2012-06-13 17 views
6

Potrzebuję przeanalizować ciąg znaków o długości od 98d 01h 23m 45s do milisekund.Łańcuch czasu analizy w milisekundach

Miałem nadzieję, że był odpowiednik SimpleDateFormat na takie czasy, ale nie mogłem nic znaleźć. Czy ktoś poleciłby lub nie próbował użyć SDF do tego celu?

Mój obecny plan jest aby użyć wyrażenia regularnego do meczu z numerami i zrobić coś jak

Pattern p = Pattern.compile("(\\d+)"); 
Matcher m = p.matcher("98d 01h 23m 45s"); 

if (m.find()) { 
    int days = Integer.parseInt(m.group()); 
} 
// etc. for hours, minutes, seconds 

a następnie użyć TimeUnit umieścić to wszystko razem i konwertować do milisekund.

Domyślam się, że moje pytanie brzmi: przesada, czy można to zrobić łatwiej? Pojawiło się wiele pytań dotyczących dat i sygnatur czasowych, ale może trochę inaczej.

+1

Twoje podejście wygląda dobrze. Ostrożnie z 'Integer.parseInt()' i wiodącymi zerami, chociaż. Coś takiego jak "... 08h ..." będzie interpretowane jako ósemkowe i nie będzie parsowane. Usuń wszystkie wiodące zera. –

+0

@PhilippReichart nie jest bezpieczny sposób, w jaki używam go powyżej, ponieważ 'Integer.parseInt (" 08 ")' zwraca '8'? – Craigy

+0

Być może Twoje myślenie o wiodących przestrzeniach. 'System.out.println (" Integer.parseInt ("009")); 'wypisuje" 9 "na moim komputerze' 'h' nie powinien być przekazany do' parseInt', jednak – Gene

Odpowiedz

5

Korzystanie z Pattern jest rozsądnym rozwiązaniem. Ale dlaczego nie użyć pojedynczego, aby uzyskać wszystkie cztery pola?

Pattern p = Pattern.compile("(\\d+)d\\s+(\\d+)h\\s+(\\d+)m\\s+(\\d+)s"); 

Następnie użyj zindeksowanej grupy pobrania.

EDIT:

budynku z dala od swojego pomysłu, ja ostatecznie napisał następujący sposób

private static Pattern p = Pattern 
     .compile("(\\d+)d\\s+(\\d+)h\\s+(\\d+)m\\s+(\\d+)s"); 

/** 
* Parses a duration string of the form "98d 01h 23m 45s" into milliseconds. 
* 
* @throws ParseException 
*/ 
public static long parseDuration(String duration) throws ParseException { 
    Matcher m = p.matcher(duration); 

    long milliseconds = 0; 

    if (m.find() && m.groupCount() == 4) { 
     int days = Integer.parseInt(m.group(1)); 
     milliseconds += TimeUnit.MILLISECONDS.convert(days, TimeUnit.DAYS); 
     int hours = Integer.parseInt(m.group(2)); 
     milliseconds += TimeUnit.MILLISECONDS 
       .convert(hours, TimeUnit.HOURS); 
     int minutes = Integer.parseInt(m.group(3)); 
     milliseconds += TimeUnit.MILLISECONDS.convert(minutes, 
       TimeUnit.MINUTES); 
     int seconds = Integer.parseInt(m.group(4)); 
     milliseconds += TimeUnit.MILLISECONDS.convert(seconds, 
       TimeUnit.SECONDS); 
    } else { 
     throw new ParseException("Cannot parse duration " + duration, 0); 
    } 

    return milliseconds; 
} 
11

Zapoznaj się z PeriodFormatter i PeriodParser z JodaTime library.

Można również użyć PeriodFormatterBuilder zbudować parser dla swoich strun jak ten

String periodString = "98d 01h 23m 45s"; 

PeriodParser parser = new PeriodFormatterBuilder() 
    .appendDays().appendSuffix("d ") 
    .appendHours().appendSuffix("h ") 
    .appendMinutes().appendSuffix("m ") 
    .appendSeconds().appendSuffix("s ") 
    .toParser(); 

MutablePeriod period = new MutablePeriod(); 
parser.parseInto(period, periodString, 0, Locale.getDefault()); 

long millis = period.toDurationFrom(new DateTime(0)).getMillis(); 

Teraz to wszystko (zwłaszcza toDurationFrom(...) część) może wyglądać trudne, ale naprawdę porad można zajrzeć do JodaTime jeśli ciebie "zajmujemy się okresami i czasami w Javie.

Aby uzyskać dodatkowe wyjaśnienia, patrz również at this answer about obtaining milliseconds from JodaTime period.

+1

Dziękuję za bardzo szczegółową odpowiedź! Niestety mam zamiar użyć rozwiązanie, które nie wymaga dodawania dodatkowych zależności, ale jestem pewien, że ktoś użyje twojego kodu – Craigy

+0

Mam! Dzięki! – Tom

4

Nowy java.time.Duration klasa w Java 8 pozwala ci przeanalizować trwania wyjęciu z pudełka:

Duration.parse("P98DT01H23M45S").toMillis(); 

Format jest nieco inny, więc wymagałoby dostosowania przed parsowaniem.

+0

Właśnie miałem opublikować nowe pytanie SO do parsowania "00:07:21.5958786 "i zwracając liczbę całkowitą (w milisach lub w nanosach) Dzięki! Nawiasem mówiąc, dokumentacja została przeniesiona, więc warto zauważyć, że polecasz java.time.Duration, a nie inne klasy Duration. – Daniel

+0

dzięki, naprawiono zepsuty link – Andrejs

Powiązane problemy