C# 如何使用TimeZoneInfo在夏令时获取本地时间?

C# 如何使用TimeZoneInfo在夏令时获取本地时间?,c#,datetimeoffset,timezone,timezoneinfo,getutcoffset,C#,Datetimeoffset,Timezone,Timezoneinfo,Getutcoffset,我试图使用DateTimeOffset在任何时区传递特定的时间点。我不知道如何使用TimeZoneInfo来处理夏令时 var dt = DateTime.UtcNow; Console.WriteLine(dt.ToLocalTime()); var tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"); var utcOffset = new DateTimeOffset(dt, TimeSpan.Zero);

我试图使用
DateTimeOffset
在任何时区传递特定的时间点。我不知道如何使用
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 2010年6月2日下午4:37:19 2010年6月2日下午3:37:19-06:00 我在中央时区,现在是夏令时。 我想让第二行读一下:

6/2/2010 4:37:19 PM -05:00 2010年6月2日下午4:37:19-05:00
BaseUtcOffset
显然不会根据DST进行更改


如何使用正确的偏移量值获取正确的时间?

您需要从TimeZoneInfo获取UtcOffset,然后将其传递给ToOffset()方法:


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

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

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


我在.NET和stackoverflow都是初学者,所以我可能错了,但这里有:

使用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);
本地时间将返回“2017-10-09T10:00:00+03:00”


+1-TimeZoneInfo.ConvertTimeBySystemTimeZoneId不仅仅适用于此:)@JamesManning-它适用于此,假设
dt.Kind
设置正确。我明白了……您必须获得时区中特定日期的UTC偏移量。谢谢。与使用单个.Net函数而不是通过创建一个新的、一次性的
DateTimeOffset
来提取偏移量相比,这不是最好的方法。您不能直接使用
TimeZoneInfo.Local
?为什么需要调用
FindSystemTimeZoneById
?没错,我们不需要它。我们可以这样做
DateTime localDateTime=TimeZoneInfo.ConvertTimeFromUtc(networkDateTime,TimeZoneInfo.Local)但是你被固定在一个时区。我想这取决于您希望如何使用代码。:-)这不是很安全。如果您将应用程序外包到云环境,您不知道哪个时区本身是本地的。如果我国的时区在夏季是EET,在冬季是EET,该怎么办?如果采用夏令时,这将如何工作?Windows知道时区信息以及夏令时日期。如果你选择一个预先定义的时区,它应该会解决问题,或者你自己解决。根据OP,这是正确的答案。要理解的主要事情是,timzone的UtcOffset不是常数,而是取决于日期本身,因为夏令时规则,我们正在谈论的是什么。因此,OP所做的唯一错误是使用了常量BaseUtcOffset,而不是GetUtcOffset(myDate)
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id);
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tzi);
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);