W3docs

Java TemporalAdjusters

Calculez des dates relatives en Java avec TemporalAdjusters — firstDayOfMonth, next, previous.

plusDays(7) ajoute sept jours. withDayOfMonth(15) saute au 15. Ces deux méthodes couvrent les cas simples. Un TemporalAdjuster est un objet en forme de fonction que vous passez à Temporal.with(adjuster) pour gérer les cas où la nouvelle date dépend de la date courante d'une manière plus complexe : « le premier lundi du mois prochain », « le dernier jour de ce trimestre », « la Thanksgiving américaine de l'année prochaine ».

L'interface possède une seule méthode :

@FunctionalInterface
interface TemporalAdjuster {
  Temporal adjustInto(Temporal temporal);
}

Vous n'avez généralement pas à l'implémenter. La classe java.time.temporal.TemporalAdjusters (notez le sAdjusters, pluriel) est une boîte à outils d'une douzaine de modificateurs intégrés couvrant les cas courants, et LocalDate.with(adjuster) est la façon de les appliquer.

Le catalogue des intégrés

Importez-les statiquement ; le code se lit mieux ainsi :

import static java.time.temporal.TemporalAdjusters.*;

Ensuite :

ModificateurEffet
firstDayOfMonth()jour → premier jour du même mois
lastDayOfMonth()jour → dernier jour du même mois
firstDayOfNextMonth()jour → premier jour du mois suivant
firstDayOfYear()jour → 1er janvier de la même année
lastDayOfYear()jour → 31 décembre de la même année
firstDayOfNextYear()jour → 1er janvier de l'année suivante
next(DayOfWeek dow)le prochain dow strictement après la date
nextOrSame(DayOfWeek dow)aujourd'hui si c'est dow, sinon le prochain dow
previous(DayOfWeek dow)le dow le plus récent strictement avant la date
previousOrSame(DayOfWeek dow)aujourd'hui si c'est dow, sinon le précédent dow
dayOfWeekInMonth(int ord, DayOfWeek dow)nième jour de la semaine du mois : dayOfWeekInMonth(3, MONDAY) → 3e lundi
firstInMonth(DayOfWeek dow)premier dow du mois (équivalent à dayOfWeekInMonth(1, dow))
lastInMonth(DayOfWeek dow)dernier dow du mois

Les deux moitiés répondent à « quel est le premier/dernier X » (moitié supérieure) et « quel est le prochain/précédent X » (moitié inférieure). Enchaînez-les lorsque la question est plus complexe :

LocalDate firstMondayNextMonth = today.with(firstDayOfNextMonth()).with(nextOrSame(DayOfWeek.MONDAY));

C'est-à-dire « le premier lundi à partir du premier du mois prochain ». Lisez de gauche à droite ; chaque with est une étape.

Appliquer avec with(adjuster)

LocalDate today = LocalDate.now();
LocalDate eom = today.with(lastDayOfMonth());
LocalDate nextMonday = today.with(next(DayOfWeek.MONDAY));
LocalDate thirdFriday = today.with(dayOfWeekInMonth(3, DayOfWeek.FRIDAY));

with existe sur tout Temporal : LocalDate, LocalDateTime, ZonedDateTime, même OffsetDateTime. Le modificateur ne touche que les composants de date — appliquer lastDayOfMonth() à un LocalDateTime laisse l'heure inchangée.

Les modificateurs sont totaux : ils retournent toujours un résultat. Il n'y a pas de chemin d'exception « et si aujourd'hui n'est pas dans le bon mois » — lastDayOfMonth() depuis le 31 janvier est toujours le 31 janvier (le dernier jour est lui-même).

Modificateurs lambda

Comme TemporalAdjuster est une @FunctionalInterface, vous pouvez écrire le vôtre avec une lambda :

TemporalAdjuster nextWorkingDay = t -> {
  LocalDate d = LocalDate.from(t).plusDays(1);
  while (d.getDayOfWeek() == DayOfWeek.SATURDAY || d.getDayOfWeek() == DayOfWeek.SUNDAY) {
    d = d.plusDays(1);
  }
  return d;
};

LocalDate friday = LocalDate.of(2025, 11, 7);
LocalDate monday = friday.with(nextWorkingDay);                 // 2025-11-10

