REGEX dla daty + czasu - gdzie mam błąd?

0

Potrzebuję sprawdzić, czy wpisana przez użytkowanika wartość mieści się w formacie:

yyyy-MM-dd hhss
(chciałbym, żeby np. 2015-3-2 231 albo 2015-03-02 2301 również było poprawną formą)

Do tego celu napisałem następujący kod:

std::string strDateTimeRegex = 
"^(19[0-9][0-9]|20[0-9][0-9])-([1-9]|0[1-9]|1[012])-([1-9]|0[1-9]|[12][0-9]|3[01])\s([1-9]|[01][1-9]|2[1-3]):([1-9]|[0-5][1-9]):([1-9]|[0-5][1-9])$";

	std::regex oREPattern(strDateTimeRegex);
	bool bMatch = std::regex_match(*a_pstrInput, oREPattern);

	std::cout << *a_pstrInput << " -- " << (bMatch ? "Valid" : "Invalid") << std::endl;

a_pstrInput to oczywiście wartość wpisywana przez użytkownika.

Czemu ciągle mam "Invalid"?
Czy jakiś dobry człowiek może mi wskazać, co robię źle?
Bo pierwszy raz mam bawię się regular expressions i na bank robię coś źle... Ale co?

1

Jezu, ale syf. Weź po prostu najpierw splitnij string wejściowy po spacjach. Zvaliduj pierwszą część: i.e. datę. Potem zvaliduj godzinę i będzie. Nie rób takich gównianych regexpow na miliard znaków, o to jest nieczytelne i efektywnie jest bez sensu.

0
IForgotMyPass napisał(a):

Jezu, ale syf. Weź po prostu najpierw splitnij string wejściowy po spacjach. Zvaliduj pierwszą część: i.e. datę. Potem zvaliduj godzinę i będzie. Nie rób takich gównianych regexpow na miliard znaków, o to jest nieczytelne i efektywnie jest bez sensu.

Ja rozumiem, że to nie jest piękne, ale myślałem, że się przy okazji nauczę czegoś nowego i dowiem, gdzie robię błąd. Nie chce parsować stringów, bo się nie dowiem nic nowego i zajmie to milion linijek.

0

No ale to ziomek, masz stringi postaci "x-y-z u-v-w" (czy jakoś tak) to podziel je najpierw po spacji, potem podziel je po znaku '-' a potem validuj osobno (jesli chcesz to regexpami) i będzie prościej.

Im mniejszy problem tym łatwiej go rozwiązać. Dziel i zwyciężaj ;-)

0

Ostatecznie stanęło na dwóch regexach:

//regex pattern for date
string strDateRegex =
		"^(19[0-9][0-9]|20[0-9][0-9])"		//year
		"-"
		"([1-9]|0[1-9]|1[012])"				//month
		"-"
		"([1-9]|0[1-9]|[12][0-9]|3[01])$";		//day
//regex pattern for time
string strTimeRegex =
		"^([1-9]|[01][1-9]|2[1-3])"			//hours
		":"
		"([1-9]|[0-5][1-9])"				//minutes
		":"
		"([1-9]|[0-5][1-9])$";				//seconds

Coś był problem ze spacją (\s). Ale dzięki za pomoc ;)

1

Ja wiem, że Regexpy są fajne, ale przecież to jest jeden z tych przypadków, gdzie się nie powinno ich stosować!
Masz jakąś funkcję do parsowania daty (konwersji stringa na konkretą wartość), użyj tej metody i sprawdzaj czy konwersja wykonała się poprawnie.
Zalety rezygnacji z regexpa w tym miejscu

  • będzie działąc szybciej
  • będzie bardziej zrozumiałe
  • będzie obsługiwać różne lokalizację bez najmniejszego wysiłku
  • nie trzeba będzie rozszyfrowywać regexpa jak do tego będziesz wracał
  • kodu będzie mniej

http://www.cplusplus.com/reference/iomanip/get_time/
http://www.cplusplus.com/reference/ctime/strftime/

0

Nie powinieneś w wyrażeniu regularnym sprawdzać poprawnej logiki (semantyki) takich wyrażeń (z tego twojego sprawdzania wychodzi póki co to, że za poprawną datę przejdzie 31. lutego). Jeżeli chcesz zostać przy regexpach to skróć go do formy "liczba-liczba-liczba liczbaliczba" i resztę sprawdź normalnymi warunkami (co swoją drogą też nie jest trywialne i mało która biblioteka od dat oraz kalendarzy robi to porządnie, włączając w to domyślne implementacje dat w Javie i .NET).

0
Rev napisał(a):

Nie powinieneś w wyrażeniu regularnym sprawdzać poprawnej logiki (semantyki) takich wyrażeń (z tego twojego sprawdzania wychodzi póki co to, że za poprawną datę przejdzie 31. lutego). Jeżeli chcesz zostać przy regexpach to skróć go do formy "liczba-liczba-liczba liczbaliczba" i resztę sprawdź normalnymi warunkami

Założenie było takie, żeby było sprawdzenie, o którym wspominasz: liczba-liczba-liczba liczbaliczba (plus, żeby nie było kwiatków w stylu 2015-13-32 2581). Takie przypadki jak 31. lutego sprawdzam już później.

MarekR22 napisał(a):

Zalety rezygnacji z regexpa w tym miejscu

  • będzie działąc szybciej
  • będzie bardziej zrozumiałe
  • będzie obsługiwać różne lokalizację bez najmniejszego wysiłku
  • nie trzeba będzie rozszyfrowywać regexpa jak do tego będziesz wracał
  • kodu będzie mniej/

No i to jest wartościowa informacja! Dziękuję!

W ogóle to przekonaliście mnie, żebym następnym razem odpuścił sobie takie regexpy :)

0

Moja rada jest taka, jeśli wpisujesz w kod twardo wyrażenie regularne, to w 90% wypadków należy zrobić to kodem.
Regexp jest bardzo dobry jako opcja konfiguracyjna, albo jako dana wejściowa od bardziej rozgarniętego użytkownika.

0

@MarekR22, możesz wyjaśnić?

1 użytkowników online, w tym zalogowanych: 0, gości: 1