Dart DateTime.parse timeZoneOffset 始终为 0

use*_*306 5 datetime iso dart flutter

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");
Run Code Online (Sandbox Code Playgroud)
  1. 问题:当我期望 +0900 时,timeZoneOffset 为 0。
  print(date.timeZoneOffset);  --> 0:00:00.000000
  print(date.timeZoneName); --> UTC 
  print(date); --> 2021-01-07 09:05:18.000Z
Run Code Online (Sandbox Code Playgroud)

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

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

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

jul*_*101 9

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
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

您应该意识到,在大多数情况下,以可以再次获取原始偏移量的形式保存时间并没有真正意义。问题是大多数国家/地区都有夏令时等规则,或者用户正在旅行并且确实希望系统能够正确处理时间。

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

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

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