2012-08-12 12 views
5

Użytkownik wprowadza datę i godzinę w osobnych polach tekstowych. Następnie łączę datę i godzinę w datetime. Muszę przekonwertować tę datę i czas na UTC, aby zapisać ją w bazie danych. Mam identyfikator strefy czasowej użytkownika zapisany w bazie danych (wybierają go, gdy się rejestrują). Najpierw próbowałem następujące:Konwertuj datetime wprowadzone przez użytkownika do UTC

string userTimeZoneID = "sometimezone"; // Retrieved from database 
TimeZoneInfo userTimeZone = TimeZoneInfo.FindSystemTimeZoneById(userTimeZoneID); 

DateTime dateOnly = someDate; 
DateTime timeOnly = someTime; 
DateTime combinedDateTime = dateOnly.Add(timeOnly.TimeOfDay); 
DateTime convertedTime = TimeZoneInfo.ConvertTimeToUtc(combinedDateTime, userTimeZone); 

Spowodowało to wyjątek:

The conversion could not be completed because the supplied DateTime did not have the Kind property set correctly. For example, when the Kind property is DateTimeKind.Local, the source time zone must be TimeZoneInfo.Local

Następnie próbowałem ustawienie obiektu tak:

DateTime.SpecifyKind(combinedDateTime, DateTimeKind.Local); 

to nie działa, więc próbowałem:

DateTime.SpecifyKind(combinedDateTime, DateTimeKind.Unspecified); 

To też nie działa. Czy ktoś może wyjaśnić, co muszę zrobić? Czy nawet robię to w prawidłowy sposób? Czy powinienem używać DateTimeOffset?

+0

możliwy duplikat [Konwersja czasu lokalnego na UTC w .NET Framework 3.0] (http://stackoverflow.com/questions/4668921/convert-local-time -to-utc-in-net-framework-3-0) – Shai

+0

@Shai: Oczywiście nie duplikat, ponieważ to pytanie ma: "Muszę używać w .NET Framework 3.0, więc nie mogę używać obiektu TimeZoneInfo." –

+0

@JonSkeet Ahhh tego nie widziałem, może dać OP prowadzenie chociaż .. – Shai

Odpowiedz

7

Podobnie jak wszystkie inne sposoby na DateTime, SpecifyKind nie zmienić istniejącą wartość - zwraca nową wartość. Potrzebne są:

combinedDateTime = DateTime.SpecifyKind(combinedDateTime, 
             DateTimeKind.Unspecified); 

Osobiście polecam korzystania Noda Time co sprawia, tego typu rzeczy raczej jaśniejszej moim zdaniem raczej tendencyjne (jestem głównym autorem). Można by skończyć z tego kodu:

DateTimeZone zone = ...; 
LocalDate date = ...; 
LocalTime time = ...; 
LocalDateTime combined = date + time; 
ZonedDateTime zoned = combined.InZoneLeniently(zone); 
// You can now get the "Instant", or convert to UTC, or whatever... 

W „łagodniej” część jest ponieważ podczas konwersji razy lokalne do określonej strefy, istnieje możliwość, za wartość lokalna jest nieprawidłowy lub niejednoznaczne w strefie czasowej należytym do zmian czasu letniego.

+0

Dzięki Jon! Nie mogę uwierzyć, że to było takie proste! Sprawdzę czas Noda, ponieważ wygląda na znacznie prostszy w użyciu! – HTX9

+0

@ HTX9: Goodo - może się okazać, że początkowo wydaje się bardziej skomplikowany, ponieważ zmusza cię do rzeczywistego ustalenia, jakie dane masz (lokalne, daty i godziny w porównaniu do daty/czasu), jak radzić sobie z niejednoznacznością itp. Są to rzeczy, o których powinieneś pomyśleć, ale API .NET sprawia, że ​​trudniej je zauważyć. Taka jest teoria, w każdym razie :) –

1

Można również spróbować tej

var combinedLocalTime = new DateTime((dateOnly + timeOnly.TimeOfDay).Ticks,DateTimeKind.Local); 
var utcTime = combinedLocalTime.ToUniversalTime(); 
Powiązane problemy