У меня есть приложение asp.net, которое должно выполнять некоторый код каждый день в определенное время в Восточном Часовом поясе (знающий DST). Таким образом, моя первая мысль, получите восточную временную стоимость и преобразуйте ее во время локального сервера.
Таким образом, мне нужно что-то вроде этого:
var eastern = DateTime.Today.AddHours(17); // run at 5pm eastern
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var utc = TimeZoneInfo.ConvertTimeToUtc(eastern, timeZoneInfo);
var local = TimeZoneInfo.ConvertTimeFromUtc(utc, TimeZoneInfo.Local);
Но как я указываю, что восточный объект DateTime должен быть в часовом поясе EST.
Я приближаюсь к этому неправильный путь?
Кажется, я смог ответить на свой вопрос. Вот код, который я использую, чтобы получить объект следующего запуска DateTime
.
private DateTime GetNextRun()
{
var today = DateTime.Today;
var runTime = new DateTime(today.Year, today.Month, today.Day, 17, 0, 0);
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
var offset = timeZoneInfo.GetUtcOffset(runTime);
var dto = new DateTimeOffset(runTime, offset);
if (DateTime.Now > dto.LocalDateTime)
dto = dto.AddDays(1);
return dto.LocalDateTime;
}
Выполнение всего преобразования с использованием DateTimeOffset
вместо DateTime
оказалось эффективным. Кажется, он даже правильно переводит летнее время.
A DateTime
не знает часовой пояс.Даже DateTimeOffset
на самом деле ничего не знает о часовом поясе - он знает о моменте UTC и смещении от него.
Вы можете написать свою собственную структуру, которая имеет TimeZoneInfo
и DateTime
, но я не уверен, что вам это понадобится в данном случае. Вы просто пытаетесь запланировать 17:00 по восточному времени, или это более общий характер? Что вы потом делаете с DateTime
(или чем-то еще)? Используя DateTimeOffset
и TimeZoneInfo
, вы определенно можете получить момент UTC интересующего вас времени; если вам просто нужно знать время между «сейчас» и «потом», это довольно просто.
Я считаю своим долгом указать, что, когда Noda Time готов к производству, это почти наверняка будет правильным ответом :)
Вы можете использовать DateTime.UtcNow, чтобы получить центральное время UTC (которое, как мне кажется, равно GMT 0), а затем просто выясните, сколько часовых поясов один, который вы хотите, и удалите / добавьте час для каждой зоны.
Во-первых, вам нужно учесть несколько вещей. Вы должны иметь дело с переходом на летнее время, которое время от времени, кажется, меняется (даты начала и окончания менялись дважды за последние 10 лет). Итак, зимой в северном полушарии восточное время составляет -5 GMT (или UTC).Но летом -6 по Гринвичу или -4 по Гринвичу, я никогда не смогу удержать это прямо (да и не должен).
Есть несколько библиотечных функций DNF для работы с информацией о часовых поясах, однако вам действительно нужен .net 3.5 для наиболее полезных вещей. В .NET 3.5 есть класс TimeZoneInfo.
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime dt = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(DateTime.Now,
TimeZoneInfo.IsDaylightSavingsTime(tzi) ?
tzi.DaylightName : tzi.StandardName);
if (dt.Hour == 17)
....
Также имейте в виду, что дважды в год час теряется или приобретается, поэтому вы также должны учитывать это, если, например, у вас есть таймер обратного отсчета, который вы показываете «время до следующей обработки» или что-то в этом роде. Дело в том, что обработка времени не так проста, как может показаться на первый взгляд, и есть много крайних случаев.