Dart DateTime.parse timeZoneOffset 始终为 0

问题描述

DateTime.parse 创建的 DateTime 似乎总是为“timeZoneOffset”返回 0

  1. 在这里创建了一个非 UTC 时区的 ISO8601 字符串:https://timestampgenerator.com/1610010318/+09:00

  2. 我将该字符串传递给 DateTime.parse:

  DateTime date = DateTime.parse("2021-01-07T18:05:18+0900");
  1. 问题:当我期待 +0900 时,timeZoneOffset 为 0。
  print(date.timeZoneOffset);  --> 0:00:00.000000
  print(date.timeZoneName); --> UTC 
  print(date); --> 2021-01-07 09:05:18.000Z

Dart DateTime 文档(https://api.dart.dev/stable/2.10.4/dart-core/DateTime/parse.html):

结果始终为本地时间或 UTC。如果指定了 UTC 以外的时区偏移量,则时间将转换为等效的 UTC 时间。

为什么 timeZoneOffset 是 0?我需要传递给 DateTime.parse 什么字符串才能让它以本地时间存储时间而不是将其转换为等效的 UTC 时间?

解决方法

Dart SDK 并没有真正处理不同的时区,这就是 parse 想要本地时区(运行程序的系统上的时区)或 UTC 的原因。

如果您尝试在没有任何时区信息的情况下解析时间戳,Dart 将假定时间在本地时区(我在丹麦使用浪漫标准时区):

void main() {
  print(DateTime.parse("2021-01-07T18:05:18").timeZoneName); // Romance Standard Time
  print(DateTime.parse("2021-01-07T18:05:18+0900").timeZoneName); // UTC
}

您可以通过在时间戳上使用 .toLocal() 将您的 UTC 时间戳转换为本地时间。但同样,这只会将其转换为您自己系统上的时区,而不是您解析时的时区:

void main() {
  print(DateTime.parse("2021-01-07T18:05:18+0900").toLocal().timeZoneName); // Romance Standard Time
}

如果你想用时区数据处理时间,你应该查看包时区:https://pub.dev/packages/timezone

关于保存时区偏移的一些注意事项

您应该意识到,在大多数情况下,以一种可以再次获得原始偏移量的形式来节省时间并没有什么意义。问题是大多数国家/地区都有 DST 等规则,或者用户正在旅行,并且确实希望系统正确处理时间。

因此在很多情况下,用户并不真的希望再次获得相同的偏移量,而是希望时间与基于当前位置和时间的当前偏移量一致。

时区包例如不允许您解析时间戳并将偏移量与其一起保存(因为偏移量与位置不同)。相反,它希望您指定时间戳用于的位置,以便它可以计算该位置的当前偏移量。

因此,总的来说,我建议您始终将时间保存为 UTC 存储时间。当要使用数据时,您应该有一些方法可以知道接收器的位置(例如,以某种形式的配置文件询问用户)并使用 timezone 包将时间转换为该位置。如果应用程序在数据接收方拥有的设备上运行,您可以使用 .toLocale() 将 UTC 转换为本地时间。