webentwicklung-frage-antwort-db.com.de

Warum kann ich in Java.time keine Dauer in Minuten oder Stunden erhalten?

Von der Duration -Klasse in der neuen JSR 310 date-API ( Java.time-Paket ), die in Java 8 und höher verfügbar ist, sagt der Javadoc:

Diese Klasse modelliert eine Menge oder Zeitdauer in Sekunden und Nanosekunden. Auf ihn kann mit anderen auf Dauer bezogenen Einheiten zugegriffen werden, z. B. als Minuten und Stunden. Außerdem kann die DAYS-Einheit verwendet werden und wird als genau gleich 24 Stunden behandelt, so dass die Sommerzeiteffekte ignoriert werden.

Warum stürzt der folgende Code ab?

Duration duration = Duration.ofSeconds(3000);
System.out.println(duration.get(ChronoUnit.MINUTES));

Dies führt zu einer UnsupportedTemporalTypeException:

Java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Minutes
    at Java.time.Duration.get(Duration.Java:537)

Was ist der empfohlene Weg, um Minuten und Stunden von einem Dauerobjekt zu extrahieren? Müssen wir die Berechnung selbst aus der Anzahl der Sekunden machen? Warum wurde es so umgesetzt?

46
Pierre Henry

"Warum wurde es so umgesetzt?"

Andere Antworten behandeln die toXxx()-Methoden, mit denen die Stunden/Minuten abgefragt werden können. Ich werde versuchen, mit dem Warum umzugehen.

Die TemporalAmount-Schnittstelle und die get(TemporalUnit)-Methode wurden relativ spät im Prozess hinzugefügt. Ich persönlich war nicht ganz überzeugt, dass wir genügend Beweise dafür hatten, wie man das Design in diesem Bereich richtig bearbeiten kann, aber ich war etwas armselig, um TemporalAmount hinzuzufügen. Ich glaube, dass wir dabei die API etwas verwirrt haben.

Im Nachhinein glaube ich, dass TemporalAmount die richtigen Methoden enthält, aber ich glaube, dass get(TemporalUnit) einen anderen Methodennamen hätte haben sollen. Der Grund ist, dass get(TemporalUnit) im Wesentlichen eine Methode auf Framework-Ebene ist - sie ist nicht für den täglichen Gebrauch konzipiert. Leider impliziert der Methodenname get dies nicht, was zu Fehlern wie dem Aufruf von get(ChronoUnit.MINUTES) bei Duration führt.

Die Funktionsweise von get(TemporalUnit) besteht darin, sich vorzustellen, dass ein untergeordneter Rahmen den Betrag als Map<TemporalUnit, Long> betrachtet, wobei Duration eine Map der Größe zwei mit den Schlüsseln SECONDS und NANOS ist.

Auf dieselbe Weise wird Period von den Low-Level-Frameworks als Map der Größe drei betrachtet - DAYS, MONTHS und YEARS (was glücklicherweise weniger Fehler verursacht).

Insgesamt ist der beste Rat für Anwendungscode, die Methode get(TemporalUnit) zu ignorieren. Verwenden Sie stattdessen getSeconds(), getNano(), toHours() und toMinutes().

Eine Möglichkeit, "hh: mm: ss" aus einer Duration zu erhalten, besteht darin, Folgendes zu tun:

LocalTime.MIDNIGHT.plus(duration).format(DateTimeFormatter.ofPattern("HH:mm:ss"))

Überhaupt nicht schön, aber es funktioniert nicht länger als einen Tag.

Neue to…Part-Methoden in Java 9

JDK-8142936 issue wurde jetzt in Java 9 implementiert und fügte die folgenden Methoden hinzu, um auf jeden Teil einer Duration zuzugreifen.

  • toDaysPart
  • toHoursPart
  • toMinutesPart
  • toSecondsPart
  • toMillisPart
  • toNanosPart
58
JodaStephen

Die Dokumentation sagt:

Dies gibt einen Wert für jede der beiden unterstützten Einheiten, SECONDS und NANOS, zurück. Alle anderen Einheiten lösen eine Ausnahme aus.

Also beste Antwort - so haben sie es entworfen.

Sie können einige der anderen Methoden verwenden, um in hours zu gelangen:

long hours = duration.toHours();

oder Minuten :

long minutes = duration.toMinutes();
27
blgt

Um die Stunde/Minute/Sekunde-Komponente "normalisiert" zu erhalten, müssen Sie sie manuell berechnen. Der folgende Code wird im Wesentlichen von der Duration#toString-Methode kopiert:

Duration duration = Duration.ofSeconds(3000);
long hours = duration.toHours();
int minutes = (int) ((duration.getSeconds() % (60 * 60)) / 60);
int seconds = (int) (duration.getSeconds() % 60);
System.out.println(hours + ":" + minutes + ":" + seconds);
7
assylias

Ich möchte zu bigt's Antwort (+1) hinzufügen, die auf die nützliche toHours, toMinutes und andere Konvertierungsmethoden hingewiesen hat. Die Dauerangabe sagt:

Diese Klasse modelliert eine Menge oder Zeit in Sekunden und Nanosekunden. [...]

Der Bereich einer Dauer erfordert die Speicherung einer Zahl, die größer als eine lange ist. Um dies zu erreichen, speichert die Klasse eine lange Sekunde und ein Intellektometer im Nanosekundenbereich, das immer zwischen 0 und 999.999.999 liegt.

Es gibt verschiedene getter -Methoden wie getSeconds, getNano und get(TemporalUnit). Da eine Dauer als Paar (Sekunden, Nanosekunden) dargestellt wird, ist klar, warum get(TemporalUnit) auf Sekunden und Nanosekunden beschränkt ist. Diese Getter-Methoden extrahieren Daten direkt aus der Dauerinstanz und sind verlustfrei. 

Im Gegensatz dazu gibt es eine Vielzahl von To-Methoden, einschließlich toDays, toHours, toMillistoMinutes und toNanos, die conversion für den Duration-Wert ausführen. Diese Konvertierungen sind insofern verlustreich, als sie zum Abschneiden von Daten führen, oder sie können eine Ausnahme auslösen, wenn der Wert für die Dauer nicht im angeforderten Format dargestellt werden kann.

Es ist eindeutig Teil des Designs, dass die get-Methoden Daten ohne Konvertierung extrahieren und die to-Methoden Konvertierungen durchführen.

7
Stuart Marks

Entfernen Sie Hourse und erhalten Sie Minuten

long hours = attendanceDuration.toHours(); long minutes = attendanceDuration.minusHours(hours).toMinutes();

0
user9078671