Comment enregistrer correctement DateTime à l'aide d'Entity Framework Core?
J'ai une classe contenant une propriété DateTime. Comment gagner du temps correctement en utilisant Entity Framework Core? Je vais donner un exemple ci-dessous.
J'utilise le format TIMESTAMP pour stocker le DateTime dans la base de données. J'ai un serveur et une base de données (MySQL) qui ont le fuseau horaire +3 (Moscou).
SELECT TIMEDIFF(current_timestamp(), utc_timestamp()); // result = 03:00:00
J'ai également un programme qui peut fonctionner sur le PC de différents utilisateurs. Le programme enregistre l'objet contenant la propriété DateTime dans la base de données:
obj.DateTime = DateTime.Parse("2020-10-13T19:00:00+0300");
Regardons maintenant quelques situations:
Le programme est lancé sur un PC avec un fuseau horaire de +3 (Moscou)
Console.WriteLine (obj.DateTime? .ToString ()); // 2020-10-13 19:00:00
Je vérifie les données dans la base de données en utilisant phpMyAdmin et je vois 2020-10-13 19:00:00. Tout va bien. Le fuseau horaire du PC est égal au fuseau horaire de la base de données, nous voyons donc le même résultat.
Le programme est ouvert sur un PC avec un fuseau horaire de +6: 30 (Yangon)
Console.WriteLine (obj.DateTime? .ToString ()); // 13.10.2020 22:30:00
Je vérifie les données dans la base de données en utilisant phpMyAdmin et je vois 2020-10-13 22:30:00. Échouer! J'aurais dû tout voir en même temps 19h00, pas 22h30. La propriété obj.DateTime contenait la même heure!
Comment puis-je comprendre maintenant que ces enregistrements contiennent une durée égale ? Pourquoi l'EF ne transfère-t-il pas DateTime à l'UTC?
Réponses
Si vous souhaitez enregistrer la base de DateTime sur la zone spécifique, pas l'heure du serveur, je vous suggère de créer un service, et à chaque fois, au lieu d'appeler DateTime, vous appelez ce service. il existe une classe appelée TimeZoneInfo qui représente n'importe quel fuseau horaire dans le monde et elle est disponible sur l' espace de noms système .
Assurez-vous que vous n'utilisez pas DateTime pour obtenir directement la date actuelle
DateTime now = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time"));
Cela convertira un temps universel coordonné (UTC) en heure dans un fuseau horaire spécifié. Vous pouvez en savoir plus sur les identifiants de zone danshttps://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-time-zones
Si vous utilisez l'injection de dépendances:
public class DateTimeService : IDateTime
{
public DateTime Now => TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time"));
}
public interface IDateTime
{
DateTime Now { get; }
}
ou si vous préférez utiliser une classe d'assistance:
public static class DateTimeHelper
{
public static DateTime Now() => TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time"));
}