Вопрос

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

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

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

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

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

Это было полезно?

Решение

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

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

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

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

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

    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 во время ваших модульных тестов.Видеть Модульное тестирование с использованием Noda Time для получения более подробной информации.

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

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

    DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
    

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top