【问题标题】:How to convert DateTime to NodaTime with timezone?如何使用时区将 DateTime 转换为 NodaTime?
【发布时间】:2016-09-04 08:21:33
【问题描述】:

出于显示目的,我尝试使用时区转换将给定的 DateTime 转换为 NodaTime。即使有 3 次不同的尝试,我也无法让 NodaTime 给我预期的结果。这是一些示例代码(给定 DateTime dt):

//option 1
NodaTime.DateTimeZone zone = NodaTime.DateTimeZoneProviders.Tzdb ["Africa/Johannesburg"];
NodaTime.LocalDateTime localDateTime = NodaTime.LocalDateTime.FromDateTime(dt);
NodaTime.ZonedDateTime zonedDateTime = localDateTime.InZoneStrictly(zone);
string str = zonedDateTime.ToString("H:mm:ss", System.Globalization.CultureInfo.InvariantCulture);

Debug.LogFormat ("TimeZone: {0}", zone);
Debug.LogFormat ("Option 1: {0} local: {1} zoned: {2}", str, localDateTime, zonedDateTime);

//option 2
NodaTime.Instant instant = NodaTime.Instant.FromDateTimeUtc (dt.ToUniversalTime ());
zonedDateTime = instant.InZone(zone);
str = zonedDateTime.ToString("H:mm:ss", System.Globalization.CultureInfo.InvariantCulture);

Debug.LogFormat ("Option 2: {0} instant: {1} zoned: {2}", str, instant, zonedDateTime);

//option 3
DateTime epochStart = new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
long epochSeconds = (long)(dt.ToUniversalTime()- epochStart).TotalSeconds;
instant = NodaTime.Instant.FromSecondsSinceUnixEpoch (epochSeconds);
zonedDateTime = instant.InZone(zone);
str = zonedDateTime.ToString("H:mm:ss", System.Globalization.CultureInfo.InvariantCulture);

Debug.LogFormat ("Option 3: {0} epoch: {1} instant: {2} zoned: {3}", str, epochSeconds, instant, zonedDateTime);

在南非以外的某个国家运行此程序(例如在我所在的以色列)为选项 2 和 3 生成正确的时间。当我在南非本身运行它时,它不行,时间差一小时。这是示例输出(正确的是“17:55”值,例如“我的电脑”的选项 2 和 3)。当然,罪魁祸首可能是时区或夏令时差异,而不是实际地理位置:

-----我的电脑(伪造 SA)-----

时区:非洲/约翰内斯堡

选项 1:18:55:41 本地:09/01/2016 18:55:41 分区: 2016-09-01T18:55:41 非洲/约翰内斯堡 (+02)

选项 2:17:55:41 瞬间:2016-09-01T15:55:41Z 分区: 2016-09-01T17:55:41 非洲/约翰内斯堡 (+02)

选项 3:17:55:41 纪元:1472745341 瞬间:2016-09-01T15:55:41Z 分区:2016-09-01T17:55:41 非洲/约翰内斯堡 (+02)

----他们的电脑(在南非)----- 时区:非洲/约翰内斯堡

选项 1:18:55:41 本地:2016 年 9 月 1 日下午 6:55:41 分区: 2016-09-01T18:55:41 非洲/约翰内斯堡 (+02)

选项 2:18:55:41 瞬间:2016-09-01T16:55:41Z 分区: 2016-09-01T18:55:41 非洲/约翰内斯堡 (+02)

选项 3:18:55:41 纪元:1472748941 瞬间:2016-09-01T16:55:41Z 分区:2016-09-01T18:55:41 非洲/约翰内斯堡 (+02)

如何确保我的 DateTime -> NodaTime 输出一致,无论当前位置如何?

【问题讨论】:

  • 不清楚您在此处期望是什么。一小时的休息时间是怎么回事?如果您的DateTime 实际上是指定时区的当地时间,那么第一个选项对我来说看起来不错,但不知道您期望什么不同,这很难提供帮助。 (如果您显示具有预期和实际输出的minimal reproducible example 会有所帮助...)
  • 重读了这个(目前还不是很清楚,IMO - 特别是因为它使用了一些我们不知道的DateUtils 类)我怀疑问题是代码正在运行的计算机上。如果他们弄乱了时区设置或没有最新的时区信息,那么您对此无能为力。选项 1 使用 Noda 时区转换 - 因此假设您使用相同的时区数据版本,将保持一致。
  • 谢谢...我摆脱了 DateUtils。 SA 的当前时间应该比我在以色列的当地时间晚 1 小时
  • 您在以色列的当地时间与什么有关?我不希望在您显示的输出中的任何地方看到这一点。目前还不清楚您期望会有什么不同,但同样,minimal reproducible example 将有助于澄清......
  • 您能否建议如何使上述内容更精简、完整或可验证?唯一缺少的部分是如何提供 DateTime 时间戳(因为它是从第三方库计算的)。请注意,unix 时间戳本身关闭了一个小时。也许这就是这里的实际问题 - DateTime 是(错误地)预先调整的......如果 unix 时间戳不同,那么输出的结果肯定会不同......

标签: c# datetime nodatime


【解决方案1】:

我会集中回答你的这部分问题:

如何确保我的 DateTime -> NodaTime 输出一致,无论当前位置如何?

您的代码中有几个地方,您在 DateTime 对象上调用 .ToUniversalTime()。当您这样做时,操作取决于分配给对象的Kind 属性的DateTimeKind 值。每the MSDN docs

因此,只要Kind 不是DateTimeKind.Utc,那么输入值就会被解释为本地时区,因此转换为 UTC 会受到计算机上本地时区的影响它在哪里运行,导致输出不一致。

如果您不希望您的代码在两台计算机之间的本地时区不同时给出不同的结果,那么您不应该使用这种方法。这就是代码中选项 #2 和选项 #3 给出不同结果的原因。

至于选项#1,目前尚不清楚您实际上要做什么。您断言输入 dt 位于 Africa/Johannesburg 时区,但您从不要求任何类型的转换。您只是发出您传入的相同本地值。如果您打算从 UTC 转换为南非,反之亦然,那么您需要在问题中更清楚地解释这一点。事实上,我无法说出你真正想要它做什么。

【讨论】:

    猜你喜欢
    • 2015-02-26
    • 1970-01-01
    • 2019-08-26
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多