DateTime vs DateTimeOffset
В настоящее время у нас есть стандартный способ работы с .net DateTimes в часовом поясе: всякий раз, когда мы производим DateTime мы делаем это в UTC (например, используя DateTime.UtcNow), и всякий раз, когда мы показываем один, мы преобразуем обратно из UTC в местное время пользователя.
это прекрасно работает, но я читал о DateTimeOffset и как он захватывает местное и UTC время в самом объекте. Так что вопрос в том, каковы были бы преимущества использования DateTimeOffset против того, что мы уже делать?
8 ответов:
DateTimeOffsetпредставление мгновенное время (также известный как времени). Под этим я подразумеваю момент времени, который является универсальным для всех (не учитывая високосных секунд, или релятивистские эффекты замедление времени). Другой способ представления мгновенного времени-с помощьюDateTimeздесь.KindиDateTimeKind.Utc.это отличается от календарного времени (также известный как гражданского времени), который является позицией в чьем-то календаре, и есть много разных календарей по всему миру. Мы называем эти календари часовых поясов. Календарное время представлено символом
DateTimeздесь.KindиDateTimeKind.UnspecifiedилиDateTimeKind.Local. И.Localимеет смысл только в сценариях, где у вас есть подразумеваемое понимание того, где находится компьютер, который использует результат. (Например, рабочая станция пользователя)Итак, почему
DateTimeOffsetвместо мировогоDateTime? все дело в перспективе. давайте проведем аналогию-притворимся фотографами.представьте, что вы стоите на календарной шкале времени, указывая камерой на человека на мгновенной шкале времени, выложенной перед вами. Вы выстраиваете свою камеру в соответствии с правилами вашего часового пояса - которые периодически меняются из-за летнего времени или из-за других изменений в юридическом определении вашего часового пояса. (У вас нет твердая рука, так что ваша камера трясется.)
человек, стоящий на фотографии, увидит угол, под которым появилась ваша камера. Если бы другие фотографировали, они могли бы быть под разными углами. Это
OffsetчастьDateTimeOffsetпредставляет.поэтому, если вы обозначаете свою камеру "Восточное время", иногда вы указываете от -5, а иногда вы указываете от -4. Есть камеры по всему миру, все помечены разные вещи, и все показывали на одной и той же мгновенной шкале времени под разными углами. Некоторые из них находятся рядом (или поверх) друг с другом, поэтому просто зная смещение недостаточно, чтобы определить, к какому часовому поясу относится время.
а как насчет UTC? Ну, это одна камера, которая гарантированно имеет устойчивую руку. Он стоит на треноге, прочно закрепленной в земле. Это никуда не денется. Мы называем его угол зрения нулем сдвиг.
Итак-о чем же говорит нам эта аналогия? Он предоставляет некоторые интуитивные рекомендации.
если вы представляете время относительно некоторого места в частности, представить его в календарном времени с
DateTime. Просто убедитесь, что вы никогда не путаете один календарь с другим.Unspecifiedдолжно быть ваше предположение.Localполезно только исходя изDateTime.Now. Например, я мог бы получитьDateTime.Nowи сохранить его в базе данных - но когда я получаю его, я должен предположить, что этоUnspecified. Я не могу полагаться на то, что мой локальный календарь-это тот же календарь, из которого он был первоначально взят.если вы всегда должны быть уверены в моменте, убедитесь, что вы представляете мгновенное время. Используйте
DateTimeOffsetчтобы применить его, или использовать UTCDateTimeпо Конвенции.Если вам нужно отслеживать момент мгновенного времени, но вы хотите также знать, " в какое время пользователь думал это было в их местном календаре?- ...тогда ты должны использовать
DateTimeOffset. Это очень важно для систем хронометража, например - как для технических, так и для юридических вопросов.Если вам когда-нибудь понадобится изменить ранее записанный
DateTimeOffset- У вас недостаточно информации только в смещении, чтобы гарантировать, что новое смещение по-прежнему актуально для пользователя. Вы должны и хранить идентификатор часового пояса (думаю-мне нужно имя этого камера, чтобы я мог сделать новый снимок, даже если положение изменилось).следует также отметить, что Нода Времени имеет представление под названием
ZonedDateTimeдля этого, в то время как библиотека базовых классов .Net не имеет ничего подобного. Вам нужно будет хранить оба aDateTimeOffsetиTimeZoneInfo.Idзначение.иногда вы захотите представить календарное время, которое является локальным для "того, кто смотрит на него". Например, при определении что средства. Сегодня ВСЕГДА полночь до полуночи, но они представляют собой почти бесконечное число перекрывающихся диапазонов на мгновенной временной шкале. (На практике у нас есть конечное число часовых поясов, но вы можете выразить смещения вплоть до тика) поэтому в этих ситуациях убедитесь, что вы понимаете, как ограничить "кто спрашивает?"вопрос до одного часового пояса, или иметь дело с переводом их обратно в мгновенное время, как соответствующий.
вот еще несколько маленьких кусочков о
DateTimeOffsetЭто подтверждает эту аналогию, и некоторые советы для поддержания его прямо:
если сравнивать два
DateTimeOffsetзначения, они сначала нормализуются до нулевого смещения перед сравнением. Другими словами,2012-01-01T00:00:00+00:00и2012-01-01T02:00:00+02:00относятся к одному и тому же мгновенному моменту и поэтому эквивалентны.если вы делаете любое испытание блока и нужно быть некоторые из смещения, тест и the
DateTimeOffsetзначение, а.Offsetсобственность отдельно.существует одностороннее неявное преобразование, встроенное в .Net framework, которое позволяет передавать
DateTimeв любомDateTimeOffsetпараметр или переменная. При этом the.Kindвопросы. Если вы передадите вид UTC, он будет переноситься с нулевым смещением, но если вы передадите либо.Localили.Unspecified, это будет считать местные. Структура в основном говорит: "Ну, вы попросили меня преобразовать календарное время в мгновенное время, но я понятия не имею, откуда это взялось, поэтому я просто собираюсь использовать местный календарь."Это огромный gotcha, если вы загружаете неопределенныйDateTimeна компьютере с другим часовым поясом. (ИМХО-это должно вызвать исключение - но это не так.)Промоушен:
многие люди делились со мной, что они находят это аналогия чрезвычайно ценна, поэтому я включил ее в свой курс Pluralsight,дата и время основы. Вы найдете пошаговое руководство по аналогии с камерой во втором модуле "контекст имеет значение" в клипе под названием "календарное время против мгновенного времени".
От Microsoft:
эти значения DateTimeOffset используются гораздо чаще, чем значения DateTime. В результате DateTimeOffset следует считать типом даты и времени по умолчанию для разработки приложений.
источник: "выбор между DateTime, DateTimeOffset, TimeSpan и TimeZoneInfo", MSDN
мы используем:
DateTimeOffsetпочти все наши приложение имеет дело с определенными моментами времени (например, когда запись была создана/обновлена). В качестве примечания мы используемDATETIMEOFFSETв SQL Server 2008, а также.я вижу
DateTimeкак полезно, когда вы хотите иметь дело только с датами, только раз, или иметь дело с любым в общем смысле. Например, если у вас есть будильник, который вы хотите отключать каждый день в 7 утра, вы можете сохранить его вDateTimeиспользуя aDateTimeKindнаUnspecifiedпотому что вы хотите, чтобы он ушел в 7 утра независимо от DST. Но если вы хотите представить историю возникновения тревоги, вы бы использовалиDateTimeOffset.будьте осторожны при использовании смеси
DateTimeOffsetиDateTimeособенно при назначении и сравнении между типами. Кроме того, только сравнитьDateTimeэкземпляры, которые являются одинаковымиDateTimeKind, потому чтоDateTimeигнорирует смещение часового пояса при сравнении.
DateTime способен хранить только два различных времени, местное время и UTC. Элемент вид свойства показывает, что.
DateTimeOffset расширяет это, имея возможность хранить местное время из любой точки мира. Он также хранит смещение между местным временем и UTC. Обратите внимание, что DateTime не может этого сделать, если вы не добавите дополнительный член в свой класс для хранения этого смещения UTC. Или только когда-либо работать с UTC. Что само по себе является прекрасной идеей кстати.
есть несколько мест, где
DateTimeOffsetимеет смысл. Когда вы имеете дело с повторяющимися событиями и летнее время. Допустим, я хочу установить будильник, чтобы уйти в 9 утра каждый день. Если я использую правило "хранить как UTC, отображать как местное время", то сигнал тревоги будет отключен в разные время, когда летнее время действует.вероятно, есть и другие, но приведенный выше пример на самом деле тот, с которым я столкнулся в прошлом (это было до добавление
DateTimeOffsetдля BCL-мое решение в то время состояло в том, чтобы явно хранить время в локальном часовом поясе и сохранять информацию о часовом поясе вдоль него: в основном чтоDateTimeOffsetНе внутренне).
наиболее важным отличием является то, что DateTime не хранит информацию о часовом поясе, в то время как DateTimeOffset делает.
хотя DateTime различает UTC и Local, нет абсолютно никакого явного смещения часового пояса, связанного с ним. Если вы выполняете какую-либо сериализацию или преобразование, будет использоваться часовой пояс сервера. Даже если вы вручную создадите локальное время, добавив минуты для смещения времени UTC, вы все равно можете получить бит на этапе сериализации, потому что (из-за отсутствия явного смещения в DateTime) он будет использовать смещение часового пояса сервера.
например, если вы сериализуете значение DateTime с помощью Kind=Local Json.Net и формат даты ISO, вы получите строку, как
2015-08-05T07:00:00-04. Обратите внимание, что последняя часть (-04) не имеет ничего общего с вашим DateTime или любым смещением, которое вы использовали для его вычисления... это просто чисто смещение часового пояса сервера.между тем, DateTimeOffset явно включает смещение. Он не может включать в себя имя часового пояса, но, по крайней мере, оно включает смещение, и если вы сериализуете его, вы получите явно включенное смещение в свое значение вместо того, чтобы быть локальным временем сервера.
большинство ответов хороши , но я подумал о добавлении еще нескольких ссылок MSDN для получения дополнительной информации
- Краткая история DateTime-by Anthony Moore by BCL team
- выбор между Datetime и DateTime Offset-по MSDN
- не забывайте, что SQL server 2008 и далее имеет новый тип данных как DateTimeOffset
- платформа .NET Framework включает в себя DateTime, DateTimeOffset, и TimeZoneInfo типы, все из которых могут быть использованы для создания приложений это работа с датами и временем.
- выполнение арифметических операций с датами и временем-MSDN
главное отличие в том, что
DateTimeOffsetможет использоваться в сочетании сTimeZoneInfoдля преобразования в местное время в часовых поясах, отличных от текущего.это полезно для серверного приложения (например ASP.NET) который доступен пользователям в разных часовых поясах.
единственная отрицательная сторона DateTimeOffset, которую я вижу, заключается в том, что Microsoft "забыла" (по дизайну) поддерживать его в своем классе XmlSerializer. Но с тех пор он был добавлен в служебный класс XmlConvert.
Я говорю идти вперед и использовать DateTimeOffset и TimeZoneInfo из-за всех преимуществ, просто будьте осторожны при создании сущностей, которые будут или могут быть сериализованы В или из XML (тогда все бизнес-объекты).

Comments