【问题标题】:How can I infer the UTC offset from an ISO date with date-fns or any other datetime library?如何使用 date-fns 或任何其他日期时间库从 ISO 日期推断 UTC 偏移量?
【发布时间】:2022-11-17 18:54:27
【问题描述】:

目前我正在这样做:

import { parseISO, format } from 'date-fns';
import { formatInTimeZone } from 'date-fns-tz'

// e.g. chosenConnection['departure'] === "2022-08-26T03:41:25.280415+02:00"
departureParsedIso = parseISO(chosenConnection['departure'])
tz = chosenConnection['departure'].slice(-6)
formatInTimeZone(departureParsedIso, tz, 'dd.MM.yyyy')

这些出发日期总是发生在某个国家和时区,所以我当然需要在正确的时区中格式化日期,而不是在浏览器或服务器的当前时区中,这就是为什么我使用 date-fns' formatInTimeZone .

但是,我发现没有其他方法可以从 chosenConnection['departure'] 中提取时区信息,这真的很奇怪而且很老套。我发现 departureParsedIso 没有以某种方式保存该信息也很奇怪。

有没有更好、更健壮、更少反模式、更优雅的方法来做到这一点?也许与另一个日期时间库?

我也尝试用format(departureParsedIso, 'xxx') 提取偏移量,但这显然再次返回客户端或服务器的时区,而不是 ISO 字符串中编码的时区。但为什么?那么parseISO有什么用呢?

【问题讨论】:

  • 不幸的是,没有可靠的方法可以从偏移量推断出时区,因为单个偏移量通常与多个时区对齐。

标签: javascript date-fns


【解决方案1】:

您可以使用luxon 解析大量所需的数据。

在这种情况下,使用 DateTime.fromISO 并将 setZone 参数设置为 true 将创建一个 DateTime 实例固定的UTC 偏移量。

这对于以本地时间和 UTC 显示出发日期非常有用,必要时还可以显示任何其他时区(例如 CET)。

您还可以获得以分钟、小时和 HH:MM 为单位的 UTC 偏移量。

我们还可以通过查找在相关时间具有相同 UTC 偏移量的任何区域来搜索可能的 IANA 区域。当然,我们可以看到会有大量可能的匹配项,因此如果没有更多信息,我们无法找到确切的区域。

所以我们可以获得 UTC 偏移量,但不一定是日期的时区。

注意:推断的固定时区将不接受任何 DST 更改,因此在对日期进行任何操作时请注意这一点。

const { DateTime, IANAZone } = luxon;

const departure = "2022-08-26T03:41:25.280415+02:00";
const dt = DateTime.fromISO(departure, { setZone: true });

console.log('Departure (local):', dt.toFormat('yyyy-MM-dd HH:mm:ss'));
console.log('Departure (UTC):  ', dt.toUTC().toFormat('yyyy-MM-dd HH:mm:ss'));
console.log('Departure (CET):  ', dt.setZone('CET').toFormat('yyyy-MM-dd HH:mm:ss'));

console.log('Departure UTC Offset (minutes):', dt.offset);
console.log('Departure UTC Offset (hours):', dt.toFormat('Z'));
console.log('Departure UTC Offset (HH:MM):', dt.toFormat('ZZ'));

console.log('')
const allZones = Intl.supportedValuesOf('timeZone');
const possibleTimeZones = allZones.map(tz => IANAZone.create(tz)).filter(zone => zone.offset(dt) === dt.offset);
console.log('Possible timezones:', possibleTimeZones.map(zone => zone.zoneName));
.as-console-wrapper { max-height: 100% !important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/3.0.1/luxon.min.js" integrity="sha512-6ZJuab/UnRq1muTChgrVxJhSgygmL2GMLVmSJN7pcBEqJ1dWPbqN9CiZ6U3HrcApTIJsLnMgXYBYgtVkJ8fWiw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

【讨论】:

    猜你喜欢
    • 2021-12-06
    • 2020-09-30
    • 2021-06-11
    • 1970-01-01
    • 2014-02-04
    • 2016-08-29
    • 1970-01-01
    • 2021-01-29
    • 2012-08-02
    相关资源
    最近更新 更多