2013-05-21 19 views
15

Po moim pierwszym poście:Konwersje NodaTime (część 2). Jak?

DateTime conversions using NodaTime on ASP.Net MVC 3 Razor website. How to?

jestem stara się znaleźć łatwy sposób przekonwertować datę/czas pomiędzy lokalnym a UTC (obie strony), stosując NodaTime.

Obecny obraz:

  • mam datę/czas zapisany jako UTC w bazie danych.
  • Podczas wyświetlania tego użytkownikowi powinienem wziąć pod uwagę lokalną strefę czasową i odpowiednio ją przekonwertować.
  • Gdy użytkownik podaje datę/godzinę jako filtr, muszę przekonwertować go z powrotem na UTC przed wysłaniem do zapytania SQL.

Co mam tak daleko:

rozszerzenie do konwersji z UTC do lokalnych (ta część działa poprawnie):

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(); 
    } 

Extension przekonwertować z lokalnym powrotem do UTC (ta część to problem):

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(); 
    } 

Co ja tu robię źle?

Odpowiedz

26

Twój UTCToLocal wygląda, jakby robił więcej pracy niż musi, szczerze mówiąc.

To właśnie powinno być:

// 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(); 
} 

Podobnie Twój LocalToUTC powinny być wzdłuż tych linii:

// 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(); 
} 

Nie trzeba go przekonwertować do innej strefy czasowej: ZonedDateTime wie, co instant jest i ToDateTimeUtc zrobi to, co trzeba. Zauważ, że tutaj nie ma prawdziwego dateTimeFromDb, ponieważ jeśli konwertujesz z nieokreślonego DateTime, prawdopodobnie od użytkownika ...

+0

Jeszcze raz dziękuję, @ ​​Jon. Wypróbuję to. Bądź na bieżąco z dobrą pracą nad NodaTime. – melancia

+0

jaki jest pożytek LocaltoUTC, czy funkcja DateTime.ToUniversalTime() nie powinna działać? dzięki – pajics

+2

@pajics: Nie, ponieważ to zawsze będzie używać strefy czasowej systemu - OP chce korzystać ze strefy czasowej użytkownika. –