Как использовать TimeZoneInfo, чтобы получить местное время в летнее время? - PullRequest
73 голосов
/ 03 июня 2010

Я пытаюсь использовать 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

Я нахожусь в центральном часовом поясе, и сейчас у нас летнее время. Я пытаюсь получить вторую строку для чтения:

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

BaseUtcOffset, по-видимому, не изменяется в зависимости от летнего времени.

Как получить правильное время с правильным значением смещения?

Ответы [ 4 ]

55 голосов
/ 03 июня 2010

Вам нужно получить UtcOffset из TimeZoneInfo, а затем передать его методу 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)));
48 голосов
/ 28 мая 2013

Вы также можете использовать TimeZoneInfo.ConvertTimeFromUtc, что позволит переходить на летнее время:

DateTime utc = DateTime.UtcNow;
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(utc, zone);
7 голосов
/ 11 марта 2015

Или лучше, если вы не хотите жестко кодировать идентификатор часового пояса :

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id);
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tzi);
3 голосов
/ 07 ноября 2017

Я новичок как в .NET, так и в stackoverflow, так что я могу ошибаться, но здесь идет речь:

Использование TimeZoneInfo.ConvertTimeFromUtc обеспечит переход на летнее время и преобразование в правильное время в соответствии с часовым поясом + возможное смещение летнего времени. Однако - само смещение в результирующем объекте будет показывать смещение для стандартного времени, а не учитывать летнее время. Поэтому, если вы хотите создать ToString для объекта, вы получите правильное время (в часах и минутах), но с неправильным смещением во время перехода на летнее время, что может привести к неправильному моменту времени позже в коде.

Если вместо этого вы используете GetUtcOffset, чтобы получить смещение в течение определенного времени, а затем выполните ToOffset для объекта DateTimeOffset, часы и минуты и само смещение будут правильно преобразованы, и вы можете безопасно сделать 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".

...