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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/179940/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 16:50:40  来源:igfitidea点击:

Convert UTC/GMT time to local time

c#.netdatetimeutc

提问by nzpcmad

We are developing a C# application for a web-service client. This will run on Windows XP PC's.

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

One of the fields returned by the web service is a DateTime field. The server returns a field in GMT format i.e. with a "Z" at the end.

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

However, we found that .NET seems to do some kind of implicit conversion and the time was always 12 hours out.

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

The following code sample resolves this to some extent in that the 12 hour difference has gone but it makes no allowance for NZ daylight saving.

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

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

As per this date site:

根据这个日期网站

UTC/GMT Offset

Standard time zone: UTC/GMT +12 hours
Daylight saving time: +1 hour
Current time zone offset: UTC/GMT +13 hours

UTC/GMT 偏移

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

How do we adjust for the extra hour? Can this be done programmatically or is this some kind of setting on the PC's?

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

回答by coder1

TimeZone.CurrentTimeZone.ToLocalTime(date);

回答by nzpcmad

In answer to Dana's suggestion:

回答 Dana 的建议:

The code sample now looks like:

代码示例现在看起来像:

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

The original date was 20/08/08; the kind was UTC.

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

Both "convertedDate" and "dt" are the same:

"convertedDate" 和 "dt" 都是一样的:

21/08/08 10:00:26; the kind was local

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

回答by Miles

I had the problem with it being in a data set being pushed across the wire (webservice to client) that it would automatically change because the DataColumn's DateType field was set to local. Make sure you check what the DateType is if your pushing DataSets across.

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

If you don't want it to change, set it to Unspecified

如果您不想更改,请将其设置为 Unspecified

回答by Mark T

I'd just like to add a general note of caution.

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

If all you are doing is getting the current time from the computer's internal clock to put a date/time on the display or a report, then all is well. But if you are savingthe date/time information for later reference or are computingdate/times, beware!

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

Let's say you determine that a cruise ship arrived in Honolulu on 20 Dec 2007 at 15:00 UTC. And you want to know what local time that was.
1.There are probably at least three 'locals' involved. Local may mean Honolulu, or it may mean where your computer is located, or it may mean the location where your customer is located.
2.If you use the built-in functions to do the conversion, it will probably be wrong. This is because daylight savings time is (probably) currently in effect on your computer, but was NOT in effect in December. But Windows does not know this... all it has is one flag to determine if daylight savings time is currently in effect. And if it is currently in effect, then it will happily add an hour even to a date in December.
3.Daylight savings time is implemented differently (or not at all) in various political subdivisions. Don't think that just because your country changes on a specific date, that other countries will too.

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

回答by Brendan Kowitz

Don't forget if you already have a DateTime object and are not sure if it's UTC or Local, it's easy enough to use the methods on the object directly:

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

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

How do we adjust for the extra hour?

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

Unless specified .net will use the local pc settings. I'd have a read of: http://msdn.microsoft.com/en-us/library/system.globalization.daylighttime.aspx

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

By the looks the code might look something like:

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

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

And as mentioned above double check what timezone setting your server is on. There are articles on the net for how to safely affect the changes in IIS.

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

回答by Daniel Ballinger

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.

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

回答by Drew Noakes

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

对于诸如 之类的字符串2012-09-19 01:27:30.000DateTime.Parse无法分辨日期和时间来自哪个时区。

DateTimehas a Kindproperty, which can have one of three time zone options:

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

  • Unspecified
  • Local
  • Utc
  • 未指定
  • 当地的
  • 世界标准时间

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

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

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

DateTime dt = convertedDate.ToLocalTime();

This will give you the result you require.

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

回答by DannykPowell

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)

我遇到了这个问题,因为我遇到了通过 twitter API 返回的 UTC 日期(状态上的 created_at 字段)的问题;我需要将它们转换为 DateTime。本页答案中的所有答案/代码示例都不足以阻止我收到“字符串未被识别为有效的日期时间”错误(但这是我在 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

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

回答by David

I know this is an older question, but I ran into a similar situation, and I wanted to share what I had found for future searchers, possibly including myself :).

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

DateTime.Parse()can be tricky -- see herefor example.

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

If the DateTimeis coming from a Web service or some other source with a known format, you might want to consider something like

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

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

or, even better,

或者,甚至更好,

DateTime.TryParseExact(...)

The AssumeUniversalflag tells the parser that the date/time is already UTC; the combination of AssumeUniversaland AdjustToUniversaltells it not to convert the result to "local" time, which it will try to do by default. (I personally try to deal exclusively with UTC in the business / application / service layer(s) anyway. But bypassing the conversion to local time also speeds things up -- by 50% or more in my tests, see below.)

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

Here's what we were doing before:

这是我们之前所做的:

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

We had profiled the app and found that the DateTime.Parse represented a significant percentage of CPU usage. (Incidentally, the CultureInfoconstructor was nota significant contributor to CPU usage.)

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

So I set up a console app to parse a date/time string 10000 times in a variety of ways. Bottom line:
Parse()10 sec
ParseExact()(converting to local) 20-45 ms
ParseExact()(not converting to local) 10-15 ms
... and yes, the results for Parse()are in seconds, whereas the others are in milliseconds.

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

回答by CJ7

DateTimeobjects have the Kindof Unspecifiedby default, which for the purposes of ToLocalTimeis assumed to be UTC.

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

To get the local time of an UnspecifiedDateTimeobject, you therefore just need to do this:

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

convertedDate.ToLocalTime();

The step of changing the Kindof the DateTimefrom Unspecifiedto UTCis unnecessary. Unspecifiedis assumed to be UTCfor the purposes of ToLocalTime: http://msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspx

改变的步骤KindDateTimeUnspecifiedUTC是不必要的。Unspecified假设是UTC为了ToLocalTimehttp: //msdn.microsoft.com/en-us/library/system.datetime.tolocaltime.aspx