Интересности      Книги      Утилиты    

19 ноября 2010 г.

Дата и время с учетом поясов – DateTimeOffset

Все мы очень часто пользуемся такой структурой из BCL как DateTime. Но если необходимо учитывать время в разных часовых поясах то, начиная с .NET 3.5 в BCL появилась новая структура DateTimeOffset.

Но многие приложения или их части должны работать в разных часовых поясах. Чтобы учесть часовые пояса в DateTime необходимо внешне конвертировать время из одного значения в другое создав либо метод для конвертации, либо враппер вокруг DateTime, наследоваться же от него не получится, так как это структура. Вот именно DateTimeOffset и решает эту проблему. Фактически это тот же DateTime только с возможностью установить смещение часового пояса.

Разница между ними видна невооруженным глазом, если взглянуть на результат работы следующих двух строчек кода:

Console.WriteLine(DateTime.Now);

Console.WriteLine(DateTimeOffset.Now);

image

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.

Комментариев нет: