白衣非少年
如果您有一个始终希望使用 date-fns 解析为 CST(美国中央标准时间)的字符串,则可以包含 date-fns-tz 并在解析时设置时区(我假设 ISO 8601 松散格式没有时区). 请注意,为避免夏令时,您必须选择全年使用 UTC-6 的位置,例如加拿大/萨斯喀彻温省。// Setupvar {parse} = require('date-fns');var {zonedTimeToUtc, utcToZonedTime, format } = require('date-fns-tz');// Parse using location for offsetlet loc = 'Canada/Saskatchewan';let s = '2020-08-14 13:05:52';let fIn = 'yyyy-MM-dd HH:mm:ss';let utcDate = zonedTimeToUtc(s, loc);// Show local equivalentconsole.log(utcDate);这让您在某种程度上受到萨斯喀彻温省管理员的摆布,他们可能会更改偏移量或引入 DST。另一种方法是将您想要的确切偏移量附加到时间戳并将其包含在解析标记中:// Parse using string for offsetlet tz = '-06';let utcDate2 = parse(s + ' ' + tz, fIn + ' X', new Date());// Show local equivalent, should be same as aboveconsole.log(utcDate2);第二种方法的优点是它不需要 date-fns-tz,并且您不会受制于萨斯喀彻温省偏移量(或任何其他 IANA 位置的偏移量)的历史或未来更改。显然有一个正在开发的 UTC 模块允许设置特定的偏移量,如 -6,而不是使用 IANA 位置(无法找到该评论 atm 的链接)。此时字符串已被解析为 GMT-6,但仍然只是一个普通的日期(即只是一个时间值,不知道与原始字符串关联的时区)。一旦你有了日期,你就可以将它显示为 CST 用于输出。要在调用format时使用 IANA 位置作为偏移量,您必须使用来自 date-fns-tz 的格式,而不是普通的 date-fns,否则它只会使用主机系统偏移量。请注意,格式调用中的值只是设置用于偏移字符串的值,它不会对实际日期和时间做任何事情,该调整已由utcToZonedTime应用。// Adjust to CSTlet dCST = utcToZonedTime(utcDate2, loc);// Format strings:let fOut1 = 'yyyy-MM-dd HH:mm:ss XXX'; // -0600let fOut2 = 'yyyy-MM-dd HH:mm:ss z'; // CST// Format using locationconsole.log(format(dCST, fOut1, {timeZone: loc}));console.log(format(dCST, fOut2, {timeZone: loc}));我更喜欢 -0600 版本,因为它避免了 DST 是否被观察到的问题(并且实际上是代码在做什么)。此外,在“z”版本中,您可能会获得偏移量或时区名称(可能取决于主机默认语言和位置,我认为这是使用Intl.DateTimeFormat的 date-fns-tz 的一个怪癖)。您还可以使用如下格式字符串手动添加时区:let fOut = 'yyyy-MM-dd HH:mm:ss \'-0600\'';这将产生如下输出:"2020-08-14 13:05:52 GMT-0600"我认为没有任何方法可以在不将其包含在调用中的情况下为解析和格式化设置特定的偏移量,如“-0600”。我认为 moment.js 和 luxon 允许它。为了完整起见,这里有一些您可以在npm.runkit.com上运行的代码,因为当前 date-fns 版本没有允许代码在此处运行的 CDN。var {parse} = require('date-fns');var {zonedTimeToUtc, utcToZonedTime, format } = require('date-fns-tz');// Parse using location for offsetlet loc = 'Canada/Saskatchewan';let s = '2020-08-14 13:05:52';let fIn = 'yyyy-MM-dd HH:mm:ss';let utcDate = zonedTimeToUtc(s, loc);// Show local equivalentconsole.log(utcDate);// Parse using string for offsetlet tz = '-06';let utcDate2 = parse(s + ' ' + tz, fIn + ' X', new Date());// Show local equivalent, should be same as aboveconsole.log(utcDate2);// Format using location:let fOut1 = 'yyyy-MM-dd HH:mm:ss XXX'; // -0600let fOut2 = 'yyyy-MM-dd HH:mm:ss z'; // CSTlet dCST = utcToZonedTime(utcDate2, loc);console.log(format(dCST, fOut1, {timeZone: loc}));console.log(format(dCST, fOut2, {timeZone: loc}));