Подтвердить что ты не робот

Получение системы LocalDateTime в Noda Time

Каков идиоматический способ получить системное время как LocalDateTime в Noda Time? Самый прямой метод, о котором я мог думать, будет

var dt = DateTime.Now
LocalDateTime systemTime = new LocalDateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute);

но учитывая, что Noda Time целая цель - заменить DateTime на что-то, что имеет более приятную семантику, я предположил, что существует предпочтительный метод, чем использовать DateTime в выше способ. Лучшее, что я мог придумать с помощью средств Noda, -

var zone = NodaTime.TimeZones.BclDateTimeZone.ForSystemDefault();
LocalDateTime systemTime = SystemClock.Instance.Now.InZone(zone).LocalDateTime;

но это кажется довольно многословным.

4b9b3361

Ответ 1

Второй пример - именно то, как вы это сделаете. Это намеренно многословно. См. Философия дизайна Noda Time.

Подумайте об этом в трех частях:

  • Получить текущий момент времени:

    // Instant now = SystemClock.Instance.Now;               // NodaTime 1.x
    Instant now = SystemClock.Instance.GetCurrentInstant();  // NodaTime 2.x
    
  • Получить системный часовой пояс. (Это предпочтительный синтаксис)

    DateTimeZone tz = DateTimeZoneProviders.Bcl.GetSystemDefault();
    
  • Применить часовой пояс к моменту:

    ZonedDateTime zdt = now.InZone(tz);
    

Ваш последний шаг при получении LocalDateTime тривиален, но признайте, что когда вы это делаете, вы удаляете информацию о часовом поясе. "Локальный" в NodaTime не означает "локально к компьютеру, на котором работает код". (Другими словами, это не похоже на DateTimeKind.Local)

Дополнительные вещи, о которых нужно подумать:

  • Вы можете отделить часы с помощью интерфейса IClock:

    IClock clock = SystemClock.Instance;
    // Instant now = clock.Now;               // NodaTime 1.x
    Instant now = clock.GetCurrentInstant();  // NodaTime 2.x
    

    Затем вы можете передать часы в качестве параметра метода или добавить его с помощью вашей любимой рамки DI/IoC. (Autofac, Ninject, StructureMap, что угодно...). Преимущество заключается в том, что вы можете использовать NodaTime.Testing.FakeClock во время тестирования устройства. Подробнее см. Unit Testing с временем Noda.

  • Вы также можете перейти в DateTimeZone, чтобы вы могли запускать свой код в любом месте, не привязавшись к системному часовому поясу. Это важно для серверных приложений, но в меньшей степени для настольных/мобильных приложений.

  • Если у вас есть другая работа, использующая часовые пояса IANA, измените шаг 2, чтобы использовать этого провайдера:

    DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
    

    Зоны TZDB намного точнее, чем зоны BCL. Noda Time отобразит ваш часовой пояс вашей системы Windows (BCL) в часовом поясе IANA (TZDB) при этом первоначальном вызове.

Если у вас есть любопытство, почему DateTime.Now настолько компактен, что время Noda так многословно, попробуйте декомпиляцию DateTime.Now или посмотрите на источники справочной системы MS. Вы увидите, что он выполняет те же действия под капотом.