将UTC / GMT时间转换为本地时间

我们正在开发一个Web服务客户端的C#应用​​程序。 这将在Windows XP PC上运行。

Web服务返回的一个字段是DateTime字段。 服务器以GMT格式返回一个字段,即最后一个“Z”。

但是,我们发现.NET似乎做了某种隐式转换,时间总是12个小时。

下面的代码示例在一定程度上解决了这个问题,12小时的差异已经消失了,但是不允许新西兰夏令时。

CultureInfo ci = new CultureInfo("en-NZ"); string date = "Web service date".ToString("R", ci); DateTime convertedDate = DateTime.Parse(date); 

根据这个date的网站 :

UTC / GMT偏移

标准时区:UTC / GMT +12小时
夏令时:1小时
当前时区偏移: UTC / GMT +13小时

我们如何调整额外的小时? 这可以通过编程来完成吗?或者这是PC上的某种设置?

对于诸如2012-09-19 01:27:30.000string, DateTime.Parse无法知道date和时间来自哪个时区。

DateTime有一个Kind属性,可以有三个时区选项之一:

  • 不明
  • 本地
  • 世界标准时间

注意 如果您希望表示UTC以外的date/时间或当地时区,则应使用DateTimeOffset


所以对于你的问题中的代码:

 DateTime convertedDate = DateTime.Parse(dateStr); var kind = convertedDate.Kind; // will equal DateTimeKind.Unspecified 

你说你知道它是什么样的,所以告诉它。

 DateTime convertedDate = DateTime.SpecifyKind( DateTime.Parse(dateStr), DateTimeKind.Utc); var kind = convertedDate.Kind; // will equal DateTimeKind.Utc 

现在,一旦系统知道UTC时间,就可以调用ToLocalTime

 DateTime dt = convertedDate.ToLocalTime(); 

这会给你你需要的结果。

如果你在.NET 3.5中,我会考虑使用System.TimeZoneInfo类。 请参阅http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx 。 这应该考虑夏令时更改正确。

 // Coordinated Universal Time string from // DateTime.Now.ToUniversalTime().ToString("u"); string date = "2009-02-25 16:13:00Z"; // Local .NET timeZone. DateTime localDateTime = DateTime.Parse(date); DateTime utcDateTime = localDateTime.ToUniversalTime(); // ID from: // "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zone" // See http://msdn.microsoft.com/en-us/library/system.timezoneinfo.id.aspx string nzTimeZoneKey = "New Zealand Standard Time"; TimeZoneInfo nzTimeZone = TimeZoneInfo.FindSystemTimeZoneById(nzTimeZoneKey); DateTime nzDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, nzTimeZone); 
 TimeZone.CurrentTimeZone.ToLocalTime(date); 

DateTime对象默认情况下具有“ Unspecified Kind ”,对于ToLocalTime而言,它被假定为UTC

要获取Unspecified DateTime对象的本地时间,您只需要这样做:

 convertedDate.ToLocalTime(); 

DateTimeKindUnspecified更改为UTC是不必要的。 为了ToLocalTime的目的, Unspecified被假定为UTC : http : //msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspx

我知道这是一个较老的问题,但我遇到了类似的情况,我想分享我为未来的search者find的东西,可能包括我自己:)。

DateTime.Parse()可能会非常棘手 – 请参阅这里例如。

如果DateTime来自Web服务或其他已知格式的源,则可能需要考虑类似的东西

 DateTime.ParseExact(dateString, "MM/dd/yyyy HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal) 

或者,甚至更好,

 DateTime.TryParseExact(...) 

AssumeUniversal标志告诉parsing器date/时间已经是UTC; AssumeUniversalAdjustToUniversal的组合告诉它不要将结果转换为“本地”时间,默认情况下它会尝试执行。 (我个人试图在业务/应用/服务层中专门处理UTC,但绕过本地时间的转换也会加快速度 – 在我的testing中速度提高了50%以上,见下文)。

以下是我们之前的工作:

 DateTime.Parse(dateString, new CultureInfo("en-US")) 

我们已经对应用程序进行了分析,发现DateTime.Parse代表了CPU占用率的很大一部分。 (顺便说一句, CultureInfo构造函数不是 CPU使用率的重要贡献者。)

所以我设置了一个控制台应用程序来以各种方式parsing10000次date/时间string。 底线:
Parse() 10秒
ParseExact() (转换为本地)20-45毫秒
ParseExact() (不转换为本地)10-15毫秒
…是的, Parse()的结果是以秒为单位的 ,而其他的则以毫秒为单位

我只想补充一点小心。

如果你只是从计算机的内部时钟获取当前时间,在显示屏或报告上inputdate/时间,那么一切都很好。 但是,如果您保存date/时间信息供以后参考或计算date/时间,请注意!

假设您确定一艘邮轮在2007年12月20日15:00 UTC抵达檀香山。 而且你想知道当地时间是什么。
1.可能至less涉及三名“本地人”。 本地可能意味着檀香山,也可能意味着您的计算机所在的位置,也可能意味着您的客户所在的位置。
2.如果使用内置函数进行转换,则可能是错误的。 这是因为夏令时(可能)目前在您的计算机上生效,但在十二月份不生效。 但Windows不知道这一切……它只有一个标志来确定夏时制是否正在生效。 如果目前正在实施,那么在十二月份的某个date,它会很乐意地增加一个小时。
夏令时在各个政治分支中的实施方式不同(或根本不同)。 不要以为只是因为你的国家在某个具体的日子发生了变化,其他国家也会这样。

不要忘记,如果你已经有了一个DateTime对象,并且不确定它是UTC还是Local,那么很容易直接使用对象的方法:

 DateTime convertedDate = DateTime.Parse(date); DateTime localDate = convertedDate.ToLocalTime(); 

我们如何调整额外的小时?

除非指定.net将使用本地电脑设置。 我会阅读: http : //msdn.microsoft.com/en-us/library/system.globalization.daylighttime.aspx

通过外观代码可能看起来像这样:

 DaylightTime daylight = TimeZone.CurrentTimeZone.GetDaylightChanges( year ); 

如上所述,仔细检查你的服务器是在什么时区设置的。 有网上的文章如何安全地影响在IIS中的变化。

在回答达纳的build议时:

代码示例如下所示:

 string date = "Web service date"..ToString("R", ci); DateTime convertedDate = DateTime.Parse(date); DateTime dt = TimeZone.CurrentTimeZone.ToLocalTime(convertedDate); 

最初的date是20/08/08; 那种是UTC。

“convertedDate”和“dt”都是一样的:

21/08/08 10:00:26; 那种是当地的

我遇到了一个问题,它是在一个数据集被推送通过networking(web服务到客户端),它会自动更改,因为DataColumn的DateType字段设置为本地。 确保你检查什么DateType是如果你推动DataSets跨。

如果您不想更改,请将其设置为“未指定”

我遇到了这个问题,因为我在通过twitter API(status上的created_at字段)返回UTCdate时遇到了问题。 我需要将它们转换为DateTime。 在这个页面的答案中没有答案/代码样本足以阻止我得到一个“string不被认为是有效的DateTime”错误(但它是最接近的,我必须find正确的答案)

张贴这个链接在这里,以防万一这有助于别人 – 我需要的答案是在这篇博客上发现: http : //www.wduffy.co.uk/blog/parsing-dates-when-aspnets-datetimeparse-doesnt-work/ – 基本上使用DateTime.ParseExact格式string,而不是DateTime.Parse

 @TimeZoneInfo.ConvertTimeFromUtc(timeUtc, TimeZoneInfo.Local)