Конверсии NodaTime (часть 2). Как?
После моего первого сообщения:
Преобразование DateTime с использованием NodaTime на веб-сайте ASP.Net MVC 3 Razor. Как?
Я пытаюсь найти простой способ конвертировать дату/время между локальным и UTC (в обоих направлениях), используя NodaTime.
Текущее изображение:
- У меня есть дата/время, сохраненное как UTC в базе данных.
- При отображении его пользователю я должен учитывать локальный часовой пояс и соответствующим образом преобразовывать его.
- Когда пользователь предоставляет дату/время в качестве фильтра, мне нужно его вернуть обратно в UTC перед отправкой в SQL-запрос.
Что я до сих пор:
Расширение для преобразования из UTC в локальный (эта часть работает нормально):
public static DateTime UTCtoLocal(this DateTime dateTime)
{
IDateTimeZoneProvider timeZoneProvider = DateTimeZoneProviders.Tzdb;
var utcTimeZone = timeZoneProvider["UTC"];
var dateTimeFromDb = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
var zonedDbDateTime = utcTimeZone.AtLeniently(LocalDateTime.FromDateTime(dateTimeFromDb));
var usersTimezoneId = "Europe/London"; //just an example
var usersTimezone = timeZoneProvider[usersTimezoneId];
var usersZonedDateTime = zonedDbDateTime.WithZone(usersTimezone);
return usersZonedDateTime.ToDateTimeUnspecified();
}
Расширение для преобразования из локальной базы в UTC (эта часть является проблемой):
public static DateTime LocaltoUTC(this DateTime dateTime)
{
IDateTimeZoneProvider timeZoneProvider = DateTimeZoneProviders.Tzdb;
var usersTimezoneId = "Europe/London";
var usersTimezone = timeZoneProvider[usersTimezoneId];
var dateTimeFromDb = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
var zonedDbDateTime = usersTimezone.AtLeniently(LocalDateTime.FromDateTime(dateTimeFromDb));
var utcTimezoneId = "UTC";
var utcTimezone = timeZoneProvider[utcTimezoneId];
var utcZonedDateTime = zonedDbDateTime.WithZone(utcTimezone);
return utcZonedDateTime.ToDateTimeUtc();
}
Что я здесь делаю неправильно?
Ответы
Ответ 1
Ваш UTCToLocal выглядит, как будто он делает больше работы, чем нужно, если честно.
Это должно быть просто:
// Note: the DateTime here must have a "Kind" of Utc.
public static DateTime UTCtoLocal(this DateTime dateTime)
{
Instant instant = Instant.FromDateTimeUtc(dateTime);
IDateTimeZoneProvider timeZoneProvider = DateTimeZoneProviders.Tzdb;
var usersTimezoneId = "Europe/London"; //just an example
var usersTimezone = timeZoneProvider[usersTimezoneId];
var usersZonedDateTime = instant.InZone(usersTimezone);
return usersZonedDateTime.ToDateTimeUnspecified();
}
Аналогично, ваш LocalToUTC должен быть в следующих строках:
// The DateTime here should have a "Kind" of Unspecified
public static DateTime LocaltoUTC(this DateTime dateTime)
{
LocalDateTime localDateTime = LocalDateTime.FromDateTime(dateTime);
IDateTimeZoneProvider timeZoneProvider = DateTimeZoneProviders.Tzdb;
var usersTimezoneId = "Europe/London";
var usersTimezone = timeZoneProvider[usersTimezoneId];
var zonedDbDateTime = usersTimezone.AtLeniently(localDateTime);
return zonedDbDateTime.ToDateTimeUtc();
}
Вам не нужно преобразовывать его в другой часовой пояс: ZonedDateTime
знает, что это такое, и ToDateTimeUtc
будет делать все правильно. Обратите внимание, что здесь нет реального dateTimeFromDb
, потому что если вы переходите от неуказанного DateTime
, предположительно от пользователя...