Parmi les Duration
class de la nouvelle JSR 310 date API ( package Java.time ) disponible dans Java 8 et versions ultérieures, le javadoc indique:
Cette classe modélise une quantité ou une quantité de temps en termes de secondes et nanosecondes. On peut y accéder en utilisant d'autres unités basées sur la durée, telles que sous forme de minutes et d’heures. De plus, l’unité DAYS peut être utilisée et est traitée comme étant exactement égale à 24 heures, en ignorant ainsi les effets de l’heure d'été.
Alors, pourquoi le code suivant plante-t-il?
Duration duration = Duration.ofSeconds(3000);
System.out.println(duration.get(ChronoUnit.MINUTES));
Cela soulève une UnsupportedTemporalTypeException
:
Java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Minutes
at Java.time.Duration.get(Duration.Java:537)
Alors, quelle est la méthode recommandée pour extraire des minutes et des heures d’un objet de durée? Devons-nous calculer nous-mêmes à partir du nombre de secondes? Pourquoi a-t-il été mis en œuvre de cette façon?
"Pourquoi a-t-il été mis en place de cette façon?"
D'autres réponses traitent des méthodes toXxx()
qui permettent d'interroger les heures/minutes. Je vais essayer de comprendre pourquoi.
Les méthodes TemporalAmount
interface et get(TemporalUnit)
ont été ajoutées assez tard dans le processus. Personnellement, je n’étais pas entièrement convaincue que nous avions suffisamment de preuves de la bonne façon de travailler la conception dans ce domaine, mais j’étais légèrement tordue au bras pour ajouter TemporalAmount
. Je crois que, ce faisant, nous avons légèrement confondu l’API.
Avec le recul, je crois que TemporalAmount
contient les bonnes méthodes, mais j'estime que get(TemporalUnit)
aurait dû avoir un nom de méthode différent. La raison en est que get(TemporalUnit)
est essentiellement une méthode de niveau cadre - elle n’est pas conçue pour une utilisation quotidienne. Malheureusement, le nom de la méthode get
n'implique pas cela, ce qui entraîne des bogues tels que l'appel de get(ChronoUnit.MINUTES)
à Duration
.
Donc, la façon de penser à get(TemporalUnit)
est d’imaginer un cadre de bas niveau affichant le montant sous la forme Map<TemporalUnit, Long>
où Duration
est un Map
de taille deux avec les clés SECONDS
et NANOS
.
De la même manière, Period
est considéré à partir des cadres de bas niveau comme un Map
de taille trois - DAYS
, MONTHS
et YEARS
(qui heureusement a moins de risques d’erreurs).
Globalement, le meilleur conseil pour le code d'application est d'ignorer la méthode get(TemporalUnit)
. Utilisez plutôt getSeconds()
, getNano()
, toHours()
et toMinutes()
.
Enfin, une façon d'obtenir "hh: mm: ss" d'un Duration
consiste à faire:
LocalTime.MIDNIGHT.plus(duration).format(DateTimeFormatter.ofPattern("HH:mm:ss"))
Pas beau du tout, mais ça marche moins d'une journée.
to…Part
en Java 9JDK-8142936 issue est maintenant implémenté dans Java 9, en ajoutant les méthodes suivantes pour accéder à chaque partie d'un Duration
.
toDaysPart
toHoursPart
toMinutesPart
toSecondsPart
toMillisPart
toNanosPart
La documentation dit:
Cela renvoie une valeur pour chacune des deux unités prises en charge, SECONDS et NANOS. Toutes les autres unités lèvent une exception.
Donc, la meilleure réponse: c'est la façon dont ils l'ont conçue.
Vous pouvez utiliser d'autres méthodes pour l'obtenir dans hours :
long hours = duration.toHours();
ou minutes :
long minutes = duration.toMinutes();
Pour obtenir les composants heure/minute/seconde de manière "normalisée", vous devez les calculer manuellement - le code ci-dessous est essentiellement copié à partir de la méthode Duration#toString
:
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);
Je voudrais ajouter à la réponse de bigt (+1) qui a souligné l'utile toHours
, toMinutes
et d'autres méthodes de conversion. La spécification de la durée indique:
Cette classe modélise une quantité ou une quantité de temps en termes de secondes et de nanosecondes. [...]
La plage d'une durée nécessite le stockage d'un nombre plus grand que long. Pour y parvenir, la classe stocke un long représentant les secondes et un int représentant une nanoseconde de seconde, qui sera toujours compris entre 0 et 999 999 999.
Il existe diverses méthodes getter telles que getSeconds
, getNano
et get(TemporalUnit)
. Étant donné qu'une durée est représentée par une paire (secondes, nanos), il est clair que get(TemporalUnit)
est limité à secondes et nanos. Ces méthodes getter extraient les données directement à partir de l'instance de durée et sont sans perte.
En revanche, il existe diverses méthodes to, y compris toDays
, toHours
, toMillis
toMinutes
et toNanos
qui font conversion sur la valeur de durée. Ces conversions entraînent des pertes, car elles impliquent la troncature des données. Elles peuvent également générer une exception si la valeur de la durée ne peut pas être représentée dans le format demandé.
Il est clair que les méthodes get extraient les données sans conversion et que les méthodes to effectuent des conversions.
Supprimer Hourse puis obtenir des minutes
long hours = attendanceDuration.toHours();
long minutes = attendanceDuration.minusHours(hours).toMinutes();