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

时间:2008-10-07 19:23:05

标签: c# .net datetime utc

我们正在为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);            

根据this date site

  

UTC / GMT Offset

     

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

我们如何调整额外的一小时?这可以通过编程方式完成,还是PC上的某种设置?

12 个答案:

答案 0 :(得分:361)

对于2012-09-19 01:27:30.000等字符串,DateTime.Parse无法判断日期和时间来自哪个时区。

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

  • 未指定的
  • 本地
  • UTC

注意 如果您希望代表UTC或当地时区以外的日期/时间,则应使用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();

这将为您提供所需的结果。

答案 1 :(得分:114)

如果您使用的是.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);

答案 2 :(得分:48)

TimeZone.CurrentTimeZone.ToLocalTime(date);

答案 3 :(得分:21)

默认情况下,

DateTime个对象的Kind UnspecifiedToLocalTime,假定为UTC

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

convertedDate.ToLocalTime();

Kind的{​​{1}}从DateTime更改为Unspecified的步骤是不必要的。 UTC的{​​{1}}被认为是UnspecifiedUTC

答案 4 :(得分:15)

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

DateTime.Parse()可能很棘手 - 例如,请参阅here

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

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

或者,甚至更好,

DateTime.TryParseExact(...)

AssumeUniversal标志告诉解析器日期/时间已经是UTC; AssumeUniversalAdjustToUniversal的组合告诉它不要将结果转换为“本地”时间,默认情况下会尝试执行此操作。 (无论如何,我个人尝试在业务/应用程序/服务层专门处理UTC。但是绕过转换到本地时间也会加快速度 - 在我的测试中增加50%或更多,见下文。)

以下是我们之前所做的事情:

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

我们对该应用进行了分析,发现DateTime.Parse占CPU使用率的很大一部分。 (顺便提一下,CultureInfo构造函数是CPU使用量的重要贡献者。)

所以我设置了一个控制台应用程序,以各种方式解析日期/时间字符串10000次。底线:
Parse() 10秒
ParseExact()(转换为本地)20-45毫秒
ParseExact()(不转换为本地)10-15毫秒
......是的,Parse()的结果是,而其他的结果是毫秒

答案 5 :(得分:14)

我想补充一点注意事项。

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

假设您确定游轮于2007年12月20日15:00 UTC抵达檀香山。你想知道当地的时间是什么 1。可能至少涉及三个“当地人”。本地可能意味着檀香山,或者它可能意味着您的计算机所在的位置,或者它可能意味着您的客户所在的位置。
2。如果使用内置函数进行转换,则可能是错误的。这是因为夏令时(可能)目前在您的计算机上有效,但在12月没有生效。但是Windows并不知道这一点......它只是一个标志,用于确定夏令时当前是否有效。如果它现在有效,那么即使到12月的日期,它也会愉快地增加一个小时 3。在各种政治分支中,夏令时的实施方式不同(或根本不实施)。不要认为仅仅因为您的国家在特定日期发生变化,其他国家也会这样做。

答案 6 :(得分:4)

不要忘记,如果您已经有一个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中的更改的文章。

答案 7 :(得分:2)

回答达纳的建议:

代码示例现在看起来像:

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

原始日期是2008年8月20日;那种是UTC。

“convertedDate”和“dt”都是相同的:

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

答案 8 :(得分:2)

@TimeZoneInfo.ConvertTimeFromUtc(timeUtc, TimeZoneInfo.Local)

答案 9 :(得分:1)

由于DataColumn的DateType字段设置为local,我遇到的问题是它在数据集中被推送到网络(webservice到客户端),它会自动更改。如果推送数据集,请确保检查DateType是什么。

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

答案 10 :(得分:1)

我遇到了这个问题,因为我遇到了通过twitter API返回的UTC日期问题(状态上的created_at字段);我需要将它们转换为DateTime。此页面上的答案中没有任何答案/代码示例足以阻止我获得“字符串未被识别为有效的DateTime”错误(但它是最接近我必须在SO上找到正确的答案)

在此处发布此链接以防其他人 - 我需要的答案在此博客文章中找到:http://www.wduffy.co.uk/blog/parsing-dates-when-aspnets-datetimeparse-doesnt-work/ - 基本上使用DateTime.ParseExact与格式字符串而不是DateTime.Parse

答案 11 :(得分:0)

此代码块使用通用时间转换当前 DateTime 对象,然后将其转换回本地 DateTime。非常适合我,希望对我有帮助!

CreatedDate.ToUniversalTime().ToLocalTime();