通过 UTC 转换获取时区

Get time zone with UTC conversion

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

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

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

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

我想你可以这样做:

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

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

几件事:

  • 你给出的字符串格式,2019-07-08T23:59:00+01:00ISO 8601 specification. To be precise, it is the "complete date and time of day representation" of the "ISO 8601 Extended Format". It also the format defined by 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 对齐的本地时间(例如冬季伦敦的格林威治标准时间,或冰岛等),请使用+00:00.

  • 在你的问题中,你说你想要 UTC 的系统时间和偏移量。我假设“系统时间”是指系统时钟的当前时间。这是由 DateTime.UtcNowDateTimeOffset.UtcNow 提供的。这些 return 要么是 DateTime 要么是 DateTimeOffset 结构——不是字符串。既然你想要一个特定格式的字符串,那么你应该首先询问当前时间,然后将其格式化为带有 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"
    
  • 如果您真正想要的是 local 时间,那么冬天的偏移量是 +00:00,而冬天的偏移量是 +01:00在夏天(在英国),然后使用 Now 而不是 UtcNow。这给出代码为 运行ning.

    的计算机时区的本地时间
    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 之间正确切换。如果您在 non-Windows 平台(Linux、OSX 等)上 运行ning .NET Core,那么您应该改用 "Europe/London"。或者,如果您想编写 platform-neutral 的代码,那么您可以使用我的 TimeZoneConverter 库,它允许您在任何平台上提供任何一种形式和 运行。

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

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