Como salvar corretamente o DateTime usando o Entity Framework Core?
Eu tenho uma classe que contém uma propriedade DateTime. Como economizar tempo corretamente usando o Entity Framework Core? Vou dar um exemplo abaixo.
Eu uso o formato TIMESTAMP para armazenar o DateTime no banco de dados. Eu tenho um servidor e banco de dados (MySQL) que tem fuso horário +3 (Moscou).
SELECT TIMEDIFF(current_timestamp(), utc_timestamp()); // result = 03:00:00
Também tenho um programa que pode ser executado no PC de vários usuários. O programa salva o objeto que contém a propriedade DateTime no banco de dados:
obj.DateTime = DateTime.Parse("2020-10-13T19:00:00+0300");
Agora, vamos examinar algumas situações:
O programa é lançado em um PC com fuso horário +3 (Moscou)
Console.WriteLine (obj.DateTime? .ToString ()); // 2020-10-13 19:00:00
Eu verifico os dados no banco de dados usando phpMyAdmin e vejo 2020-10-13 19:00:00. Está tudo bem. O fuso horário do PC é igual ao fuso horário do banco de dados, então vemos o mesmo resultado.
O programa está aberto em um PC com fuso horário +6: 30 (Yangon)
Console.WriteLine (obj.DateTime? .ToString ()); // 13.10.2020 22:30:00
Eu verifico os dados no banco de dados usando phpMyAdmin e vejo 2020-10-13 22:30:00. Falhou! Eu deveria ter visto tudo ao mesmo tempo 19:00, não 22:30. A propriedade obj.DateTime continha o mesmo tempo!
Como posso agora entender que esses registros contêm tempo igual ? Por que o EF não transfere DateTime para o UTC?
Respostas
Se você quiser salvar DateTime com base na zona específica, não no horário do servidor, sugiro que você crie um serviço, e todas as vezes, em vez de chamar DateTime, chame esse serviço. existe uma classe chamada TimeZoneInfo que representa qualquer fuso horário do mundo e está disponível no namespace do sistema .
Certifique-se de não usar DateTime para obter a data atual diretamente
DateTime now = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time"));
Isso converterá um Tempo Universal Coordenado (UTC) para a hora em um fuso horário especificado. Você pode encontrar mais sobre ids de zona emhttps://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-time-zones
Se você estiver usando injeção de dependência:
public class DateTimeService : IDateTime
{
public DateTime Now => TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time"));
}
public interface IDateTime
{
DateTime Now { get; }
}
ou se você preferir usar uma classe auxiliar:
public static class DateTimeHelper
{
public static DateTime Now() => TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time"));
}