我编写了两种扩展方法,用于将时间从本地时间转换为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;
}
我在我的应用程序中经常使用这两个,我想知道它们是否是线程安全的。另外,将这两个方法放在一个抽象类中然后让所有涉及时间操作的类继承自这个抽象类会有什么好处吗?
感谢您就此时间转换主题提出的建议。
答案 0 :(得分:3)
是的,它们是线程安全的。它们在变量命名方面是丑陋的(为什么“之前的所有”,为什么是Pascal-casing?),你应该考虑使用DateTime.SpecifyKind
,但是他们没有对共享状态做任何事情......除非TimeZoneInfo
有线程安全问题,否则应该没问题。 (TimeZoneInfo
实际上指定实例成员不保证是线程安全的,但它也被指出是不可变的。我期望它是线程安全的。)
你绝对不应该将这些作为基类放在抽象类中 - 这将是滥用继承。它真的代表了你想要专门化的一些抽象概念,是吗?扩展方法在这里是合理的。
您还应该仔细考虑非常关于如何在转换模糊或无效的情况下第一种方法中的代码行为:例如,如果时钟在凌晨1点到凌晨2点前进,当天上午1:30在该时区无效。同样,如果它从凌晨2点回到凌晨1点,那么凌晨1点半就会发生两次。检查TimeZoneInfo.GetUtcOffset
的文档,以确保在这些情况下从中返回的值是您想要的。
最后,考虑使用Noda Time替代,我的替代.NET日期/时间API(我相信)让事情变得更加清洁 - 并使您对日期/时间转换等事情的选择非常明确。
(前几天我写了一篇blog post about this very topic,关于我一直在考虑API的选择。欢迎反馈。)
答案 1 :(得分:1)
我想确保我们说的是同一个词。 Thread Safety是
如果一段代码仅以保证多个线程同时安全执行的方式操作共享数据结构,则它是线程安全的。有各种策略来制作线程安全的数据结构
如果要更改类的成员或进入的参数,请查看您的方法,它不是线程安全的唯一方法。
由于这些方法是静态的,因此您不能更改类是线程安全的方面的成员。
如果要更改进入方法的对象,则可能违反下一个线程安全性。
由于在您的代码中您没有更改变量,因此您可以在该路线上使用。您也可以通过您使用的类型来判断。由于字符串是immutable,因此它们始终是线程安全的。由于DateTime是一个线程安全的struct。