英文:
Two Dart DateTime instances end up with different timezones in Firestore
问题
考虑在Dart(带有Flutter)中的这两个DateTime实例。
```dart
DateTime birthdate = DateTime(
int.parse(birthdateList[2]), // 1995
int.parse(birthdateList[0]), // 05
int.parse(birthdateList[1]), // 17
);
DateTime now = DateTime.now();
我的时区是东部(UTC-5)。在保存到Firestore时,尚未进行其他处理,但birthdate
具有UTC-4,now
具有UTC-5。这是如何工作的?
编辑
我在Firebase控制台中观察到这些值,如下面的截图所示。
<details>
<summary>英文:</summary>
Consider these two DateTime instances in Dart (with Flutter).
DateTime birthdate = DateTime(
int.parse(birthdateList[2]), // 1995
int.parse(birthdateList[0]), // 05
int.parse(birthdateList1), // 17
);
DateTime now = DateTime.now();
My timezone is eastern (UTC-5). When saved to Firestore, no other processing is done yet `birthdate` has UTC-4 and `now` has UTC-5. How does that work?
**Edit**
I'm observing these values in the Firebase console which is shown in the following screenshot
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/J8yLq.png
</details>
# 答案1
**得分**: 2
您观察到两个不同的时区是因为您的本地时区在这些日期之间遵守夏令时变更规则。
> 我的时区是东部时区(UTC-5)。当保存到Firestore时,没有进行其他处理,但`birthdate`有UTC-4,`now`有UTC-5。这是如何工作的?
*您的*计算机知道自己的时区和夏令时规则,并在将*不明确*的本地时间转换为绝对时间时应用这些规则。
当您为1997-05-17 00:00创建一个本地的`DateTime`对象时,没有明确指定时区,但您的计算机知道该本地时间落在夏令时观察期内。因此,它将其视为绝对时间1997-05-17 00:00 EDT(与UTC-4相同)。
同样,您的计算机知道2023-02-26属于标准时间并将其视为EST(UTC-5)。
可以轻松观察到这一点:
```dart
void main() {
var date1 = DateTime(1995, 5, 17);
var date2 = DateTime(2023, 2, 26);
print(date1); // 打印:1995-05-17 00:00:00.000
print(date2); // 打印:2023-02-26 00:00:00.000
print(date1.toUtc()); // 打印:1995-05-17 07:00:00.000Z
print(date2.toUtc()); // 打印:2023-02-26 08:00:00.000Z
print(date1.timeZoneName); // 打印:太平洋夏令时
print(date2.timeZoneName); // 打印:太平洋标准时间
}
(上面的输出是基于我的时区,即PST(UTC-8)。请注意,date1
和date2
都已经是绝对的时间点;从不明确的本地时间到绝对时间的转换发生在每个DateTime
对象创建时。
然后,您将这些绝对时间写入Firestore。Firestore内部如何存储或表示它们并不重要;它们已经是绝对的时间点。当您再次读取这些绝对时间时,因为您的计算机知道自己的夏令时规则,它知道在显示它们为本地时间时,应该将1997-05-17显示为EDT,将2023-02-26显示为EST。
(我认为在您的时区当前为EST时显示EDT时间是合适的,而不是错误。如果您为2023-03-12 12:00安排了“中午会议”,那么在观看该事件前一天时,将其显示为2023-03-12 11:00 EST会显得奇怪和混乱。查看该事件的人需要知道夏令时变更,以便知道实际发生时的本地时间是12:00 PM。)
如果您的目标是仅存储日期,不关心时间,我建议在创建绝对时间时明确指定它们与本地时区规则无关。在Dart的标准库中,您可以通过构建UTC DateTime
对象来实现这一点;没有其他内置的指定明确时区的方式。由于您不关心时间部分,可以忽略它(保持为午夜)。
英文:
You're observing two different time zones reported because your local time zone observes a Daylight Saving Time change across those dates.
> My timezone is eastern (UTC-5). When saved to Firestore, no other processing is done yet birthdate
has UTC-4 and now
has UTC-5. How does that work?
Your computer knows its own time zone and knows its own DST rules, and it applies them when converting an unqualified local time to and from an absolute time.
When you create a local DateTime
object for 1997-05-17 00:00, there is no time zone explicitly specified, and your computer knows that that local time falls within the period where DST is observed. It therefore treats it as the absolute time 1997-05-17 00:00 EDT (which is the same as UTC-4).
Likewise, your computer knows that 2023-02-26 falls within standard time and treats it as EST (UTC-5).
It's easy to observe this:
void main() {
var date1 = DateTime(1995, 5, 17);
var date2 = DateTime(2023, 2, 26);
print(date1); // Prints: 1995-05-17 00:00:00.000
print(date2); // Prints: 2023-02-26 00:00:00.000
print(date1.toUtc()); // Prints: 1995-05-17 07:00:00.000Z
print(date2.toUtc()); // Prints: 2023-02-26 08:00:00.000Z
print(date1.timeZoneName); // Prints: Pacific Daylight Time
print(date2.timeZoneName); // Prints: Pacific Standard Time
}
(The output above is for my timezone, which is PST (UTC-8).) Note that date1
and date2
are both already absolute points in time; the conversion from an unqualified local time to an absolute time happened when each DateTime
object was constructed.
You then write those absolute times to Firestore. It doesn't matter how Firestore internally stores them or represents them; they're already absolute points in time. When you read those absolute times back, because your computer knows its own DST rules, it knows to present the 1997-05-17 one as EDT and to present the 2023-02-26 as EST when showing them as local times.
(I contend that it's appropriate and not a bug to show an EDT time while your timezone is currently EST. If you scheduled "Noon meeting" for 2023-03-12 12:00 EDT, it would be weird and confusing if it were displayed as 2023-03-12 11:00 EST when viewing that event one day prior. A human viewing that would need to be aware of the DST change to know that the local time would be 12:00 PM when the event actually occurs.)
If your goal is to store just a date, and you don't care about the time, I recommend that you be explicit when creating absolute times so that they are independent of your local time zone rules. With Dart's standard library, you do that by constructing UTC DateTime
objects; there is no other built-in way to specify an explicit time zone. Since you don't care about the time, that portion can be ignored (and left as midnight).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论