Artykuł

freeimages.com freeimages.com
wrz 27 2014
0

Czas w .Net cz. 2 - DateTimeOffset i TimeZoneInfo

W poprzednim i zarazem pierwszym odcinku cyklu o czasie, napisałem sporo o klasie DateTime, która jest bazową konstrukcją wykorzystywaną do określenia daty i czasu. Nakreśliłem jej podstawowe wady, zalety i zastosowania. Generalnie warto znać tę klasę i ogółem jest to bardzo dobra opcja, w sytuacji gdy nasza aplikacja nie korzysta ze stref czasowych. Innymi słowy dobrze nadaje się ona do rozwiązań działających lokalnie. Problem pojawia się gdy korzystamy z bazy danych (tym zajmiemy się w kolejnym odcinku) oraz gdy działamy bardziej globalnie. W takim przypadku klasa DateTime może okazać się niewystarczająca. Na szczęście w wersji 3.5 .Net frameworka Microsoft dodał klasy DateTimeOffset oraz TimeZoneInfo, które w znaczący sposób zwiększają nasze możliwości.

DateTimeOffset

Można powiedzieć, że klasa DateTimeOffset to swego rodzaju ładny kontener opakowujący DateTime. W istocie jest to ta sama konstrukcja, z tym że wzbogacona o pole offset, które wyrażone jest obiektem klasy TimeSpan. Obiekt klasy DateTimeOffset można utworzyć na kilka sposobów, m.in poprzez podanie istniejącego obiektu klasy DateTime, bądź też poprzez wykorzystanie statycznych metod Parse (i pochodne), Now, UtcNow itp.:

// 2014-09-14 15:00:00 +02:00
DateTimeOffset dtoSpec = new DateTimeOffset(new DateTime(
	2014, 09, 14, 15, 0, 0, DateTimeKind.Local));
// 2014-09-14 15:00:00 +09:00
DateTimeOffset dtoSeul = new DateTimeOffset(new DateTime(
	2014, 09, 14, 15, 0, 0, DateTimeKind.Unspecified), new TimeSpan(9,0,0));
DateTimeOffset dtoUtcNow = DateTimeOffset.UtcNow;
DateTimeOffset dtoNow = DateTimeOffset.Now;

Możecie teraz zapytać co właściwie daje nam taka klasa? W istocie to bardzo wiele, ponieważ w praktyce możemy utworzyć nowy obiekt przechowujący czas z dowolnej strefy czasowej, niezależnie od tej która funkcjonuje na naszym komputerze.

Możliwe jest tworzenie obiektów które zawierają zarówno czas UTC, jak też czas lokalny, czy np. czas z Seulu (tutaj warto zwrócić uwagę na wartość Unspecified, która w przypadku DateTimeOffset jest bardzo użyteczna do określania przesunięć innych niż lokalne). Na szczęście wartości dla obiektu TimeSpan nie musimy zgadywać sami. Wystarczy wykorzystać w tym celu klasę TimeZoneInfo, o której kilka słów więcej poniżej;-)

TimeZoneInfo

TimeZoneInfo to bardzo użyteczna klasa która przechowuje informacje o konkretnej strefie czasowej. Posiada ona również bogaty zestaw metod statycznych wykorzystywanych bardzo często do konwersji. Nowe obiekty klasy TimeZoneInfo tworzymy za pomocą statycznej metody FindSystemTimeZoneById do której należy przekazać id wybranej strefy czasowej:

TimeZoneInfo mst = TimeZoneInfo.FindSystemTimeZoneById("Myanmar Standard Time");

Tak utworzony obiekt, zawiera informacje o konkretnej strefie czasowej. Tutaj mała uwaga - niektóre właściwości są wrażliwe na ustawienia kulturalne komputera na którym został uruchomiony kod. Jeśli na komputerze jest system z polskim językiem, to właściwość DisplayName zostanie wyświetlona w języku polskim, nawet jeśli w samym programie zmienimy ustawienia kulturowe na inny język. Wartości te pobierane są z rejestru Windowsa.

Wróćmy jednak do naszego obiektu. Mając obiekt TimeZoneInfo bardzo łatwo możemy utworzyć obiekt DateTimeOffset dla konkretnej strefy czasowej:

TimeZoneInfo mst = TimeZoneInfo.FindSystemTimeZoneById("Myanmar Standard Time");
//  DateTime = {2014-09-14 15:00:00}
//  UtcDateTime = {2014-09-14 08:30:00}
DateTimeOffset mdto = new DateTimeOffset(new DateTime(2014, 9, 14, 15, 0, 0, 
    DateTimeKind.Unspecified), mst.GetUtcOffset(mdt));

Warto również zwrócić uwagę na statyczne metody wykorzystywane do konwersji. Spójrzmy jak można łatwo przekonwertować powyższy obiekt do strefy czasowej na Grenlandii:

// 2014-09-14 06:30:00 -02:00
DateTimeOffset dtoGreen = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(mdto, "Greenland Standard Time");

Oprócz tego możemy również skorzystać z poniższych metod konwersji:

TimeZoneInfo.ConvertTime(DateTime.Now, TimeZoneInfo
    .FindSystemTimeZoneById("Greenland Standard Time"));
DateTime convertedDt = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, 
    TimeZoneInfo.FindSystemTimeZoneById("Greenland Standard Time"));
TimeZoneInfo.ConvertTimeToUtc(convertedDt);

Warto samemu sprawdzić jakie w tym przypadku otrzymamy rezultaty;-)

Podsumowanie

W dzisiejszym odcinku opowiedziałem Wam o dwóch dość istotnych klasach związanych z przetwarzaniem czasu w .Net. Obie klasy stoją trochę w cieniu konstrukcji DateTime, choć moim zdaniem oferują one znacznie większe możliwości - przede wszystkim zyskujemy pełną kontrolę nad zapisywaną datą i to niezależnie od tego do jakiej strefy czasowej chcemy ją przypisać. Obie konstrukcje uwzględniają również DST.

W kolejnym odcinku zmiksuję to wszystko w jedną sensowną całość i pokażę jak wykorzystać całą zdobytą wiedzę w pracy z bazą danych.

Cykl

Data ostatniej modyfikacji: 04.10.2014, 15:05.

Podoba Ci się ten wpis? Powiedz o tym innym!

Send to Kindle

Komentarze

blog comments powered by Disqus