Le schéma : convertir le Temporal entrant dans le type de date souhaité (LocalDate.from(t)), calculer la nouvelle date, la retourner. Le type de retour est Temporal (l'interface), mais le JDK accepte le retour concret.

Pour un usage ponctuel, c'est excessif — incorporez simplement la logique à côté du point d'appel. Pour un calcul que vous utiliserez à plusieurs endroits (prochain jour ouvrable, dernier jour du trimestre, jour férié observé), le regrouper comme modificateur garde les points d'appel lisibles.

ofDateAdjuster pour le cas lambda simple

Si votre modificateur ne fonctionne que sur LocalDate (le cas courant), TemporalAdjusters.ofDateAdjuster(UnaryOperator<LocalDate>) est la fabrique plus propre :

TemporalAdjuster nextWorkingDay = TemporalAdjusters.ofDateAdjuster(d -> {
  LocalDate result = d.plusDays(1);
  while (result.getDayOfWeek().getValue() > 5) {
    result = result.plusDays(1);
  }
  return result;
});

La lambda prend et retourne un LocalDate. La fabrique l'encapsule en tant que TemporalAdjuster. C'est ce que vous utilisez dans 90% des cas lors de l'écriture de modificateurs personnalisés.

Un exemple complet : dates ouvrées, jours fériés, fin de période

Le programme ci-dessous utilise des modificateurs pour le calendrier comptable : fin de mois pour la facturation, dernier jour ouvrable du mois pour la clôture des caisses, premier lundi du mois prochain pour une réunion de planification régulière, un modificateur « prochain jour ouvrable » tenant compte des jours fériés, et le calcul de fin de trimestre.

java— editable, runs on the server

Ce qu'il faut retenir de l'exécution :

  • Les modificateurs intégrés ont couvert les cas limites (firstDayOfMonth, lastDayOfMonth, firstDayOfYear, etc.) sans aucune arithmétique de votre côté. Pour « cette date alignée sur le début/fin de son mois ou de son année », ce sont les bons outils — plus clairs que le calcul manuel withDayOfMonth(1), et immunisés contre les surprises de longueur de mois.
  • next(MONDAY) et previous(FRIDAY) ont retourné des dates strictement différentes ; nextOrSame(TUESDAY) sur un mardi a retourné aujourd'hui. Mémorisez la distinction strict-vs-ou-même ; c'est la source de la plupart des bugs « décalé d'une semaine » quand la date de départ tombe sur le jour de la semaine cible.
  • L'enchaînement firstDayOfNextMonth().nextOrSame(MONDAY) a exprimé « le premier lundi à partir du premier du mois prochain » en deux lectures. La chaîne tient sur une ligne ; l'équivalent manuel en prend six. Enchaîner les modificateurs est la façon idiomatique de les composer.
  • NEXT_BUSINESS_DAY a sauté le week-end et un jour férié en une seule opération. L'ensemble HOLIDAYS était un exemple synthétique à deux éléments ; une implémentation réelle chargerait depuis un service. La forme du modificateur est la même — enveloppez la boucle dans TemporalAdjusters.ofDateAdjuster(...) et vous pouvez l'utiliser dans les appels today.with(NEXT_BUSINESS_DAY) partout.
  • END_OF_QUARTER était un modificateur personnalisé en une ligne qui sélectionnait le troisième mois du trimestre de la date et appliquait lastDayOfMonth(). Le point : les opérations de domaine complexes appartiennent à des constantes TemporalAdjuster nommées, où le point d'appel se lit someDate.with(END_OF_QUARTER) au lieu d'incorporer un bloc arithmétique de six lignes. Gardez la logique du calendrier en un seul endroit.

Et maintenant

TemporalAdjusters clôturent l'API java.time moderne. Les deux derniers chapitres de cette partie couvrent les types hérités que vous rencontrerez dans du code plus ancien : Java Legacy Date Class pour le java.util.Date original, et Java Calendar Class pour java.util.Calendar. Les deux sont toujours présents pour la compatibilité ; les deux ont un chemin de conversion propre vers java.time.

Pratique

Pratique
Vous avez besoin du 'premier lundi du mois prochain' à partir de n'importe quelle date donnée. Quelle expression retourne cette valeur de façon la plus idiomatique ?
Vous avez besoin du 'premier lundi du mois prochain' à partir de n'importe quelle date donnée. Quelle expression retourne cette valeur de façon la plus idiomatique ?
Was this page helpful?