Obtendo o LocalDateTime do sistema em Noda Time
Pergunta
Qual é a maneira idiomática de obter a hora do sistema como um LocalDateTime
na hora de Noda?O método mais direto que eu poderia pensar seria
var dt = DateTime.Now
LocalDateTime systemTime = new LocalDateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute);
mas dado que Noda Time's todo o propósito é substituir DateTime por algo que tenha uma semântica melhor, presumi que havia um método preferido do que usar DateTime
da maneira acima.O melhor que consegui usando as instalações do Noda é
var zone = NodaTime.TimeZones.BclDateTimeZone.ForSystemDefault();
LocalDateTime systemTime = SystemClock.Instance.Now.InZone(zone).LocalDateTime;
mas isso parece bastante detalhado.
Solução
Seu segundo exemplo é exatamente como você faria isso.Isso é intencionalmente prolixo.Ver Filosofia de design da Noda Time.
Pense nisso em três partes:
Obtenha o momento atual:
// Instant now = SystemClock.Instance.Now; // NodaTime 1.x Instant now = SystemClock.Instance.GetCurrentInstant(); // NodaTime 2.x
Obtenha o fuso horário do sistema.(Esta é a sintaxe preferida)
DateTimeZone tz = DateTimeZoneProviders.Bcl.GetSystemDefault();
Aplique o fuso horário ao instante:
ZonedDateTime zdt = now.InZone(tz);
Sua última etapa para obter um LocalDateTime
é trivial, mas reconheça que, ao fazer isso, você estará eliminando qualquer informação de fuso horário."Local" no NodaTime faz não significa "local para o computador onde o código está sendo executado".(Em outras palavras, não é como DateTimeKind.Local
)
Coisas adicionais para pensar:
Você pode preferir abstrair o relógio usando o
IClock
interface:IClock clock = SystemClock.Instance; // Instant now = clock.Now; // NodaTime 1.x Instant now = clock.GetCurrentInstant(); // NodaTime 2.x
Então você pode passar o relógio como um parâmetro de método ou injetá-lo com sua estrutura DI/IoC favorita.(Autofac, Ninject, StructureMap, tanto faz...).A vantagem é que você pode usar um
NodaTime.Testing.FakeClock
durante seus testes de unidade.Ver Teste de Unidade com Noda Time para mais detalhes.Você também pode preferir passar no
DateTimeZone
para que você possa executar seu código em qualquer lugar sem estar vinculado ao fuso horário do sistema.Isso é importante para aplicativos de servidor, mas nem tanto para aplicativos de desktop/móveis.Se você tiver outro trabalho que use fusos horários da IANA ou se estiver usando a versão .NET Standard do Noda Time, altere a etapa 2 para usar o
Tzdb
fornecedor:DateTimeZone tz = DateTimeZoneProviders.Tzdb.GetSystemDefault();
As zonas TZDB são muito mais precisas que as zonas BCL.O Noda Time mapeará o fuso horário do Windows (BCL) do seu sistema para um fuso horário IANA (TZDB) nesta chamada inicial.
Se você tem curiosidade em saber por que DateTime.Now
é tão compacto enquanto o Noda Time é tão detalhado, tente descompilar DateTime.Now
ou olhando as fontes de referência do MS.Você verá que ele está executando essencialmente as mesmas etapas nos bastidores.