Java LocalTime
Représentez des heures sans date ni fuseau horaire en Java avec LocalTime.
LocalTime est le miroir de LocalDate : une heure de la journée — heure, minute, seconde, nanoseconde — sans date ni fuseau horaire. Il représente la même lecture d'horloge murale chaque jour du calendrier, partout : LocalTime.of(9, 30) correspond à neuf heures et demie, n'importe quel jour dans n'importe quelle ville.
C'est le bon type pour une heure récurrente de la journée — ouverture d'un magasin à 09:30, une tâche quotidienne de type cron à 03:15, une réunion qui commence à 14:00 quel que soit le jour. Ce n'est pas le bon type pour "le moment où l'utilisateur a cliqué sur Envoyer à 14:30 aujourd'hui" — cela nécessite une date, et probablement un fuseau horaire. Les deux combinés donnent LocalDateTime, le sujet du chapitre suivant.
Création
LocalTime now = LocalTime.now(); // current time in the JVM default zone
LocalTime nine = LocalTime.of(9, 0); // hour, minute
LocalTime nineThirty = LocalTime.of(9, 30, 15); // hour, minute, second
LocalTime nineThirtyNanos = LocalTime.of(9, 30, 15, 500_000_000); // + nanosecond (0 ..999_999_999)
LocalTime parsed = LocalTime.parse("09:30:15"); // ISO-8601 HH:mm[:ss[.nnnnnnnnn]]Les constantes prédéfinies sont utiles pour les conditions aux limites :
LocalTime.MIDNIGHT // 00:00
LocalTime.NOON // 12:00
LocalTime.MIN // 00:00:00.000000000
LocalTime.MAX // 23:59:59.999999999MIN et MAX sont particulièrement utiles lorsqu'on les combine avec un LocalDate pour couvrir toute une journée : LocalDateTime.of(date, LocalTime.MIN) correspond à "minuit au début de la date" ; LocalTime.MAX est la dernière nanoseconde représentable de la journée.
Résolution : nanosecondes
LocalTime est précis à la nanoseconde — neuf champs de résolution (1 seconde = 1 000 000 000 ns). Sur la plupart des systèmes d'exploitation, la résolution réelle de l'horloge est en millisecondes (1 000 000 ns chacune) ou en microsecondes (1 000 ns chacune) ; la précision supplémentaire est là pour que le type ne perde pas d'information lors d'interactions avec des systèmes ayant des horloges à résolution plus élevée.
Accesseurs directs :
time.getHour(); // 0-23
time.getMinute(); // 0-59
time.getSecond(); // 0-59
time.getNano(); // 0-999_999_999Il n'y a pas de getMilli() ; si vous voulez des millisecondes, divisez les nanosecondes : time.getNano() / 1_000_000.
Format 24 heures, sans AM/PM
LocalTime utilise le format 24 heures en interne. LocalTime.of(13, 0) correspond à "13h00" et le type ne connaît pas AM/PM. L'analyse de chaînes avec "AM"/"PM" nécessite un DateTimeFormatter personnalisé (le chapitre Analyse des dates couvre cela) — le parse par défaut est uniquement au format ISO-8601 sur 24 heures.
Arithmétique et modifications
Même syntaxe fluide que LocalDate :
time.plusHours(2);
time.plusMinutes(30);
time.plusSeconds(45);
time.plusNanos(500_000);
time.withHour(14); // replace one field
time.withMinute(0);Le comportement de bouclage : chaque méthode plus/minus sur LocalTime boucle silencieusement autour de minuit. LocalTime.of(23, 0).plusHours(2) donne 01:00, pas "demain à 01:00" — il n'y a pas de "demain" dans LocalTime. Si vous avez besoin de savoir si un bouclage s'est produit, utilisez LocalDateTime ou faites le calcul vous-même :
LocalTime late = LocalTime.of(23, 0);
LocalTime later = late.plusHours(2); // 01:00 — silently wrapped
// To detect wrap: compare the new value's getHour with what you expected, or use LocalDateTime.Ce bouclage est documenté et intentionnel, mais c'est un piège si vous l'oubliez. Pour les calculs de type "quand ce quart de travail se termine-t-il ?" pouvant traverser minuit, le bon type est LocalDateTime, pas LocalTime.
Comparaison
time.isBefore(other);
time.isAfter(other);
time.compareTo(other);
time.equals(other);Ordre lexical par heure:minute:seconde:nano. LocalTime implémente Comparable<LocalTime>, vous pouvez donc trier une liste d'heures ou l'utiliser directement comme clé de TreeMap.
Distance
Duration.between et ChronoUnit.X.between fonctionnent tous les deux :
Duration d = Duration.between(start, end);
long minutes = ChronoUnit.MINUTES.between(start, end);
long seconds = ChronoUnit.SECONDS.between(start, end);Le signe : positif lorsque end est après start, négatif sinon. La même mise en garde de bouclage s'applique — Duration.between(LocalTime.of(23, 0), LocalTime.of(1, 0)) est −22 heures, pas +2 heures ; l'API traite 01:00 comme antérieur à 23:00 du même jour notionnel. Pour "le quart de travail s'est poursuivi après minuit", l'arithmétique basée sur LocalDateTime est le bon outil.
Combinaison avec LocalDate
Vous convertirez souvent vers une date avec heure :
LocalDate date = LocalDate.of(2025, 11, 4);
LocalTime time = LocalTime.of(9, 30);
LocalDateTime dt = date.atTime(time); // 2025-11-04T09:30
LocalDateTime dt2 = time.atDate(date); // same thingatTime / atDate sont les méthodes de jonction. Le résultat est un LocalDateTime — toujours sans fuseau horaire, mais maintenant ancré à un jour du calendrier. Le chapitre suivant va plus loin.
Un exemple concret : un petit assistant de planification
Le programme ci-dessous utilise LocalTime pour une tâche de type planning quotidien : définir une fenêtre "heures d'ouverture", vérifier si un moment donné s'y situe, calculer combien de temps avant la prochaine ouverture, et illustrer le piège du bouclage à minuit.
Ce qu'il faut retenir de l'exécution :
LocalTimeaffiché comme09:00,17:30,12:30— la forme canonique ISO-8601 sur 24 heures. Pas d'AM/PM dans le type. Si vous avez besoin d'afficher "5:30 PM" à un utilisateur, le chapitre Formatage des dates contient le formateur approprié ; le type lui-même ne le sait pas.- La vérification "l'heure est-elle dans la fenêtre" utilise
!isBefore(open) && !isAfter(close). C'est l'idiome de l'intervalle semi-ouvert vs fermé — les deux extrémités sont incluses. Pour "strictement à l'intérieur", basculez vers les formes non niées. Duration.between(LocalTime.of(22, 0), LocalTime.of(2, 0))a renvoyéPT-20H, pasPT4H.LocalTimen'a aucune notion de "jour suivant" — lorsqueendest plus tôt questarten termes d'horloge, la durée devient négative. Pour un quart de travail qui traverse minuit, changez les entrées enLocalDateTimeet laissez les dates résoudre l'ambiguïté. C'est le piège principal deLocalTime.LocalTime.of(23, 30).plusHours(2)a renvoyé01:30. Le bouclage est silencieux — pas d'exception, pas de drapeau, pas de report dans la date. Si vous avez besoin de savoir "est-ce que ça a bouclé ?", utilisezLocalDateTime. Si vous souhaitez vraiment une arithmétique d'horloge modulo 24 (un planning récurrent, par exemple), le bouclage est le comportement correct.date.atTime(time)était la jonction canonique versLocalDateTime. Son miroirtime.atDate(date)produit le même résultat. Vous les utiliserez constamment lorsque vous lirez une heure d'une source et une date d'une autre, puis les combinerez en un seul objet pour l'API en aval.
Prochaine étape
Le chapitre suivant, Java LocalDateTime, combine LocalDate et LocalTime en un troisième type "local" : une date et une heure, toujours sans fuseau horaire. C'est l'unité naturelle pour "cela s'est produit à 14:30 le 4 novembre" lorsque le fuseau horaire est sans importance ou enregistré séparément.