2010-06-02 30 views
57

我试图使用DateTimeOffset在任何时区传达特定的时间。我无法弄清楚如何使用TimeZoneInfo来处理夏令时。如何在夏令时期间使用TimeZoneInfo获取当地时间?

var dt = DateTime.UtcNow; 
Console.WriteLine(dt.ToLocalTime()); 

var tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"); 
var utcOffset = new DateTimeOffset(dt, TimeSpan.Zero); 
Console.WriteLine(utcOffset.ToOffset(tz.BaseUtcOffset)); 

此打印出:

6/2/2010 4:37:19 PM 
6/2/2010 3:37:19 PM -06:00 

我在中央时区,而我们目前在夏令时。 我想获得第二行改为:

6/2/2010 4:37:19 PM -05:00 

BaseUtcOffset显然不会更改基于DST。

我怎样才能得到适当的偏移值正确的时间?

+9

+1 - 这简直让我疯狂的是TimeZoneInfo.ConvertTimeBySystemTimeZoneId不只是这个:) – 2010-06-03 04:14:13

回答

47

你需要得到来自的TimeZoneInfo的UTCOFFSET,然后传递到ToOffset()方法:

var dt = DateTime.UtcNow; 
Console.WriteLine(dt.ToLocalTime()); 

var tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"); 
var utcOffset = new DateTimeOffset(dt, TimeSpan.Zero); 
Console.WriteLine(utcOffset.ToOffset(tz.GetUtcOffset(utcOffset))); 
+0

我看到工作......你要获得UTC针对特定日期偏移时区。 谢谢。 – jaminto 2010-06-03 19:50:57

+3

与[Karl Gjertsen的答案](http://stackoverflow.com/a/16789973/57611)相比,这不是最好的方式,它使用单一的.Net函数来完成这项工作,而不是通过创建一个新的,扔掉'DateTimeOffset'。 – ErikE 2017-01-04 00:32:35

35

您还可以使用TimeZoneInfo.ConvertTimeFromUtc,这将允许夏令时:

DateTime utc = DateTime.UtcNow; 
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"); 
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(utc, zone); 
5

或者更好,如果你不想硬编码时区标识符

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id); 
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tzi); 
+0

难道你不能直接使用'TimeZoneInfo.Local'吗?你为什么需要调用FindSystemTimeZoneById? – CoderDennis 2015-10-14 21:15:16

+1

你说得对,我们不需要它。我们可以像这样做'DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(networkDateTime,TimeZoneInfo。本地);' – Pabinator 2015-10-15 15:40:51

+0

但是,你固定在一个时区。取决于你想如何使用我猜的代码。 :-) – 2015-11-05 16:32:35

1

我无论是在.NET和计算器一个初学者,所以我可能是错的,但这里有云:

使用TimeZoneInfo.ConvertTimeFromUtc将允许夏令时间,并根据时间转换为正确的时间区域+可能的DST偏移量。但是 - 结果对象中的偏移本身将显示标准时间的偏移量,并且不考虑夏令时。所以如果你想在对象上做一个ToString,你最终会得到正确的时间(以小时和分钟为单位),但是在夏令时期间错误的偏移量可能会导致代码后面错误的时间。

如果您改为使用GetUtcOffset获取特定时间的偏移量,然后对DateTimeOffset对象执行ToOffset,则小时/分钟和偏移量本身都将被正确转换,并且您可以安全地执行ToString 。

string ExpectedDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss''zzz"; 
string timeZoneId = "FLE Standard Time"; 
string dateTimestr = "2017-10-09T09:00:00+02:00"; 

DateTimeOffset dto = DateTimeOffset.Parse(dateTimeStr); 
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId); 
TimeSpan offset = zone.GetUtcOffset(dto); 
dto = dto.ToOffset(offset); 
string localTime = dto.ToString(ExpectedDateTimePattern); 

localTime将返回“2017-10-09T10:00:00 + 03:00”。