【发布时间】:2023-08-22 02:13:01
【问题描述】:
我对 TimeZoneInfo.IsValidTime() 的行为感到惊讶,因为当 DateTime 设置为 DateTimeKind.Local 时,它无法正常工作
[Fact]
public void DateTimeInvalidForTimeZone()
{
TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
var testTimeUnspec = new DateTime(2020, 3, 29, 02, 01, 0, DateTimeKind.Unspecified);
var testTimeLocal = new DateTime(2020, 3, 29, 02, 01, 0, DateTimeKind.Local);
var testTimeUtc = new DateTime(2020, 3, 29, 02, 01, 0, DateTimeKind.Utc);
Assert.False(timeZone.IsInvalidTime(testTimeUtc)); //as anticipated - UTC so cannot be invalid
Assert.True(timeZone.IsInvalidTime(testTimeUnspec)); //as anticipated - the time is invalid
Assert.False(timeZone.IsInvalidTime(testTimeLocal)); //unexpected - the time is invalid
}
注意:中欧标准时间在 2020 年 3 月 29 日凌晨 02:00 转换为夏令时,因此按照当地时间的时间顺序为 01:59:58、01:59:59、03:00:00、03 :00:01。因此,02:00:00 到 02:59:59 之间的所有当地时间都是无效的。
- 对于非本地的 DateTimeKind.Local 和 TimeZoneInfo(即与计算机的时区不同)IsValidTime(DateTime) 将 DateTime 转换为 TimeZoneInfo 对象的时间并返回 false .
这表明 DateTimeKind.Local 的 DateTime 对象将始终有效,这不是我所期望或想要的。谁能解释微软实施背后的逻辑?另一个考虑 Nodatime?
的理由【问题讨论】:
-
您的当地时间无效。你期望结果是什么? DateTime 作为 UTF 格式的数字存储在计算机(和网络)中。然后,当日期显示为字符串时,Net 应用计算机的时区设置作为默认格式。当在 Net 中将日期从字符串解析为数字时,默认采用本地时间并转换为 UTF,除非字符串包含时区。
-
我希望 IsInvalidTime() 在传递无效日期时返回 TRUE,在传递有效日期时返回 FALSE。在我上次的测试中没有这样做。因此我的问题。我的测试仅在最后一次测试的 Assert.False 时通过。
-
我猜 New DateTime 正在转换为 UTC。一旦它被转换,它就不再无效。假设有人在时间转换时正在工作 2:30。这个人忘记换手表了。 Net 库只是将时间转换为 UTC 而没有任何错误并保存结果。一旦它被保存,它就不再是错误的了。正如我所说,时间始终以 UTC 格式存储。
-
如何将无效的 DateTime 转换为 UTC?如果您在 2020 年 3 月 29 日凌晨 1 点 59 分在华沙工作,并记录了它的有效时间,那么您可以将其转换为 UTC (00:59)。两分钟后,华沙的凌晨 3:01 也是有效的,因此您可以将其转换为 UTC (01:01)。但是,如果您错误地创建了一个 TimeDate(2020, 3, 29, 2, 1, 0) 来表示华沙当地时间,则无法将其转换为 UTC,因为它是无效的。
-
时间并不总是以 UTC 格式存储,但我同意这样做是个好主意。 DateTime 对象在其 Kind 属性之外没有关于其时区的信息 - 本质上是一个表明它是否为 UTC 的标志。因此,您可以创建和存储在大多数时区都有效的 TimeDate(2020, 3, 29, 2, 1, 0)。但是,如果它与华沙当地时间有关,则无效。这就是为什么我需要类似 timeZone.IsInvalidTime() 的东西 - 即传递的 DateTime 在这个特定时区是否有效?