gpt4 book ai didi

c# - 安全地比较本地和通用日期时间

转载 作者:IT王子 更新时间:2023-10-29 03:59:02 25 4
gpt4 key购买 nike

我刚刚注意到 DateTime 比较似乎有一个荒谬的缺陷。

DateTime d = DateTime.Now;
DateTime dUtc = d.ToUniversalTime();

d == dUtc; // false
d.Equals(dUtc); //false
DateTime.Compare(d, dUtc) == 0; // false

如果一个是 DateTimeKind.Local,一个是 DateTimeKind.UTC,那么 DateTimes 上的所有比较操作似乎都无法进行任何类型的智能转换。除了始终将比较中涉及的两者都转换为 utc 时间之外,是否有更好的可靠比较日期时间的方法?

最佳答案

当您调用 .Equal.Compare 时,会在内部比较值 .InternalTicks,这是一个 ulong 没有它的前两位。此字段不相等,因为它已调整几个小时以表示世界时的时间:当您调用ToUniversalTime() 时,它调整 具有当前系统本地时区设置偏移量的时间。

您应该这样看:DateTime 对象表示未命名时区的时间,但不是世界时加时区。时区是本地(您系统的时区)或 UTC。您可能认为这是缺少 DateTime 类,但从历史上看,它已实现为“自 1970 年以来的滴答数”,并且不包含时区信息。

转换到另一个UTC时,时间是——而且应该——调整。这可能就是微软选择使用方法而不是属性的原因,以强调在转换为 UTC 时会采取操作。

最初我在这里写道,比较结构并且 System.DateTime.Kind 的标志不同。这不是真的:不同的是刻度的数量:

t1.Ticks == t2.Ticks;       // false
t1.Ticks.Equals(t2.Ticks); // false

要安全地比较两个日期,您可以将它们转换为同一类型。如果您在比较之前将任何日期转换为世界标准时间,您将得到您想要的结果:

DateTime t1 = DateTime.Now;
DateTime t2 = someOtherTime;
DateTime.Compare(t1.ToUniversalTime(), t2.ToUniversalTime()); // 0
DateTime.Equals(t1.ToUniversalTime(), t2.ToUniversalTime()); // true

在不改变本地时间的情况下转换为UTC时间

您还可以覆盖DateTimeKind,而不是转换到UTC(并且在此过程中保持时间相同,但滴答数不同) 并将其设置为 UTC(这改变了时间,因为它现在是 UTC,但它比较相等,因为刻度数相等)。

var t1 = DateTime.Now
var t2 = DateTime.SpecifyKind(t1, DateTimeKind.Utc)
var areEqual = t1 == t2 // true
var stillEqual = t1.Equals(t2) // true

我猜 DateTime 是那些罕见的类型之一,它们可以按位不相等,但比较相等,或者可以按位相等(时间部分)但比较不相等。

.NET 6 中的变化

在 .NET 6.0 中,我们现在有 TimeOnlyDateOnly .您可以使用它们来存储“只是一天中的时间”“只是一年中的日期”。将这些组合在一个结构中,您将拥有一个没有原始 DateTime 历史问题的日期和时间结构。

备选方案

在 .NET 中很难正确使用 DateTimeTimeZoneInfo、闰秒、日历、移动时区、持续时间等。我个人比较喜欢NodaTime由 Jon Skeet 编写,它以有意义且明确的方式将控制权交还给程序员。

This insightful post by Jon Skeet explains深入探讨程序员在仅以 UTC 格式存储所有内容时试图规避所有 DateTime 问题时可能面临的麻烦。

来源背景信息

如果你勾选the DateTime struct in the .NET source ,您会发现一条注释,解释了最初(在 .NET 1.0 中)DateTime 只是刻度数,但后来他们添加了存储通用时间或本地时间的功能。但是,如果您序列化,此信息将丢失。

这是源代码中的注释:

    // This value type represents a date and time.  Every DateTime
// object has a private field (Ticks) of type Int64 that stores the
// date and time as the number of 100 nanosecond intervals since
// 12:00 AM January 1, year 1 A.D. in the proleptic Gregorian Calendar.
//
// Starting from V2.0, DateTime also stored some context about its time
// zone in the form of a 3-state value representing Unspecified, Utc or
// Local. This is stored in the two top bits of the 64-bit numeric value
// with the remainder of the bits storing the tick count. This information
// is only used during time zone conversions and is not part of the
// identity of the DateTime. Thus, operations like Compare and Equals
// ignore this state. This is to stay compatible with earlier behavior
// and performance characteristics and to avoid forcing people into dealing
// with the effects of daylight savings. Note, that this has little effect
// on how the DateTime works except in a context where its specific time
// zone is needed, such as during conversions and some parsing and formatting
// cases.

关于c# - 安全地比较本地和通用日期时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6930489/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com