Дата и время с учетом поясов – DateTimeOffset
Все мы очень часто пользуемся такой структурой из BCL как DateTime. Но если необходимо учитывать время в разных часовых поясах то, начиная с .NET 3.5 в BCL появилась новая структура DateTimeOffset.
Но многие приложения или их части должны работать в разных часовых поясах. Чтобы учесть часовые пояса в DateTime необходимо внешне конвертировать время из одного значения в другое создав либо метод для конвертации, либо враппер вокруг DateTime, наследоваться же от него не получится, так как это структура. Вот именно DateTimeOffset и решает эту проблему. Фактически это тот же DateTime только с возможностью установить смещение часового пояса.
Разница между ними видна невооруженным глазом, если взглянуть на результат работы следующих двух строчек кода:
Console.WriteLine(DateTime.Now); Console.WriteLine(DateTimeOffset.Now);
DateTimeOffset совместим с DateTime, и значение между ними можно легко конвертировать.
DateTime в DateTimeOffset :
DateTime d1 = DateTime.Now; DateTimeOffset o1 = new DateTimeOffset(d1); DateTimeOffset of1 = new DateTimeOffset(d1, new TimeSpan(-5, 0, 0));Например DateTimeOffset в DateTime:
DateTimeOffset o2 = DateTimeOffset.Now; DateTime d2 = o2.DateTime;Можно также вручную задать значения:
DateTime dt1 = new DateTime(2008, 8, 22, 1, 0, 0); DateTimeOffset do1 = new DateTimeOffset(2008, 8, 22, 1, 0, 0, new TimeSpan(-5, 0, 0));Или производить над ними арифметические действия
DateTime dateTime1 = DateTime.Now; DateTime dateTime2 = DateTime.UtcNow; Console.WriteLine(dateTime1 - dateTime2); DateTimeOffset offset1 = DateTimeOffset.Now; DateTimeOffset offset2 = DateTimeOffset.UtcNow; Console.WriteLine(offset1 - offset2);С DateTimeOffset легко сравнивать значения времени в разных часовых поясах. Например код ниже сравнивает разные на первый взгляд значения в разных часовых поясах. Но результат будет true. Так как в UTC их значение будет одинаковым:
DateTimeOffset ao1 = new DateTimeOffset(2008, 8, 22, 12, 0, 0, new TimeSpan(-5, 0, 0)); DateTimeOffset ao2 = new DateTimeOffset(2008, 8, 22, 9, 0, 0, new TimeSpan(-8, 0, 0)); Console.WriteLine(ao1 == ao2);
Когда же лучше использовать DateTime, а когда DateTimeOffset?
Можно выделить такие сценарии использования:
- DateTimeOffset лучше использовать для значений даты, когда их смещение относительно UTC, т.е. часовой пояс, известны или когда необходимо производить операции с датами из разных часовых поясов. Но это не значит, что необходимо полностью отказаться от DateTime в пользу его аналога со смещением.
- DateTime удобно использовать, когда нет привязки к часовым поясам либо часовой пояс не известен, т.е. просто представить значение даты, например время открытия магазинов
- Также DateTime больше подходит для хранения значений из БД(в SQL Server 2008 есть datetimeoffset) так как в большинстве СУБД не хранится информация о часовом поясе.
- DateTime более подходит для interop сценариев, например OLE Automation, databases, существующее .NET API, где используется DateTime и т.п.
- DateTime с временем 00:00:00 чтобы представить дату, например День рождения
- TimeSpan для указания времени без даты
Ребята из команды BCL пишут DateTimeOffset is the new preferred type to use for the most common date time scenarios.