如何使用TimeZoneInfo在夏令时期间获取当地时间?

jam*_*nto 78 c# timezone datetimeoffset

我正在尝试使用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));
Run Code Online (Sandbox Code Playgroud)

打印出:

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进行更改.

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

Pau*_* pk 57

您需要从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)));
Run Code Online (Sandbox Code Playgroud)

  • 与[Karl Gjertsen的答案](http://stackoverflow.com/a/16789973/57611)相比,这不是最好的方法,它使用单个.Net函数来完成工作,而不是通过创建一个新的,抛出来提取偏移量-away`DateTimeOffset`. (4认同)

Kar*_*sen 51

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

DateTime utc = DateTime.UtcNow;
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(utc, zone);
Run Code Online (Sandbox Code Playgroud)

  • 这似乎无法根据夏令时正确调整。 (7认同)

Pab*_*tor 7

或者更好的是,如果您不想对时区标识符进行硬编码:

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id);
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tzi);
Run Code Online (Sandbox Code Playgroud)

  • 这不是很安全.如果您将应用程序外包给云环境,则不知道哪个时区本身就是本地区域. (5认同)
  • 不能直接使用`TimeZoneInfo.Local` 吗?为什么需要调用“FindSystemTimeZoneById”? (3认同)
  • 你是对的,我们不需要它.我们可以这样做`DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(networkDateTime,TimeZoneInfo.Local);` (3认同)

Nie*_*ein 6

我是 .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);
Run Code Online (Sandbox Code Playgroud)

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