在c#中的特定时区创建日期时间

时间:2022-10-29 11:17:53

I'm trying to create a unit test to test the case for when the timezone changes on a machine because it has been incorrectly set and then corrected.

我正在尝试创建一个单元测试来测试机器上时区更改的情况,因为它已被错误设置然后更正。

In the test I need to be able to create DateTime objects in a none local time zone to ensure that people running the test can do so successfully irrespective of where they are located.

在测试中,我需要能够在非本地时区创建DateTime对象,以确保运行测试的人员无论身在何处都能成功完成。

From what I can see from the DateTime constructor I can set the TimeZone to be either the local timezone, the UTC timezone or not specified.

从我从DateTime构造函数中可以看到,我可以将TimeZone设置为本地时区,UTC时区或未指定。

How do I create a DateTime with a specific timezone like PST?

如何使用PST等特定时区创建DateTime?

6 个解决方案

#1


172  

Jon's answer talks about TimeZone, but I'd suggest using TimeZoneInfo instead.

Jon的回答谈到了TimeZone,但我建议使用TimeZoneInfo。

Personally I like keeping things in UTC where possible, so I'd suggest a structure like this:

就个人而言,我喜欢在可能的情况下保留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);         }    }        }

You may wish to change the "TimeZone" names to "TimeZoneInfo" to make things clearer - I prefer the briefer names myself.

您可能希望将“TimeZone”名称更改为“TimeZoneInfo”以使事情更清晰 - 我更喜欢自己的名字。

#2


41  

The DateTimeOffset structure was created for exactly this type of use.

DateTimeOffset结构是为这种类型的使用而创建的。

See:http://msdn.microsoft.com/en-us/library/system.datetimeoffset.aspx

Here's an example of creating a DateTimeOffset object with a specific time zone:

以下是使用特定时区创建DateTimeOffset对象的示例:

DateTimeOffset do1 = new DateTimeOffset(2008, 8, 22, 1, 0, 0, new TimeSpan(-5, 0, 0));

DateTimeOffset do1 = new DateTimeOffset(2008,8,22,1,0,0,new TimeSpan(-5,0,0));

#3


29  

The other answers here are useful but they don't cover how to access Pacific specifically - here you go:

这里的其他答案很有用,但它们没有涵盖如何专门访问太平洋 - 在这里你去:

public static DateTime GmtToPacific(DateTime dateTime){    return TimeZoneInfo.ConvertTimeFromUtc(dateTime,        TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"));}

Oddly enough, although "Pacific Standard Time" normally means something different from "Pacific Daily Time," in this case it refers to Pacific time in general. In fact, if you use FindSystemTimeZoneById to fetch it, one of the properties available is a bool telling you whether that timezone is currently in daylight savings or not.

奇怪的是,虽然“太平洋标准时间”通常意味着与“太平洋日报时间”不同,但在这种情况下,它指的是太平洋时间。实际上,如果你使用FindSystemTimeZoneById来获取它,那么可用的一个属性是bool,告诉你该时区目前是否在夏令时中。

You can see more generalized examples of this in a library I ended up throwing together to deal with DateTimes I need in different TimeZones based on where the user is asking from, etc:

您可以在库中看到更多关于此的一般化示例我最终会根据用户询问的位置等在不同的TimeZones中处理我需要的DateTimes:

https://github.com/b9chris/TimeZoneInfoLib.Net

This won't work outside of Windows (for example Mono on Linux) since the list of times comes from the Windows Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\

这不适用于Windows之外(例如Linux上的Mono),因为时间列表来自Windows注册表:HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Time Zones \

Underneath that you'll find keys (folder icons in Registry Editor); the names of those keys are what you pass to FindSystemTimeZoneById. On Linux you have to use a separate Linux-standard set of timezone definitions, which I've not adequately explored.

在其下方,您将找到密钥(注册表编辑器中的文件夹图标);这些键的名称是您传递给FindSystemTimeZoneById的名称。在Linux上,你必须使用一组单独的Linux标准时区定义,我没有充分研究过。

#4


6  

I altered Jon Skeet answer a bit for the web with extension method. It also works on azure like a charm.

我用扩展方法改变了Jon Skeet对网络的回答。它也适用于天蓝色的魅力。

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);   }}

#5


2  

You'll have to create a custom object for that. Your custom object will contain two values:

您必须为此创建自定义对象。您的自定义对象将包含两个值:

  • a DateTime value
  • DateTime值

  • a TimeZone object
  • 一个TimeZone对象

Not sure if there already is a CLR-provided data type that has that, but at least the TimeZone component is already available.

不确定是否已有CLR提供的数据类型,但至少TimeZone组件已经可用。

#6


2  

I like Jon Skeet's answer, but would like to add one thing. I'm not sure if Jon was expecting the ctor to always be passed in the Local timezone. But I want to use it for cases where it's something other then local.

我喜欢Jon Skeet的回答,但想补充一点。我不确定Jon是否期望ctor始终在本地时区传递。但是我想把它用于那些本地以外的东西。

I'm reading values from a database, and I know what timezone that database is in. So in the ctor, I'll pass in the timezone of the database. But then I would like the value in local time. Jon's LocalTime does not return the original date converted into a local timezone date. It returns the date converted into the original timezone (whatever you had passed into the ctor).

