JavaScript – sprawdzanie poprawności daty
listopad 3rd, 2009. Brak komentarzy.
Kategorie: JavaScript, Zabawy z kodem.
Będzie krótko i szybko. Problem jest trywialny – użytkownik ma podać datę. Nie ważne, w jaki sposób. Zakładamy, że nie chcemy/nie możemy (niepotrzebne skreślić) używać jakiegoś DatePickera. A nie możemy zostawić tego na głowie użytkownika, bo nawet, jeśli miałaby to być jego data urodzin, w 90% przypadków poda nieprawidłową :)
Najlepiej w ogóle dać użytkownikowi do wyboru (np. z pola SELECT) dni od 1 do 31, wtedy w ok. 50% przypadków powinno być wszystko w porządku :) Jeśli data ma zostać wpisana (a fe, co za rozwiązanie w ogóle?), jest gorzej, ale założenia są te same.
Na początek krótkie wprowadzenie do teorii sprawdzania poprawności daty. Musimy pamiętać o dwóch rzeczach:
- ilości dni w poszczególnych miesiącach
- ilości dni w lutym
Z grubsza to tyle. W kwestii rozwinięcia drugiego punktu, w podstawówce uczą nas, że jeśli rok jest przestępny, luty ma 29 dni, w przeciwnym wypadku 28. I że rok przestępny zdarza się co 4 lata…
…a przynajmniej tak było do 1582 roku. Z definicji wiadomo, że rok jest przestępny, jeśli jest podzielny przez 4, ale nie dotyczy to lat podzielnych przez 100, chyba, że są podzielne przez 400. I tego się trzymamy.
Prosty algorytm sprawdzania, czy rok jest przestępny, podany przez Wikipedię, wygląda następująco:
1 2 3 4 5 6 7 8 | function czyPrzestępny(rok: integer): boolean; begin if (rok mod 4 = 0) and (rok mod 100 <> 0) or (rok mod 400 = 0) then czyPrzestępny=true; else czyPrzestępny=false; end; |
Czyli generalnie po wklepaniu takiej funkcji, moglibyśmy już śmiało pisać algorytm, wyglądający mniej-więcej następująco:
funkcja DataPoprawna(dzien, miesiac, rok) { // ogolne sprawdzenie poprawnosci danych jesli(!jestLiczba(dzien) || !jestLiczba(miesiac) || !jestLiczba(rok) || dzien < 1 || miesiac < 1 || rok < 1) return false; // sprawdzenie dla poszczegolnych miesiecy jesli(miesiac nalezyDo(1, 3, 5, 7, 8, 10, 12) && dzien < 32) return true; // oszczedzamy czas, dzien i tak >= 1 jesli(miesiac nalezyDo(4, 6, 9, 11) && dzien < 31) return true; // jw. // jesli funkcja jeszcze sie wykonuje, to podano albo // luty, albo nieprawdlowa date. Dla wygody: jesli(miesiac != 2) return false; // teraz pozostaje tylko luty: jesli(czyPrzestepny(rok)) jesli(dzien < 30) return true; else jesli(dzien < 29) return true; return false; // na wszelki wypadek :) }
Zaznaczę od razu, że powyższy “algorytm” nie jest zoptymalizowany, bo jest tylko pisanym na szybko przykładem dla zilustrowania problemu.
No dobrze, po co ja to piszę? Miałem podać rozwiązanie w JavaScript, tak? Po co ten pseudokod?
Z czystej przekory :) JavaScript posiada przydatne mechanizmy pobierania dnia/miesiaca/roku ze stringa z datą. Metody obiektu klady Date, takie jak:
.getDate().getMonth().getFullYear()
zwrócą albo pożądaną wartość, albo false, jeśli data jest niepoprawna. Raj na Ziemi!
Nagroda dla tych, którzy dotrwali do końca tego wpisu (albo przewinęli):
1 2 3 4 5 6 7 8 9 10 11 12 13 | function sprawdzDate(dzien, miesiac, rok) { // inwersja na format "amerykanski" :) var date_string = miesiac + "/" + dzien + "/" + rok; var date_obj = new Date(date_string); if(date_obj.getDate() != dzien || // JavaScript liczy miesiace od 0 do 11 date_obj.getMonth() != (miesiac - 1) || date_obj.getFullYear() != rok) return false; return true; } |
Szybciej i łatwiej, prawda?