получить DateTimeOffset из DateTime (utc) и TimeZoneInfo - PullRequest
15 голосов
/ 08 июня 2011

Мне нужно конвертировать DateTime + TimeZoneInfo в DateTimeOffset.

Как мне это сделать?Я предполагаю, что должен пройти TimeSpan, но тогда я не уверен, что летнее время будет обработано правильно ..

Спасибо!

ОБНОВЛЕНИЕ

TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("Mountain Standard Time");
return new DateTimeOffset(DateTime.UtcNow, timeZone.BaseUtcOffset);

Этот код вызывает исключение ..

Смещение UTC для экземпляров Utc DateTime должно быть 0. \ r \ nИмя параметра: смещение

ОБНОВЛЕНИЕ2

Извините, я не осознавал, что DateTimeOffset содержит только смещение, он не содержит фактическую информацию о зоне - поэтому я принимаю ответ от @Dave, поскольку я буду использовать его..

Ответы [ 4 ]

18 голосов
/ 08 июня 2011

Вы должны получить разницу между DateTime.UtcNow и DateTime.Now

var now = DateTime.Now;
var utcNow = now.ToUniversalTime();
var ts = utcNow - now;

Если вы сохраняете смещение, обычно выгодно сохранять все даты в UTC (особенно в дБ), чтобы вам не приходилось иметь дело со смещениями. Вы просто конвертируете их перед отображением, но выполняете все вычисления в формате UTC.

Изменить: Если у вас есть объект TimeZone, вы можете преобразовать дату UTC в местное время для этого часового пояса.

TimeZone.CurrentTimeZone.ToLocalTime()

OR

DateTime dt = TimeZoneInfo.ConvertTimeFromUtc()

Вот пример кода, в котором будет указана дата во всех часовых поясах.

var dt = new DateTime(2011, 5, 21, 11, 0, 0);
foreach (var tzi in TimeZoneInfo.GetSystemTimeZones())
{
    Console.WriteLine(string.Format("Time in {0} is {1}", tzi.DisplayName, TimeZoneInfo.ConvertTimeFromUtc(dt, tzi)));
}
6 голосов
/ 08 июня 2011

TimeZoneInfo имеет свойство BaseUtcOffset, представляющее собой TimeSpan, представляющее смещение.

Это смещение, которое конструкторы DateTimeOffsetожидает:

var myDTOffset = new DateTimeOffset(myDatetime, mytzInfo.BaseUtcOffset);
3 голосов
/ 13 августа 2015

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

TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("Mountain Standard Time");
return new DateTimeOffset(DateTime.UtcNow, timeZone.BaseUtcOffset);

DateTimeOffset генерирует исключение. То, что вы хотели, это:

TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("Mountain Standard Time");
return new DateTimeOffset(DateTime.UtcNow).ToOffset(timeZone.BaseUtcOffset);

Это не приведет к исключению. Я не уверен, почему конструктор, который принимает TimeSpan, даже существует, поскольку он работает, только если он соответствует локальному смещению или смещению utc, указанному в объекте DateTime. Но это все еще возможно с меньшей головной болью.

2 голосов
/ 06 января 2015

Для тех из нас, кто работает с устаревшими системами, не всегда возможно изменить способ хранения данных.Если вас интересует только конкретный часовой пояс на машине, с которой выполняется ваш код, вы можете использовать приведенный ниже метод расширения.Между DateTime и DateTimeOffset существует неявное преобразование, которое учитывает свойство DateTime.Kind.

public static DateTimeOffset ToDateTimeOffset(this DateTime dt)
{
    return DateTime.SpecifyKind(dt, DateTimeKind.Local);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...