Как правильно сохранить DateTime с помощью Entity Framework Core?
У меня есть класс, содержащий свойство DateTime. Как правильно сэкономить время с помощью Entity Framework Core? Ниже я приведу пример.
Я использую формат TIMESTAMP для хранения DateTime в базе данных. У меня есть сервер и база данных (MySQL) с часовым поясом +3 (Москва).
SELECT TIMEDIFF(current_timestamp(), utc_timestamp()); // result = 03:00:00
Еще у меня есть программа, которую могут запускать на ПК разных пользователей. Программа сохраняет в базе данных объект, содержащий свойство DateTime:
obj.DateTime = DateTime.Parse("2020-10-13T19:00:00+0300");
Теперь рассмотрим несколько ситуаций:
Программа запускается на ПК с часовым поясом +3 (Москва)
Console.WriteLine (obj.DateTime? .ToString ()); // 2020-10-13 19:00:00
Я проверяю данные в базе данных с помощью phpMyAdmin и вижу 2020-10-13 19:00:00. Все нормально. Часовой пояс ПК равен часовому поясу базы данных, поэтому мы видим тот же результат.
Программа открыта на ПК с часовым поясом +6:30 (Янгон)
Console.WriteLine (obj.DateTime? .ToString ()); // 13.10.2020 22:30:00
Я проверяю данные в базе данных с помощью phpMyAdmin и вижу 2020-10-13 22:30:00. Неудача! Я должен был увидеть все одновременно в 19:00, а не в 22:30. Свойство obj.DateTime содержало то же время!
Как мне теперь понять, что эти записи содержат одинаковое время ? Почему EF не передает DateTime в UTC?
Ответы
Если вы хотите сохранить базу DateTime для определенной зоны, а не для серверного времени, я предлагаю вам создать службу, и каждый раз вместо вызова DateTime вы вызываете эту службу. есть класс TimeZoneInfo, который представляет любой часовой пояс в мире и доступен в системном пространстве имен.
Убедитесь, что вы не используете DateTime для получения текущей даты напрямую
DateTime now = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time"));
Это преобразует всемирное координированное время (UTC) во время в указанном часовом поясе. Вы можете найти больше об идентификаторах зон вhttps://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-time-zones
Если вы используете инъекцию зависимостей:
public class DateTimeService : IDateTime
{
public DateTime Now => TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time"));
}
public interface IDateTime
{
DateTime Now { get; }
}
или если вы предпочитаете использовать вспомогательный класс:
public static class DateTimeHelper
{
public static DateTime Now() => TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time"));
}