目前我正在这样做:
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>