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

3

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

2019/10/01 15:30

正如您所看到的,这些字符串不包含任何时区信息。但是,我知道时间所代表的时区。

如果我在我的个人电脑上使用此C#代码,该电脑已正确设置本地时区,则时间将按预期解析。我期望将本地时间转换为UTC以插入数据库中。

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

然而,如果我在其中一个将时区设置为UTC的Docker主机上运行此代码,则时间将解析为UTC。这是有意义的,因为在使用UTC的Docker主机上,AssumeLocal将与UTC相同。
仅应用手动偏移量是不够的,因为由于夏令时的原因。而且,其中一些日志是历史性的,可以追溯到夏令时更改之前,因此即使使用算法也会很复杂,似乎应该已经解决了这个问题(即根据日期和时区确定是否处于夏令时状态,然后相应地调整为UTC)。
我想要能够显式指定时间戳的时区,并让框架同时使用给定的时区和实际日期来正确转换时间为UTC。我查看了这个问题这个问题,但它们都似乎依赖于系统本身被设置为您希望假定日期所在的时区。
第二个问题似乎开始解决假定已知时区的问题,但是响应仅使用已解析时间的GetUtcOffset来确定偏移时间的数量。这假设时间已经在所需时区中解析。

provider 设置为什么?另外,我猜你是指 DateTime.ParseExact - JuanR
这是你要找的吗?https://learn.microsoft.com/en-us/dotnet/api/system.datetime.specifykind?view=netframework-4.8 编辑:我看错了,我发现你的机器不一定在你想要的时区。然而,你仍然可以使用https://learn.microsoft.com/en-us/dotnet/api/system.timezoneinfo?view=netframework-4.8来指定一个时区。 - rainydevbs
1个回答

1

我相信你要找的是 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

1
正是我所需要的。ConvertTimeToUtc方法允许您为源指定明确的时区。谢谢。顺便说一句,我想知道它如何处理模糊时间(例如,在秋季夏令时更改期间的一小时重叠)。 - fdmillion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接