2015-09-03 11 views
9

Die Period Klasse in java.time behandelt nur den datumsorientierten Trank: Jahre, Monate, Tage.Wie mit vollen Zeitraum in java.time umzugehen?

Was ist mit der Zeit Teil: Stunden, Minuten, Sekunden?

Wie können wir Zeichenkettendarstellungen vollständiger Perioden wie in ISO 8601, PnYnMnDTnHnMnS definiert analysieren und generieren? Zum Beispiel eineinhalb Tage: P1DT12H. Das akademische Jahr ist neun Monate, P9M. Jedes Jahr bekomme ich zwei Wochen und drei Tage Urlaub, P17D. Der Kunde besetzte das Hotelzimmer für 2 Tage und 17 1/2 Stunden, P2DT17H30M.

Die Klasse Period in Joda-Time behandelt vollen Zeitraum. Warum nicht in java.time? Gibt es einen anderen Mechanismus?

+0

@Cobebender Dauer ist ein anderes Konzept in java.time. Und die Dauer ist nicht auf weniger als einen Tag beschränkt. Und Dauer kann nicht mit Periode kombiniert werden, um einen ganzen Tag zu bilden, zumindest nicht, dass ich weiß. –

+0

Ich wollte sagen, Dauer und Zeitraum können nicht kombiniert werden, um einen vollen Zeitraum (nicht "Tag") zu erstellen. –

+0

Haben Sie es ... Sie wollen so etwas wie "2 and Halbtage" darstellen. Oder '2 Tage und 1 Stunde'. Nicht "49 Stunden". – Codebender

Antwort

1

org.threeten.extra.PeriodDuration

Das ThreeTen-Extra Projekt bietet eine Klasse eine Period und Duration Kämmen. Einfach PeriodDuration genannt.

Eine Zeitspanne im ISO-8601-Kalendersystem, die einen Punkt und eine Dauer kombiniert.

Diese Klasse modelliert eine Menge oder Menge an Zeit in Form eines Zeitraums und einer Dauer. Ein Zeitraum ist ein datumsbasierter Zeitraum, bestehend aus Jahren, Monaten und Tagen. Eine Dauer ist eine zeitbasierte Zeitspanne, die aus Sekunden und Nanosekunden besteht. Weitere Informationen finden Sie in den Klassen "Periode" und "Dauer".

Die Tage in einem Zeitraum berücksichtigen Sommerzeitänderungen (23 oder 25 Stunden Tage). Bei Berechnungen wird zuerst die Periode und dann die Dauer hinzugefügt.

Caveat: Seien Sie sicher, the Answer by JodaStephen zu lesen, um die Probleme bei dem Versuch, Period und Duration beteiligt zu verstehen, zu kombinieren.

11

In Java SE 8 liegt es in der Verantwortung der Anwendung, eine Klasse zu erstellen, die Period und Duration verbindet, falls dies erforderlich ist.

Beachten Sie, dass ein eine Anzahl von Sekunden enthält, nicht separate Mengen von Sekunden, Minuten und Stunden. Die Anzahl der Sekunden kann 24 Stunden überschreiten, daher kann ein Duration einen "Tag" darstellen. Aber es ist ein fester 24-Stunden-Tag. Im Gegensatz dazu ist die Darstellung eines "Tages in Period beschreibend und berücksichtigt DST. Der Zustand einer Period besteht aus drei getrennten Feldern - Tagen, Monaten und Jahren.

Bedenken Sie, dass" der Kunde die Hotelzimmer für 2 Tage und siebzehn und eine halbe Stunde, P2DT17H30M“hat die Möglichkeit, durch DST cutovers kompliziert zu sein mit Period und Duration separat Dinge sind klar -.. Period von DST cutovers betroffen ist und Duration ist nicht

In Design Die ursprüngliche java.time Period enthielt zwar Stunden, Minuten und Sekunden, dies führte jedoch dazu, dass viele Methoden und komplizierte Javadocs beschrieben werden mussten e alle Möglichkeiten um Normalisierung und DST. Durch die Trennung der Konzepte wird die Interaktion mit der Zeitachse deutlich klarer. Beachten Sie, dass sich die beiden Klassen auch auf das SQL-Design beziehen (Konzepte "Jahr zu Monat" und "Tag zu Sekunde").

Es gibt derzeit keine Pläne, eine neue Klasse für Java SE 9 in diesem Bereich hinzuzufügen, dies kann jedoch nicht vollständig ausgeschlossen werden, da XML/ISO-8601 eine einzige kombinierte Darstellung zulässt.

+1

Danke für die Erklärung der Gründe. Aber ... was ist dann der richtige Weg, um die gesamte Dauer zu bewältigen? Z.B. Wenn ich _Start time plus eine Periode plus eine duration_ brauche, müsste ich folgendes tun: 'String [] periodAndDuration = isoStartTime.split (" T "); Periodendauer = Period.parse (periodAndDuration [0]); Duration duration = Duration.parse ("PT" + periodAndDuration [1]); 'Scheint schrecklich unhandlich ... – kaqqao

+0

Siehe die Antwort von Basil Borque unten, wo die notwendige Klasse zur ThreeTen-Extra-Bibliothek hinzugefügt wurde. – JodaStephen

5

Kurze Antwort in Bezug auf java.time (JSR-310):

Nein, das Paket bietet keine Lösung.

