【问题标题】:Get time zone with UTC conversion使用 UTC 转换获取时区
【发布时间】:2019-11-23 14:51:02
【问题描述】:

我在 BST 中有系统日期。我想将其转换为 UTC。以下也是如此:

string utcDate= TimeZoneInfo.ConvertTimeToUtc(dt).ToString("dd/MM/yyyy HH:mm:ss");

我想要的是获取区域以及 UTC 中的日期。请考虑夏令时。

例如:2019-07-08T23:59:00+01:00.

【问题讨论】:

  • 如果您想了解如何让 Javascript 为用户获取本地时区,我不久前回答了一个类似的问题。 stackoverflow.com/questions/46475559/…
  • 不清楚你在问什么。如果您只想要系统日期和时间与 UTC 的偏移量,那么只需调用 DateTimeOffset.Now
  • @JasonRoner - 这个问题与 JavaScript 无关。
  • @mattJohnson - 问题是 - 我想要带有偏移的 UTC 时间
  • 2019-07-08T23:59:00+01:00 这是我想要的格式

标签: c# .net timezone utc


【解决方案1】:

一些事情:

  • 您给出的示例字符串格式2019-07-08T23:59:00+01:00ISO 8601 规范的一部分。准确地说,它是“ISO 8601 扩展格式”的“完整日期和时间表示”。也是RFC 3339定义的格式。

  • 在这种格式中,日期和时间部分表示本地时间,由时区偏移部分表示。换句话说,这些值不是 UTC,而是已经调整过。在您的示例中,2019-07-08T23:59:00 是当地时间,UTC+01:00 在当时有效。因此,相应的 UTC 时间会提前一个小时,2019-07-08T22:59:00Z

  • 您似乎在询问 UTC 日期,但偏移量包括夏令时。这是不可能的,因为 UTC 不遵守夏令时。与 UTC 的偏移量始终为零。 You can read more about UTC here.

  • UTC 本身的偏移量用Z 表示,但也可以用+00:00 表示,可以认为是“与UTC 的零偏移量”。换句话说,如果您指的是 UTC 时间,请使用 Z,如果您指的是与 UTC 一致的本地时间(例如冬季的伦敦 GMT 或冰岛等),请使用 @987654332 @。

  • 在您的问题中,您说您想要 UTC 的系统时间和偏移量。我将假设“系统时间”是指系统上时钟的当前时间。这是由DateTime.UtcNowDateTimeOffset.UtcNow 提供的。这些返回 DateTimeDateTimeOffset 结构 - 而不是字符串。既然你想要一个特定格式的字符串,那么你应该先询问当前时间,然后将其格式化为带有ToString的字符串:

    using System.Globalization;
    

    ...

    string a = DateTime.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:ssK", CultureInfo.InvariantCulture);
    // output example: "2019-07-08T22:59:00Z"
    
    string b = DateTimeOffset.UtcNow.ToString("yyyy-MM-dd'T'HH:mm:sszzz", CultureInfo.InvariantCulture);
    // output example: "2019-07-08T22:59:00+00:00"
    
  • 如果您真正想要的是 本地 时间,这样偏移量将是冬季的 +00:00 和夏季的 +01:00(在英国),然后使用 Now而不是UtcNow。这给出了运行代码的计算机所在时区的本地时间。

    string c = DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ssK", CultureInfo.InvariantCulture);
    // output example: "2019-07-08T23:59:00+01:00"
    
    string d = DateTimeOffset.Now.ToString("yyyy-MM-dd'T'HH:mm:sszzz", CultureInfo.InvariantCulture);
    // output example: "2019-07-08T23:59:00+01:00"
    
  • 如果您确实想要英国的时间而不管本地计算机的时区是什么,那么您必须首先获取 UTC 时间,然后在创建字符串之前将其转换为英国时间。

    TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
    string e = TimeZoneInfo.ConvertTime(DateTime.UtcNow, tzi).ToString("yyyy-MM-dd'T'HH:mm:ssK", CultureInfo.InvariantCulture);
    // output example: "2019-07-08T23:59:00"
    
    string f = TimeZoneInfo.ConvertTime(DateTimeOffset.UtcNow, tzi).ToString("yyyy-MM-dd'T'HH:mm:sszzz", CultureInfo.InvariantCulture);
    // output example: "2019-07-08T23:59:00+01:00"
    

    在示例e 中,请注意DateTime 不能存储任意偏移作为时区转换的结果,因此您将DateTimeKind.Unspecified 分配给Kind 属性,这导致没有偏移在字符串表示中。因此大多数时候你应该使用DateTimeOffset(例如f)来代替。

    另外,请注意"GMT Standard Time" 的时区 ID 是在 Windows 平台上用于英国的正确 ID。它在适当时在 GMT 和 BST 之间正确切换。如果您在非 Windows 平台(Linux、OSX 等)上运行 .NET Core,则应改用 "Europe/London"。或者,如果您想编写与平台无关的代码,那么您可以使用我的 TimeZoneConverter 库,它允许您提供任何一种形式并在任何平台上运行。

  • 在您的代码示例中,您没有调用任何“现在”函数,而是提供了一个 dt 变量。假设这是一个DateTime,调用TimeZoneInfo.ConvertTimeToUtc 的结果将取决于该变量的Kind 属性。如果是DateTimeKind.Utc,则不执行转换。如果是DateTimeKind.Local DateTimeKind.Unspecified,则该值将从计算机的本地时区转换为UTC。

  • 最后,请记住,在与国际观众交谈时,时区缩写可能会模棱两可。我可以通过“BST”推断出您的意思是英国夏令时,但这只是因为您在问题中显示了+01:00 偏移量。 “BST”也可以代表“孟加拉国标准时间”(+06:00)或“布干维尔标准时间”(+11:00)。

【讨论】:

  • 感谢您的详细解释。我使用了下面的代码并且对我来说工作正常: string zoneDate = dt.ToString("yyyy-MM-dd'T'HH:mm:ss") + dt.ToString("zzz");虽然这很好,但代码在夏令时的第 2 天不起作用。例如:在 2020 年,日光从 3 月 29 日凌晨 1 点开始。该代码从 4 月 1 日起增加了 +1 小时。你能帮我理解为什么它不适用于 29-31 虽然夏令时有效。
【解决方案2】:

我猜你可以这样做:

var dt = DateTime.Now;
string utcDate = dt.ToUniversalTime().ToString("dd/MM/yyyy HH:mm:ss") +
                 dt.ToString(" zzz");

输出:(我在 EET)

14/07/2019 20:02:17 +02:00

但请注意,这可能会让人们感到困惑。标准方式是时区遵循本地日期,而不是通用日期。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-12
    • 2016-10-10
    • 2018-02-24
    • 1970-01-01
    • 2017-11-07
    • 2021-12-24
    • 2011-09-16
    • 2020-03-21
    相关资源
    最近更新 更多