我正在读取数据库中的值,我知道数据库所处的时区。所以在ctor中,我将传入数据库的时区。但后来我想在当地时间价值。 Jon的LocalTime不会将原始日期转换为本地时区日期。它返回转换为原始时区的日期(无论您传递到ctor中)。

I think these property names clear it up...

我认为这些属性名称可以清除它......

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);}

#1


172  

Jon's answer talks about TimeZone, but I'd suggest using TimeZoneInfo instead.

Jon的回答谈到了TimeZone,但我建议使用TimeZoneInfo。

Personally I like keeping things in UTC where possible, so I'd suggest a structure like this:

就个人而言,我喜欢在可能的情况下保留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);         }    }        }

You may wish to change the "TimeZone" names to "TimeZoneInfo" to make things clearer - I prefer the briefer names myself.

您可能希望将“TimeZone”名称更改为“TimeZoneInfo”以使事情更清晰 - 我更喜欢自己的名字。

#2


41  

The DateTimeOffset structure was created for exactly this type of use.

DateTimeOffset结构是为这种类型的使用而创建的。

See:http://msdn.microsoft.com/en-us/library/system.datetimeoffset.aspx

Here's an example of creating a DateTimeOffset object with a specific time zone:

以下是使用特定时区创建DateTimeOffset对象的示例:

DateTimeOffset do1 = new DateTimeOffset(2008, 8, 22, 1, 0, 0, new TimeSpan(-5, 0, 0));

DateTimeOffset do1 = new DateTimeOffset(2008,8,22,1,0,0,new TimeSpan(-5,0,0));

#3


29  

The other answers here are useful but they don't cover how to access Pacific specifically - here you go:

这里的其他答案很有用,但它们没有涵盖如何专门访问太平洋 - 在这里你去:

public static DateTime GmtToPacific(DateTime dateTime){    return TimeZoneInfo.ConvertTimeFromUtc(dateTime,        TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time"));}

Oddly enough, although "Pacific Standard Time" normally means something different from "Pacific Daily Time," in this case it refers to Pacific time in general. In fact, if you use FindSystemTimeZoneById to fetch it, one of the properties available is a bool telling you whether that timezone is currently in daylight savings or not.

奇怪的是,虽然“太平洋标准时间”通常意味着与“太平洋日报时间”不同,但在这种情况下,它指的是太平洋时间。实际上,如果你使用FindSystemTimeZoneById来获取它,那么可用的一个属性是bool,告诉你该时区目前是否在夏令时中。

You can see more generalized examples of this in a library I ended up throwing together to deal with DateTimes I need in different TimeZones based on where the user is asking from, etc:

您可以在库中看到更多关于此的一般化示例我最终会根据用户询问的位置等在不同的TimeZones中处理我需要的DateTimes:

https://github.com/b9chris/TimeZoneInfoLib.Net

This won't work outside of Windows (for example Mono on Linux) since the list of times comes from the Windows Registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\

这不适用于Windows之外(例如Linux上的Mono),因为时间列表来自Windows注册表:HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows NT \ CurrentVersion \ Time Zones \

Underneath that you'll find keys (folder icons in Registry Editor); the names of those keys are what you pass to FindSystemTimeZoneById. On Linux you have to use a separate Linux-standard set of timezone definitions, which I've not adequately explored.

在其下方,您将找到密钥(注册表编辑器中的文件夹图标);这些键的名称是您传递给FindSystemTimeZoneById的名称。在Linux上,你必须使用一组单独的Linux标准时区定义,我没有充分研究过。

#4


6  

I altered Jon Skeet answer a bit for the web with extension method. It also works on azure like a charm.

我用扩展方法改变了Jon Skeet对网络的回答。它也适用于天蓝色的魅力。

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);   }}

#5


2  

You'll have to create a custom object for that. Your custom object will contain two values:

您必须为此创建自定义对象。您的自定义对象将包含两个值:

  • a DateTime value
  • DateTime值

  • a TimeZone object
  • 一个TimeZone对象

Not sure if there already is a CLR-provided data type that has that, but at least the TimeZone component is already available.

不确定是否已有CLR提供的数据类型,但至少TimeZone组件已经可用。

#6


2  

I like Jon Skeet's answer, but would like to add one thing. I'm not sure if Jon was expecting the ctor to always be passed in the Local timezone. But I want to use it for cases where it's something other then local.

我喜欢Jon Skeet的回答,但想补充一点。我不确定Jon是否期望ctor始终在本地时区传递。但是我想把它用于那些本地以外的东西。

I'm reading values from a database, and I know what timezone that database is in. So in the ctor, I'll pass in the timezone of the database. But then I would like the value in local time. Jon's LocalTime does not return the original date converted into a local timezone date. It returns the date converted into the original timezone (whatever you had passed into the ctor).

我正在读取数据库中的值,我知道数据库所处的时区。所以在ctor中,我将传入数据库的时区。但后来我想在当地时间价值。 Jon的LocalTime不会将原始日期转换为本地时区日期。它返回转换为原始时区的日期(无论您传递到ctor中)。

I think these property names clear it up...

我认为这些属性名称可以清除它......

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);}