Укажите дату в другом часовом поясе C#

У меня есть приложение 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.

Я приближаюсь к этому неправильный путь?

5
задан mikefrey 9 February 2010 в 06:36
поделиться

4 ответа

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

3
ответ дан 18 December 2019 в 10:44
поделиться

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

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

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

4
ответ дан 18 December 2019 в 10:44
поделиться

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

1
ответ дан 18 December 2019 в 10:44
поделиться

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

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

8
ответ дан 18 December 2019 в 10:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: