C # DateTime.ToString com quebras de zzz na estrutura dotnet, mas não no núcleo dotnet

Nov 25 2020

Eu tenho minha hora local em GMT +01: 00 como a hora em que escrevo. Eu experimento algo, para mim inesperado, ao fazer um ToString da seguinte maneira. Aqui vamos nós:

Demonstrando as configurações do sistema local com fuso horário +01: 00 (todos estes executados em verde):

var myLocalDate = new DateTime(2020, 11, 25, 08, 00, 00, DateTimeKind.Local);
Assert.AreEqual("2020-11-25T08:00:00+01:00", myLocalDate.ToString(@"yyyy-MM-dd\THH:mm:sszzz"));
Assert.AreEqual(DateTimeKind.Local, myLocalDate.Kind);
Assert.AreEqual(myLocalDate, myLocalDate.ToLocalTime());

E agora eu crio o mesmo tempo, em utc, subtraindo manualmente uma hora e especificando o "utc" como kind. Mas quando chamo ToString, o fuso horário é escrito como +01: 00, que eu esperaria ser +00: 00:

var myUtcDate = new DateTime(2020, 11, 25, 07, 00, 00, DateTimeKind.Utc);
// THIS Breaks:
Assert.AreEqual("2020-11-25T07:00:00+00:00", myUtcDate.ToString(@"yyyy-MM-dd\THH:mm:sszzz"));

Mensagem de erro:

Mensagem: Assert.AreEqual falhou. Esperado: <2020-11-25T07: 00: 00 + 00: 00>. Real: <2020-11-25T07: 00: 00 + 01: 00>.

Sinto falta de algo sobre datas e formatos aqui, ou talvez seja um bug conhecido?

Eu executo o .Net Framework 4.8

Esta postagem é sobre o mesmo problema, eu vejo: Como resolver o erro DateTimeInvalidLocalFormat: "Um DateTime UTC está sendo convertido em texto em um formato que é correto apenas para horários locais."?

ATUALIZAR:

A execução do programa a seguir produz resultados diferentes na estrutura dotnet e no núcleo dotnet (conforme mencionado por evk):

Console.WriteLine(new DateTime(2025, 11, 25, 07, 00, 00, DateTimeKind.Utc).ToString(@"yyyy-MM-dd\THH:mm:sszzz"));

impressões do núcleo dotnet:

2020-11-25T07: 00: 00 + 00: 00

impressões da estrutura dotnet:

2020-11-25T07: 00: 00 + 01: 00

Além disso, ao executar a estrutura dotnet no modo de depuração, a seguinte mensagem do assistente de depuração é exibida, mas é ignorada internamente no DateTime.ToString ():

Assistente de depuração gerenciado 'DateTimeInvalidLocalFormat': 'Um DateTime UTC está sendo convertido em texto em um formato que é correto apenas para horas locais. Isso pode acontecer ao chamar DateTime.ToString usando o especificador de formato 'z', que incluirá um deslocamento de fuso horário local na saída. Nesse caso, use o especificador de formato 'Z', que designa uma hora UTC, ou use a string de formato 'o', que é a maneira recomendada de persistir um DateTime no texto. Isso também pode ocorrer ao passar um DateTime para ser serializado por XmlConvert ou DataSet. Se estiver usando XmlConvert.ToString, passe XmlDateTimeSerializationMode.RoundtripKind para serializar corretamente. Se estiver usando DataSet, defina DateTimeMode no objeto DataColumn como DataSetDateTime.Utc. '

Respostas

5 JonSkeet Nov 25 2020 at 19:09

Não, está se comportando conforme documentado. A partir da documentação do zzzespecificador de formato (grifo meu):

Com os DateTimevalores, o especificador de formato personalizado "zzz" representa o deslocamento assinado do fuso horário do sistema operacional local em relação ao UTC, medido em horas e minutos. Não reflete o valor da DateTime.Kindpropriedade de uma instância . Por esse motivo, o especificador de formato "zzz" não é recomendado para uso com DateTimevalores.

Sem dúvida, isso é lamentável, mas não é um bug.

Observe que o .NET Core (e .NET 5.0) aparentemente não se comporta conforme documentado. Embora você possa argumentar que ele está "consertado" no .NET Core, sugiro que se comportar de forma não documentada é um bug em si mesmo, e pode tornar a migração do código mais difícil do que o esperado.

Eu sugiro que você siga as recomendações da documentação, e evite usar zzzcom DateTimevalores. Eu também sugeriria usar minha biblioteca Noda Time , onde não há ambigüidade em termos de um valor "talvez sendo local, ou talvez sendo UTC", mas isso é um assunto um pouco diferente. (Eu não esperaria que você encontrasse esse problema usando o Horário de Noda, e seu outro código de data / hora ficaria mais claro.)