Parsowanie czasu

0

Chcę np. taki format czasu:
002
przeparsować na właściwy czyli:
0002

lub z takiego:
0071
na taki
0011

Macie jakiś dobry pomysł na to?

0

Ja bym dzielił na h m s, po czym napisał, funkcje na parsowanie każdej składowej. Funkcja wypluwała by ilość pełnych jednostek nadrzędnych (w przypadku m, nadrzędne to h), oraz resztę w jednostkach parsowanych. Po przeprasowaniu 3 składowych masz 6 składowe wynikowe - 1 składowa doby, 2-3 składowa godziny x2 , 4-5 składowa minuty x2. 6 składowa sekundy. Teraz musisz to posumować z pamięcią o przeniesieniach lub użyć czegoś w rodzaju klasy DateTime lub TimeSpan - ustawić na 0000 i dodawać sekundy, potem minuty etc. W zasadzie to można zupełnie tą magię wyżej odpuścić i posplitować po dwukropku i dodawać do TimeSpana 0000 sec, min, h bez parsowania tego i będzie. Pytanie czy masz to zrobić szybko, czy ma szybko działać, czy ma być elegancko zrobione. W zależności od potrzeby masz tutaj 2 rozwiązania, a trzeci było by wykluczeniem TimeSPana i ręczne napisanie funkcji do dodawania czasu, który będzie wypluwał coś ala TimeSpan, lub znów składowe z przeniesieniem (coś jak adder w logice cyfrowej).

edyta.

Podana funkcja wyżej jeśli jest gotowa i rozwiązuje problem, to o ile nie jest to problem akademicki jest lepszym rozwiązaniem.

0
Dregorio napisał(a):

Użyj https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html
Mam coś takiego:

DateTimeFormatter readFormatter = DateTimeFormatter.ofPattern("hh:mm:ss.SSS");
LocalTime parsedDate = LocalTime.parse("00:02:3", readFormatter);

i rzuca wyjątek w stylu: Text '003' could not be parsed at index 6

1

Poprawiona wersja:

import java.util.*;
import java.lang.*;
import java.io.*;
import java.time.LocalTime;
import java.time.format.*;

class Ideone
{
	public static void main (String[] args) throws java.lang.Exception
	{
		DateTimeFormatter readFormatter = DateTimeFormatter.ofPattern("H:m:s");
		LocalTime parsedDate = null;
		try {
		   parsedDate = LocalTime.parse("00:12:3", readFormatter);
		} catch(DateTimeParseException e) {
			System.out.println(e);
		}   
		System.out.print(parsedDate);
	}
}


Wynik: 00:12:03

https://ideone.com/tWznbc

3
boleq napisał(a):

lub z takiego:
0071
na taki
0011

Macie jakiś dobry pomysł na to?

Mój dobry pomysł byłby taki, żeby tego nie robić ;) Chyba, że nie masz na decyzję wpływu, bo jest to jakieś zadanie, albo tak się szef uparł, itp., ewentualnie forma ćwiczenia.

Praktycznego sensu w tym nie widzę. Jeśli człowiek wprowadził "06:71" błędnie, to jest mało prawdopodobne, że zrobił to, bo miał na myśli "07:11".

Jeśli coś jest trudne do zaimplementowania (w oparciu o biblioteki standardowe i ogólnodostępne, nawet w bogatym tzw. ekosystemie), to może istnieć ku temu całkiem niezły powód. Moim zdaniem tak jest w tym przypadku.

0

ok próbowałem tak ale wtedy są problemy z;
Text '0000.555' could not be parsed, unparsed text found at index 8

0
boleq napisał(a):

ok próbowałem tak ale wtedy są problemy z;
Text '0000.555' could not be parsed, unparsed text found at index 8

bo formater miał przyjmowac godziny, minuty, sekundy, a ty mu dorzuciłeś do tego milisekundy. Generalnie jest wiele sposobów jak można ograć wiele różnych formatów zapisu czasu, ale najprostszy to walidacja tego co podaje użytkownik i jeżeli masz taką możliwość to tak rób i zaoszczędzisz sobie kodzenia. Zresztą wszystko nie tylko 'czas' warto walidować, bo im więcej użytkowników tym więcej głupich pomysłów i czasem prób 'hackowania' systemu

0
V-2 napisał(a):

Jeśli coś jest trudne do zaimplementowania (w oparciu o biblioteki standardowe...

Co tu jest takie trudne? Wyrażenie regularne z grupami i jazda. Tak, wiem, wtedy będziesz miał 2 problemy, ale dla autora tego powiedzonka już i tak jesteś stracony, bo używasz Javy. ;)

1
xy napisał(a):

