Answers:
乔恩(Jon)的答案是关于TimeZone的,但我建议改用TimeZoneInfo。
我个人喜欢尽可能将事情保留在UTC中(至少在过去;将UTC存储在将来会存在潜在的问题),因此我建议采用这样的结构:
public struct DateTimeWithZone
{
private readonly DateTime utcDateTime;
private readonly TimeZoneInfo timeZone;
public DateTimeWithZone(DateTime dateTime, TimeZoneInfo timeZone)
{
var dateTimeUnspec = DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified);
utcDateTime = TimeZoneInfo.ConvertTimeToUtc(dateTimeUnspec, timeZone);
this.timeZone = timeZone;
}
public DateTime UniversalTime { get { return utcDateTime; } }
public TimeZoneInfo TimeZone { get { return timeZone; } }
public DateTime LocalTime
{
get
{
return TimeZoneInfo.ConvertTime(utcDateTime, timeZone);
}
}
}
您可能希望将“ TimeZone”名称更改为“ TimeZoneInfo”以使内容更清楚-我更喜欢自己的简称。
正是为这种使用类型创建了DateTimeOffset结构。
请参阅:http: //msdn.microsoft.com/en-us/library/system.datetimeoffset.aspx
这是创建具有特定时区的DateTimeOffset对象的示例:
DateTimeOffset do1 = new DateTimeOffset(2008, 8, 22, 1, 0, 0, new TimeSpan(-5, 0, 0));
这里的其他答案很有用,但它们没有专门介绍如何访问Pacific-在这里您可以:
public static DateTime GmtToPacific(DateTime dateTime)
{
return TimeZoneInfo.ConvertTimeFromUtc(dateTime,
TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"));
}
奇怪的是,尽管“太平洋标准时间”通常表示与“太平洋夏令时间”有所不同,但在这种情况下,它通常指太平洋时间。实际上,如果您使用FindSystemTimeZoneById
它来获取它,则可用的属性之一是bool,它告诉您该时区当前是否处于夏时制。
您可以在一个库中看到更多通用的示例,我最终根据用户向何处询问,将这些库集中在一起处理不同的TimeZone中所需的DateTime,等等:
https://github.com/b9chris/TimeZoneInfoLib.Net
这在Windows外部(例如Linux上的Mono)不起作用,因为时间列表来自Windows注册表:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\
在下面可以找到键(注册表编辑器中的文件夹图标);这些密钥的名称就是您要传递的密钥FindSystemTimeZoneById
。在Linux上,您必须使用单独的Linux标准时区定义集,但我没有对此进行充分探讨。
我用扩展方法将Jon Skeet的答案更改为Web。它还可以像魅力一样在天蓝色上工作。
public static class DateTimeWithZone
{
private static readonly TimeZoneInfo timeZone;
static DateTimeWithZone()
{
//I added web.config <add key="CurrentTimeZoneId" value="Central Europe Standard Time" />
//You can add value directly into function.
timeZone = TimeZoneInfo.FindSystemTimeZoneById(ConfigurationManager.AppSettings["CurrentTimeZoneId"]);
}
public static DateTime LocalTime(this DateTime t)
{
return TimeZoneInfo.ConvertTime(t, timeZone);
}
}
我喜欢乔恩·斯基特(Jon Skeet)的回答,但想补充一件事。我不确定Jon是否期望ctor总是在本地时区传递。但我想将其用于除本地以外的其他情况。
我正在从数据库中读取值,并且知道该数据库位于哪个时区。因此在ctor中,我将传入数据库的时区。但是,那么我想以当地时间为准。Jon的LocalTime不会返回转换为本地时区日期的原始日期。它返回转换为原始时区的日期(无论您传递给ctor的是什么)。
我认为这些属性名称可以清除它...
public DateTime TimeInOriginalZone { get { return TimeZoneInfo.ConvertTime(utcDateTime, timeZone); } }
public DateTime TimeInLocalZone { get { return TimeZoneInfo.ConvertTime(utcDateTime, TimeZoneInfo.Local); } }
public DateTime TimeInSpecificZone(TimeZoneInfo tz)
{
return TimeZoneInfo.ConvertTime(utcDateTime, tz);
}