我编写了两个扩展方法来将时间从本地时间转换为 UTC 时间并返回。这就是我所拥有的:
public static DateTime ConvertUserTimeToUTCTime(this DateTime TheUserTime, string TheTimezoneID)
{
TheUserTime = new DateTime(TheUserTime.Year, TheUserTime.Month,
TheUserTime.Day, TheUserTime.Hour, TheUserTime.Minute,
TheUserTime.Second, DateTimeKind.Local);
TimeZoneInfo TheTZ = TimeZoneInfo.FindSystemTimeZoneById(TheTimezoneID);
TimeSpan TheOffset = TheTZ.GetUtcOffset(TheUserTime);
DateTimeOffset TheUTCTimeOffset = new DateTimeOffset(
TheUserTime, TheOffset).ToUniversalTime();
DateTime TheUTCTime = new DateTime(TheUTCTimeOffset.Year,
TheUTCTimeOffset.Month, TheUTCTimeOffset.Day, TheUTCTimeOffset.Hour,
TheUTCTimeOffset.Minute, 0, DateTimeKind.Utc);
return TheUTCTime;
}
public static DateTime ConvertUTCTimeToUserTime(this DateTime TheUTCTime,
string TheTimezoneID)
{
TimeZoneInfo TheTZ = TimeZoneInfo.FindSystemTimeZoneById(TheTimezoneID);
DateTime UTCTime = new DateTime(TheUTCTime.Year, TheUTCTime.Month,
TheUTCTime.Day, TheUTCTime.Hour, TheUTCTime.Minute, 0, DateTimeKind.Utc);
DateTime TheUserTime = TimeZoneInfo.ConvertTime(UTCTime, TheTZ);
return TheUserTime;
}
Run Code Online (Sandbox Code Playgroud)
我在我的应用程序中经常使用这两个,我想知道它们是否是线程安全的。另外,将这两个方法放在一个抽象类中,然后让所有涉及时间操作的类继承这个抽象类会有什么好处吗?
感谢您对此时间转换主题的建议。
是的,它们是线程安全的。它们在变量命名方面很丑陋(为什么在所有内容之前都使用“The”,以及为什么使用 Pascal 命名法?),并且您应该考虑使用DateTime.SpecifyKind,但它们不会对共享状态执行任何操作...除非TimeZoneInfo存在线程安全问题,应该没问题。(TimeZoneInfo实际上指定实例成员不保证是线程安全的,但也指出它是不可变的。我希望它是线程安全的。)
您绝对不应该将它们放在抽象类中作为基类 - 这将是对继承的滥用。它并不真正代表您想要专门研究的某些抽象概念,不是吗?扩展方法在这里是合理的。
您还应该非常仔细地考虑您希望第一个方法中的代码在转换不明确或无效的情况下如何表现:例如,如果时钟在凌晨 1 点前进到凌晨 2 点,那么凌晨 1:30 在该时区是无效的在那一天。同样,如果从凌晨 2 点返回到凌晨 1 点,则凌晨 1:30 会出现两次。检查文档以TimeZoneInfo.GetUtcOffset确保从它返回的值是您在这些情况下想要的值。
最后,考虑使用Noda Time,这是我的替代 .NET 日期/时间 API,(我相信)它可以使事情变得更加干净 - 并使您对日期/时间转换等事情的选择非常明确。
(前几天我写了一篇关于这个主题的博客文章,内容涉及我一直在考虑的 API 的选择。欢迎反馈。)