Co tu jest takie trudne? Wyrażenie regularne z grupami i jazda. Tak, wiem, wtedy będziesz miał 2 problemy, ale dla autora tego powiedzonka już i tak jesteś stracony, bo używasz Javy. ;)

Samo używanie regexów, do wydawałoby się, trywialnej operacji można już uznać za trudne.
@V-2 raczej chodziło o sam problem. Otrzymujemy dane w wielu różnych formatach, nie mówiąc o godzinach typu 6:71. Jeśli takie dane otrzymaliśmy i próbujemy je obsłużyć, to coś dziwnego dzieje się na wejściu i raczej wydawałoby się, że to tam należy sprawdzić, dlaczego tak się dzieje i uniemożliwić wprowadzanie nieprawidłowych dat.

No, chyba, że te daty, z jakiegoś powodu są w danej aplikacji prawidłowe, ale na to musi istnieć naprawdę dobre uzasadnienie.

I na tym skupia się @V-2 - dlaczego w ogóle uznajemy, że godzina 6:71 jest uznawana za prawidłową? Dlaczego wejście nie może nam zapewnić jakiegoś standardowego, znormalizowanego formatu daty? Może nie ma sensu wymyślać mechanizmu do obsługi czegoś, co jest błędne, tylko po prostu poprawić tamten błąd u źródła?
Już nawet nie skupiając się na tym konkretnym przypadku, zbyt często widziałem, jak developerzy wymyślali rozwiązania na jakiś swój konkretny problem, powstawały jakieś potworki, nikt nie chciał z danym systemem pracować, bo ma niewygodne API. Ale nikt nie pomyślał o tym, że to API można poprawić, uporządkować i sprawić, by praca z nim była przyjemna, dopóki jest jeszcze na to czas (np. nie utworzono jeszcze zbyt wielu zależności i można sobie pozwolić na drobny refaktor już istniejących).
Niestety, przez takie podejście task oriented, zbyt często rozwiązując swój problem, obchodzimy tylko realny, globalny problem, a potem napotykamy ten słynny technical debt.

Wracając do tematu OPa - oczywiście, pewnie najprościej obsłużyć to regexami z grupami (choć, czy najefektywniej? jakie rzeczywiście będą formaty danych? czy ktoś nie może sobie wprowadzić danych, które doprowadzą do zwiększenia obciążenia na potrzeby weryfikacji regexa i nie spowodują jakiegoś DoSa?),

Problem z regexami jest taki, że zaczynamy od jakiegoś prostego i naiwnego ^(?:(?:\d{1,2}-){2}(?:\d{2}|\d{4}))(?:[tT ](\d{1,2}:){2}(?:\d{1,2}))?$ potem robimy kilka "prostych" modyfikacji i powstają takie regexy jak ten:

^(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:Z|[+-][01]\d:[0-5]\d)$
3
xy napisał(a):
V-2 napisał(a):

Jeśli coś jest trudne do zaimplementowania (w oparciu o biblioteki standardowe...

Co tu jest takie trudne? Wyrażenie regularne z grupami i jazda.

Trudne do zaimplementowania w oparciu o biblioteki standardowe - napisałem przecież. Czyli "trudne" w tym sensie, że trudno jest wymusić na nich oczekiwane zachowanie, i praktycznie rzecz biorąc musimy je obchodzić, własną ścieżką. Np. w taki sposób jak podałeś. Już to powinno skłonić inżyniera do refleksji.

catom napisał(a):

@V-2 raczej chodziło o sam problem. Otrzymujemy dane w wielu różnych formatach, nie mówiąc o godzinach typu 6:71. Jeśli takie dane otrzymaliśmy i próbujemy je obsłużyć, to coś dziwnego dzieje się na wejściu i raczej wydawałoby się, że to tam należy sprawdzić, dlaczego tak się dzieje i uniemożliwić wprowadzanie nieprawidłowych dat.

Tak, między innymi o to mi chodzi. "Domyślny" system, który po cichu poprawia nieprawidłowe dane, jest moim zdaniem gorszy, niż system prosty. Jeśli użytkownik wpisał (dajmy na to) czas okrążenia 1:77, to czy na pewno chodziło mu o 2:17? A może chciał raczej wpisać 1:7 (czyli 1:07), tylko mu rączka zadygotała?

- Mamo, wychodzę!
- Dobrze, o której wracasz? Obiad jest na drugą.
- Będę najpóźniej na dwunastą dziewięćdziesiąt!
- Trzynastą trzydzieści, tak?
- O w mordę, no tak, znowu się przejęzyczyłem - zafrasował się autor tego pomysłu (w epoce dziecięcej beztroski jeszcze).
- Co ja ci mówiłam o wyrażeniach regularnych - oburzyła się matka. I słusznie się oburzyła

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