Alternativ können Sie die Klasse Duration im Paket javax.xml.datatype für das Parsen von Strings wie PnYnMnDTnHnMnS verwenden. Dies ist auch in älteren JDK-Versionen seit Java-5 verfügbar. Beispiel:

// parsing 
String iso = "P2Y4M30DT17H5M57.123S"; 
javax.xml.datatype.Duration xmlDuration = 
    DatatypeFactory.newInstance().newDuration(iso); 
int years = xmlDuration.getYears(); 
int months = xmlDuration.getMonths(); 
int days = xmlDuration.getDays(); 
int hours = xmlDuration.getHours(); 
int minutes = xmlDuration.getMinutes(); 
int fullSeconds = xmlDuration.getSeconds(); 
BigDecimal seconds = (BigDecimal) xmlDuration.getField(DatatypeConstants.SECONDS); 

// generating ISO-string 
String xml = xmlDuration.toString(); 
System.out.println(xml); // P2Y4M30DT17H5M57.123S 

Wenn Sie Einschränkungen/Fragen fragen, na ja, hier erhalten Sie eine Liste:

  • Einige (alternative) ISO-Formate wie P0001-04-20T4H nicht analysiert werden können.

  • Einige in javax.xml.datatype.Duration verlassen definierten Methoden auf einem internen Calendar -instance (dokumentiert), so dass diese Verfahren, wenn eine Instanz von Duration möglicherweise nicht sehr großen Werten hält.

  • Die Arbeit mit Sekundenbruchteilen kann umständlich sein und manchmal in der Präzision eingeschränkt sein, wenn Sie mit einer Calendar -Instanz arbeiten.

  • Es gibt nur eine einzige Normalisierungsmethode, die eine Calendar -Instanz verwendet. Zumindest diese Methode berücksichtigt standardmäßig DST-Effekte.

  • Formatierung (nicht einmal lokales Drucken zu erwähnen) wird nicht angeboten.

Wenn Sie diese Probleme überwinden wollen, dann können Sie eine externe Bibliothek betrachten (und ja, ich glaube nicht nur von Joda-Time, deren Präzision millisecs eingeschränkt ist und deren Internationalisierung begrenzt ist, auch). Ansonsten hat das Paket javax.xml.datatype den Vorteil, den Aufwand zum Einbetten einer externen Bibliothek in Ihren Klassenpfad einzusparen.

Update:

über die Frage in Kommentar zu externen Bibliotheken bezogen, ich weiß Joda-Time und meine Bibliothek Time4J.

Erste (Joda-Time) bietet eine spezielle Klasse namens ISOPeriodFormat. Diese Klasse ist auch in der Lage, alternative ISO-Formate zu analysieren (obwohl PyyyyWwwddThhmmss nicht im Original ISO-8601-Papier erwähnt wird, während die Unterstützung für PYYYY-DDD fehlt). Joda-Time definiert einen Builder-gesteuerten Ansatz für Periodenformatierer, der auch für das Drucken von Zeiträumen (Perioden) verwendet werden kann. Darüber hinaus gibt es eine begrenzte Unterstützung für lokales Drucken (mit Version 2.9.3 von Joda-Time in 13 Sprachen). Schließlich bietet die Klasse Period verschiedene Normalisierungsmethoden (siehe javadoc).

zweite (Time4J) bietet die Klassen net.time4j.Duration und zwei Formatierungstools (Duration.Formatter für musterbasierte Druck/Parsing und net.time4j.PrettyTime für lokalisierte Druck in tatsächlich 78 Sprachen). Die Klasse Duration bietet zum Parsen von ISO-Strings die statische Methode parsePeriod(String) sowie verschiedene Normalisierungsmethoden an. Beispiel für die Interoperabilität mit java.time (JSR-310) beweist, dass diese Bibliothek betrachtet und als leistungsstarke Erweiterung von neuem Java-8-date-time-api verwendet werden kann:

// input: using java.time-package 
LocalDateTime start = LocalDateTime.of(2016, 3, 7, 10, 15, 8); 
LocalDateTime stop = LocalDateTime.of(2016, 6, 1, 22, 15); 

// define how you measure the duration (zone correction would also be possible) 
Duration<?> duration = 
    TimestampInterval.between(start, stop).getDuration(
     CalendarUnit.YEARS, 
     CalendarUnit.MONTHS, 
     CalendarUnit.DAYS, 
     ClockUnit.HOURS, 
     ClockUnit.MINUTES, 
     ClockUnit.SECONDS 
    ); 

// generate standard ISO-representation 
String s = duration.toStringISO(); 
System.out.println(s); // P2M25DT11H59M52S 

// parse ISO-String and prove equality with original 
System.out.println(Duration.parsePeriod(s).equals(duration)); // true 

// adding duration to <start> yields <stop> 
System.out.println(start.plus(duration.toTemporalAmount())); // 2016-06-01T22:15 

// format in human time 
System.out.println(PrettyTime.of(Locale.US).print(duration)); 
// output: 2 months, 25 days, 11 hours, 59 minutes, and 52 seconds 

Die Vollständigkeit halber soll ich auch ocpsoft.PrettyTime erwähnen, aber Ich bin mir nicht sicher, ob diese Bibliothek ISO-Strings verarbeiten kann. Es ist eher für relative Zeiten ausgelegt.

+0

Hast du neben Joda-Time noch irgendwelche speziellen externen Bibliotheken im Kopf? Bitte liste sie auf. –