C# 在 DateTime.ParseExact 中手动指定时区

C# Manually specify a timezone in DateTime.ParseExact

我有一个包含 date/time 字符串的日志文件,格式如下:

2019/10/01 15:30

如您所见,字符串不包含任何时区信息。但是,我确实知道时间所在的时区。

如果我在自己的 PC 上使用此 C# 代码,并且本地时区设置正确,则时间会按预期进行解析。我希望将本地时间转换为 UTC 以插入数据库。

Time.ParseExact("2019/10/01 15:30", "yyyy/MM/dd HH:mm", provider, DateTimeStyles.AdjustToUniversal & DateTimeStyles.AssumeLocal);

但是,如果我 运行 我的其中一台 Docker 主机上的此代码(其时区设置为 UTC),时间将被解析为 UTC。这是有道理的,因为在 Docker 主机上使用 UTC AssumeLocal 将与 UTC 相同。

由于夏令时,仅应用手动偏移是不够的。此外,其中一些日志是历史记录,可以追溯到 DST 更改之前,因此即使使用算法也会很复杂,而且看起来应该已经解决了(即给定日期和时区,确定它是否在 DST 中或不然后相应地调整为 UTC)

我想要做的是明确指定时间戳的 timezone 并让框架同时使用给定的时区和实际日期来正确转换时间到协调世界时。我看过 this question and this question,但它们似乎都取决于系统本身被设置为您想要假定日期所在的时区。

第二个问题似乎确实开始解决假定已知时区的问题,但随后的响应只是在解析的时间上使用 GetUtcOffset 来确定偏移时间的时间量。这假定时间已经在所需时区中解析。

我相信你要找的是TimeZoneInfo

使用 TimeZoneInfo,您可以从 TimeZoneInfo.FindSystemTimeZoneById.

获取您需要的信息

这些 ID 基于操作系统,但只要您的所有容器都在 Linux(例如)上,您就可以使用它来获取 UTC 时间进行存储。您提到您知道您的字符串所在的时区,因此您可能需要将其转换为 TimeZoneInfo 可读的 ID。

取自TimeZoneInfo.FindSystemTimeZoneById

的代码示例
using System;

public class Example
{
   public static void Main()
   {
      // Get time in local time zone 
      DateTime thisTime = DateTime.Now;
      Console.WriteLine("Time in {0} zone: {1}", TimeZoneInfo.Local.IsDaylightSavingTime(thisTime) ?
                        TimeZoneInfo.Local.DaylightName : TimeZoneInfo.Local.StandardName, thisTime);
      Console.WriteLine("   UTC Time: {0}", TimeZoneInfo.ConvertTimeToUtc(thisTime, TimeZoneInfo.Local));
      // Get Tokyo Standard Time zone
      TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById("Tokyo Standard Time");
      DateTime tstTime = TimeZoneInfo.ConvertTime(thisTime, TimeZoneInfo.Local, tst);      
      Console.WriteLine("Time in {0} zone: {1}", tst.IsDaylightSavingTime(tstTime) ?
                        tst.DaylightName : tst.StandardName, tstTime);
      Console.WriteLine("   UTC Time: {0}", TimeZoneInfo.ConvertTimeToUtc(tstTime, tst));
   }
}

// The example displays output like the following when run on a system in the
// U.S. Pacific Standard Time zone:
//       Time in Pacific Standard Time zone: 12/6/2013 10:57:51 AM
//          UTC Time: 12/6/2013 6:57:51 PM
//       Time in Tokyo Standard Time zone: 12/7/2013 3:57:51 AM
//          UTC Time: 12/6/2013 6:57:51 PM