324

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

Web 服务返回的字段之一是 DateTime 字段。服务器返回 GMT 格式的字段,即末尾带有“Z”。

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

以下代码示例在一定程度上解决了这个问题,因为 12 小时的差异已经消失,但它没有考虑到 NZ 夏令时。

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

根据此日期网站

UTC/GMT 偏移量

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

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

4

12 回答 12

395

For strings such as 2012-09-19 01:27:30.000, DateTime.Parse cannot tell what time zone the date and time are from.

DateTime has a Kind property, which can have one of three time zone options:

  • Unspecified
  • Local
  • Utc

NOTE If you are wishing to represent a date/time other than UTC or your local time zone, then you should use DateTimeOffset.


So for the code in your question:

DateTime convertedDate = DateTime.Parse(dateStr);

var kind = convertedDate.Kind; // will equal DateTimeKind.Unspecified

You say you know what kind it is, so tell it.

DateTime convertedDate = DateTime.SpecifyKind(
    DateTime.Parse(dateStr),
    DateTimeKind.Utc);

var kind = convertedDate.Kind; // will equal DateTimeKind.Utc

Now, once the system knows its in UTC time, you can just call ToLocalTime:

DateTime dt = convertedDate.ToLocalTime();

This will give you the result you require.

于 2009-06-08T07:43:37.160 回答
125

I'd look into using the System.TimeZoneInfo class if you are in .NET 3.5. See http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx. This should take into account the daylight savings changes correctly.

// 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);
于 2009-01-18T21:50:49.100 回答
63
TimeZone.CurrentTimeZone.ToLocalTime(date);
于 2008-10-07T19:29:47.013 回答
29

DateTime默认情况下,对象具有Kindof Unspecified,出于 的目的,ToLocalTime假定为UTC.

要获取Unspecified DateTime对象的本地时间,您只需执行以下操作:

convertedDate.ToLocalTime();

改变fromKind的步骤是不必要的。假定用于:http : //msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspxDateTimeUnspecifiedUTCUnspecifiedUTCToLocalTime

于 2012-11-16T03:51:35.413 回答
16

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

DateTime.Parse()可能很棘手-例如,请参见此处。

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

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

或者,甚至更好,

DateTime.TryParseExact(...)

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

这是我们之前所做的:

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

我们对应用程序进行了分析,发现 DateTime.Parse 占 CPU 使用率的很大一部分。(顺便说一句,CultureInfo构造函数对 CPU 使用率的影响 并不大。)

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

于 2011-10-26T16:10:55.060 回答
15

我只想添加一个一般性的注意事项。

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

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

于 2008-10-08T12:21:02.743 回答
9
@TimeZoneInfo.ConvertTimeFromUtc(timeUtc, TimeZoneInfo.Local)
于 2017-05-28T09:25:43.063 回答
5

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

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

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

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

从外观上看,代码可能类似于:

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

如上所述,请仔细检查您的服务器所在的时区设置。网上有文章介绍如何安全地影响 IIS 中的更改。

于 2008-10-08T12:48:24.343 回答
4

回答 Dana 的建议:

代码示例现在看起来像:

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

原来的日期是 20/08/08;那种是UTC。

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

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

于 2008-10-07T19:55:26.277 回答
1

我遇到了一个问题,它位于通过网络推送的数据集中(webservice 到客户端),它会自动更改,因为 DataColumn 的 DateType 字段设置为本地。如果您推送数据集,请确保检查 DateType 是什么。

如果您不希望它更改,请将其设置为未指定

于 2008-10-07T19:59:08.547 回答
1

I came across this question as I was having a problem with the UTC dates you get back through the twitter API (created_at field on a status); I need to convert them to DateTime. None of the answers/ code samples in the answers on this page were sufficient to stop me getting a "String was not recognized as a valid DateTime" error (but it's the closest I have got to finding the correct answer on SO)

Posting this link here in case this helps someone else - the answer I needed was found on this blog post: http://www.wduffy.co.uk/blog/parsing-dates-when-aspnets-datetimeparse-doesnt-work/ - basically use DateTime.ParseExact with a format string instead of DateTime.Parse

于 2009-10-03T16:01:31.207 回答
0

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

CreatedDate.ToUniversalTime().ToLocalTime();
于 2021-01-20T20:46:46.627 回答