我如何用date-fns或任何其他日期时间库从ISO日期推断UTC偏移量?



目前我正在这样做:

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

然而,我发现它真的很奇怪和hackish,我没有找到其他的方法来提取时区信息,即偏移量,从chosenConnection['departure']。我也觉得很奇怪,departureParsedIso不知何故没有保存这些信息。

是否有更好、更健壮、更少反模式、更优雅的方法来做到这一点?在date-fns吗?或者使用另一个日期时间库?

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

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

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

这对于显示当地时间和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>

最新更新