我正在尝试创建一个单元测试,以测试当机器上的时区因设置不正确而更改时的情况。
在测试中,我需要能够在非本地时区创建DateTime对象,以确保运行测试的人可以成功地这样做,而不管他们位于哪里。
从我可以从DateTime构造函数中看到,我可以将TimeZone设置为本地时区,UTC时区或未指定。
我如何创建一个日期时间与特定的时区,如PST?
您必须为此创建一个自定义对象。您的自定义对象将包含两个值:
不确定是否已经有clr提供的数据类型具有此功能,但至少TimeZone组件已经可用。
乔恩的回答谈论的是时区,但我建议使用TimeZoneInfo代替。
就我个人而言,我喜欢尽可能将内容保存在UTC中(至少对于过去;为future存储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结构正是为这种类型的使用而创建的。
下面是创建带有特定时区的DateTimeOffset对象的示例:
DateTimeOffset do1 = new DateTimeOffset(2008, 8, 22, 1, 0, 0, new TimeSpan(-5, 0, 0));
这里的其他答案是有用的,但他们不包括如何访问太平洋具体-在这里:
public static DateTime GmtToPacific(DateTime dateTime) { return TimeZoneInfo.ConvertTimeFromUtc(dateTime, TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time")); }
奇怪的是,虽然“太平洋标准时间”通常与“太平洋夏令时”的意思不同,但在这种情况下,它指的是一般的太平洋时间。事实上,如果你使用FindSystemTimeZoneById来获取它,其中一个可用的属性是bool,告诉你该时区当前是否处于夏令时。
FindSystemTimeZoneById
你可以在一个库中看到更通用的例子,我最终拼凑了一个库来处理我需要的不同时区的DateTimes,基于用户从哪里询问,等等:
https://github.com/b9chris/TimeZoneInfoLib.Net
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\
在下面你会发现键(注册表编辑器中的文件夹图标);这些键的名称是你传递给FindSystemTimeZoneById的。在Linux上,您必须使用单独的Linux标准时区定义集,对此我还没有充分探讨。
我喜欢乔恩·斯基特的回答,但我想补充一点。我不确定乔恩是否期待着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); }
我用扩展方法改变了乔恩·斯基特回答一点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); } }
使用时区类可以很容易地创建时区特定的日期。
TimeZoneInfo.ConvertTime(DateTime.Now, TimeZoneInfo.FindSystemTimeZoneById(TimeZones.Paris.Id));
尝试TimeZoneInfo.ConvertTime(dateTime, sourceTimeZone, destinationTimeZone)
TimeZoneInfo.ConvertTime(dateTime, sourceTimeZone, destinationTimeZone)
对于具有特定时区(既不是本地时区,也不是UTC时区)偏移量的日期/时间,您可以使用DateTimeOffset类:
var time = TimeSpan.Parse("9:00"); var est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time"); var nationalDateTime = new DateTimeOffset(DateTime.Today.Ticks + time.Ticks, est.BaseUtcOffset);