2016-01-20 4 views
4

У меня есть дата-время в базе данных, которое я читаю с использованием SqlDataReader, а затем отбрасываю его на (DateTime). После литья его Kind собственности DateTimeKind.Unspecified.Время синтаксиса даты C# с правильным часовым поясом и видом

Тогда у меня есть другая строка, которую я читаю из какого-то другого источника. Его формат выглядит следующим образом: 2016-01-20T22:20:29.055Z. Я делаю DateTime.Parse("2016-01-20T22:20:29.055Z"), а его свойство Kind - DateTimeKind.Local.

Как правильно разобрать оба времени для сравнения? Нужно ли использовать DateTimeOffsets? Как мне их разобрать?

Благодаря

ответ

4

Поскольку SQLReader не может разумно вывести DateTimeKind, он оставляет его неуказанным. Вы хотите использовать DateTime.SpecifyKind, чтобы изменить DateTimeKind на выходе SQLReader на соответствующее значение. Это работает нормально, если вы имеете дело только с UTC и одним последовательным местным часовым поясом; в противном случае вы действительно должны использовать DateTimeOffset как в своем коде, так и в базе данных SQL.

Строка «2016-01-20T22: 20: 29.055Z» соответствует ISO 8601 и является датой UTC; однако DateTime.Parse с 1 аргументом может завершить преобразование в локальное время. За документации:

Как правило, метод Анализировать возвращает объект DateTime, чье Kind свойство DateTimeKind.Unspecified. Тем не менее, метод синтаксического анализа может также выполнять преобразование часового пояса и установите значение свойства Вид по-разному, в зависимости от значений х и стилей параметров:

  • Если S содержит информацию о часовом поясе, дата и время преобразуются во время в локальном часовом поясе, а Тип - DateTimeKind.Local.
  • Если s содержит информацию о часовом поясе, а стили включают AdjustToUniversalflag, дата и время преобразуются в координаты Универсальное время (UTC), а Kind - DateTimeKind.Utc.
  • Если s содержит указатель часового пояса Z или GMT, а стили включают флаг RoundtripKind, дата и время интерпретируются как UTC и Тип DateTimeKind.Utc.

Также см. UTC gotchas in .NET and SQL Server в блоге Дерека Фаулера для дополнительного освещения темы.

+1

Но разве это не означает «Z»? Почему он все еще появляется как 'DateTimeKind.Local'. Это должно быть 'DateTimeKind.Utc', потому что« Z »- это UTC, это неправильно? –

+1

@mwahidje Упс, хороший момент. Подождите, пока я отредактирую ответ правильно. Спасибо, что поймали его. – JamieSee

+0

Обратите внимание, что в этом конкретном случае * либо * 'AdjustToUniversal', либо' RoundTripKind' решит проблему. –

0

Вы можете использовать что-то вроде этого:

string format = "ddd dd MMM h:mm tt yyyy"; 
DateTime dateTime = DateTime.ParseExact(dateString, format, 
    CultureInfo.InvariantCulture); 

В переменной формата, вы можете поместить формат, который вы хотите, и передать его функции ParseExact.

Надеюсь, это поможет.

2

В вашем втором примере 2016-01-20T22:20:29.055Z содержит информацию о часовом поясе; «Z» в конце указывает, что временная метка предназначена для скоординированного универсального времени (UTC). Однако DateTime.Parse() по умолчанию будет преобразовывать его с использованием DateTimeKind.Local, если не указан конкретный часовой пояс. Вы можете более точно использовать DateTime.ParseExact.

Что касается причин, по которым значения datetime в вашей базе данных выглядят как Unspecified, это, скорее всего, потому, что они вообще не содержат индикатора часового пояса. Проверьте, указывают ли данные базы данных информацию о часовом поясе, либо с помощью «Z» в конце, либо с указанием точного часового пояса, например 2016-01-20T22:20:29.055-07:00 (UTC-7).

+0

Даже если я задаю часовой пояс для 'DateTime.Parse()' ('Z' в моем случае), он по-прежнему 'DateTimeKind.Local', а также' DateTime.ParseExact («2016-01-20T22: 20: 29.055Z "," yyyy-MM-ddThh: mm: ss.fffZ ", null)' все еще выходит как 'DateTimeKind.Local' –

+1

По умолчанию' ParseExact' преобразуется в 'DateTimeKind.Local'. Для преобразования в UTC вам нужно использовать 'DateTimeStyle'' AdjustToUniversal''. Например: DateTime.ParseExact («2016-01-20T22: 20: 29.055Z», «yyyy-MM-ddTHH: mm: ss.fffZ», CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal); ' – Chase

+0

^^^ is еще 'DateTimeKind.Local' –

0

В вашей базе данных отсутствует контекст (смещение) даты и времени. Вы должны сохранять его либо в столбце datetimeoffset, либо в столбце datetime, но сохраняя время utc. И всегда лучше сравнивать два времени utc.