我有一个日志文件,其中包含格式如下的日期/时间字符串:
2019/10/01 15:30
如您所见,字符串不包含任何时区信息。但是,我确实知道表示时间的时区。
如果我在自己的电脑上使用此 C# 代码,并且本地时区设置正确,则会按预期解析时间。我希望将本地时间转换为 UTC 以插入数据库。
Time.ParseExact("2019/10/01 15:30", "yyyy/MM/dd HH:mm", provider, DateTimeStyles.AdjustToUniversal & DateTimeStyles.AssumeLocal);
但是,如果我在我的一个 Docker 主机上运行此代码,该主机的时区设置为 UTC,则时间将解析为 UTC。这是有道理的,因为在使用 UTC 的 Docker 主机上,AssumeLocal
将与 UTC 相同。
由于夏令时,仅应用手动偏移是不够的。此外,其中一些日志是历史日志,可以追溯到 DST 更改之前,因此即使使用算法也会很复杂,而且似乎应该已经解决了(即给定日期和时区,确定它是否在 DST 中,然后相应地调整为 UTC(
我希望能够做的是明确指定时间戳的时区,并让框架同时使用给定的时区和实际日期将时间正确转换为 UTC。我已经看过这个问题和这个问题,但它们似乎都取决于系统本身是否设置为您要假设日期所在的时区。
第二个问题似乎确实开始解决假设已知时区的问题,但是响应只是使用解析时间的GetUtcOffset
来确定偏移时间的时间量。这假设时间已在所需时区中解析。
我相信你要找的是TimeZoneInfo。
使用 TimeZoneInfo,您可以从 TimeZoneInfo.FindSystemTimeZoneById 获取所需的信息。
这些 ID 基于操作系统,但只要您的所有容器都在 Linux 上(例如(,您就可以使用它来获取 UTC 存储时间。您提到您知道字符串所在的时区,因此您可能需要一些东西来将其转换为 TimeZoneInformation 可读的 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