Code Review: Parsowanie daty

Zadanie jest następujące. Mamy w pliku tekstowym dane zawierające m.in datę  z góry w zdefiniowanym formacie a mianowicie 2012/10/05 (piąty październik 2012). Dla uproszczenia, ograniczymy się tylko do dnia, miesiąca i roku, bez czasu. Pierwsze podejście, najgorsze mogłoby wyglądać następująco:

string timestamp = "2012/10/05";
DateTime dateTime = DateTime.Parse(timestamp);
Console.WriteLine(dateTime);

Dlaczego jest to niepoprawne? W niektórych ustawieniach regionalnych (np. USA) format jest następujący “yyyy/dd/MM”  tzn. najpierw jest dzień a potem miesiąc. W PL z kolei jest to zawsze posortowane czyli rok, miesiąc, dzień albo dzień, miesiąc, rok. Jeśli mamy z góry zdefiniowany format, lepiej użyć funkcji ParseExact, która akceptuje jawny format daty:

string timestamp = "2012/10/05";
DateTime dateTime = DateTime.ParseExact(timestamp,"yyyy/MM/dd",null);
Console.WriteLine(dateTime);

W UK powyższy kod zadziała. W Niemczech czy w Polsce już niekoniecznie. Dlaczego? W końcu jawnie określamy format daty i aktualne ustawienia regionalne nie powinny być brane pod uwagę. Niestety tak nie jest ponieważ slash (/) jest znakiem specjalnym tutaj i oznacza po prostu separator zależny od kultury. W Polsce, używa się myślnika(-) i data jest w formacie yyyy-MM-dd.  W jaki sposób zatem prawidłowo parsować datę? Dobrym podejściem jest przekazywanie InvariantCulture tzn.:

string timestamp = "2012/10/05";
DateTime dateTime = DateTime.ParseExact(timestamp,"yyyy/MM/dd",CultureInfo.InvariantCulture);
Console.WriteLine(dateTime);

W takim przypadku mamy pewność, że wszelkie znaki specjalne (takie jak ‘/’) będą traktowane w sposób jednakowy, na wszystkich maszynach, niezależnie od aktualnych ustawień regionalnych. Tak się składa, że InvariantCulture używa jako separatora ‘/’ więc wszystko zgadza się. Innym sposobem jest użycie cudzysłowu aby potraktować ‘/’ jako zwykły znak:

string timestamp = "2012/10/05";
DateTime dateTime = DateTime.ParseExact(timestamp,"yyyy'/'MM'/'dd",null);
Console.WriteLine(dateTime);

Warto zwrócić uwagę na to ponieważ łatwo popełnić błąd jeśli nie wie się, że slash to taki sam znak specjalny jak yyyy czy MM.

Leave a Reply

Your email address will not be published.