Как использовать TimeZoneInfo, чтобы получить местное время в летнее время?
Я пытаюсь использовать 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 ответа:
вам нужно получить 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)));
вы также можете использовать TimeZoneInfo.ConvertTimeFromUtc, что позволит перейти на летнее и зимнее время:
DateTime utc = DateTime.UtcNow; TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"); DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(utc, zone);
или лучше, если вы не хотите, чтобы жесткий код часовой пояс идентификатор:
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id); DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tzi);
Я новичок как в .NET, так и в stackoverflow, поэтому я могу ошибаться, но здесь идет:
С Помощью TimeZoneInfo.ConvertTimeFromUtc позволит переходить на летнее время и конвертировать в правильное время в соответствии с часовым поясом + возможное смещение DST. Однако-само смещение в результирующем объекте будет показывать смещение для стандартного времени,а не учитывать летнее время. Поэтому, если вы хотите сделать 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".