Укажите дату в другом часовом поясе C # - PullRequest
5 голосов
/ 09 февраля 2010

У меня есть приложение asp.net, которое должно запускать некоторый код каждый день в определенное время в восточном часовом поясе (с учетом летнего времени). Поэтому моя первая мысль - получить восточное значение времени и преобразовать его в локальное время сервера.

Так что мне нужно что-то вроде этого:

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.

Неправильно ли я подхожу к этому?

Ответы [ 4 ]

8 голосов
/ 09 февраля 2010

Во-первых, есть несколько вещей, которые вы должны рассмотреть. Вам приходится иметь дело с переходом на летнее время, которое время от времени меняется (даты начала и окончания менялись дважды за последние 10 лет). Таким образом, в зимнем северном полушарии восточное время составляет -5 по Гринвичу (или 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)
    ....

Кроме того, имейте в виду, что два раза в год час теряется или набирается, поэтому вы также должны учитывать это, если, например, у вас есть таймер обратного отсчета, на котором отображается «время до следующей обработки» или что-то в этом роде. Дело в том, что обработка времени не так проста, как кажется на первый взгляд, и существует множество крайних случаев.

4 голосов
/ 09 февраля 2010

A DateTime не знает о часовом поясе. Даже DateTimeOffset на самом деле не знает о часовом поясе - он знает о времени UTC и смещении от него.

Вы можете написать свою собственную структуру, которая имеет с TimeZoneInfo и DateTime, но я не уверен, что она вам нужна в этом случае. Вы просто пытаетесь запланировать 5 вечера по восточному времени, или это на самом деле более общее? Что вы делаете с DateTime (или чем-то еще) после этого? Используя DateTimeOffset и TimeZoneInfo, вы определенно можете получить момент UTC интересующего вас времени; если вам просто нужно знать время между «сейчас» и потом, это довольно просто.

Я чувствую себя обязанным отметить, что, когда Noda Time готов к производству, это почти наверняка будет правильным ответом:)

3 голосов
/ 10 февраля 2010

Кажется, я смог ответить на свой вопрос. Вот код, который я использую для получения объекта 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 оказалось эффективным. Кажется, он даже правильно обрабатывает переход на летнее время.

1 голос
/ 09 февраля 2010

Вы можете использовать DateTime.UtcNow, чтобы получить центральное время UTC (которое, я считаю, GMT 0), и просто узнать, сколько часовых поясов вы хотите, и удалить / добавить час для каждой зоны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...