Introduction à Joda-Time

Introduction à Joda-Time

1. introduction

Joda-Time est la bibliothèque de traitement de la date et de l'heure la plus utilisée, avant la sortie de Java 8. Son objectif était de proposer une API intuitive pour le traitement de la date et de l'heure et de résoudre les problèmes de conception de l'API Java Date / Time.

The central concepts implemented in this library were introduced in the JDK core with the release of the Java 8 version. La nouvelle API de date et d'heure se trouve dans le packagejava.time (JSR-310). Un aperçu de ces fonctionnalités peut être trouvé dans cearticle.

Après la sortie de Java 8, les auteurs considèrent que le projet est presque terminé et conseillent d'utiliser l'API Java 8 si possible.

2. Pourquoi utiliser Joda-Time?

L'API de date / heure, avant Java 8, présentait plusieurs problèmes de conception.

Parmi les problèmes, il y a le fait que les classesDate etSimpleDateFormatter ne sont pas thread-safe. Pour résoudre ce problème,Joda-Time uses immutable classes for handling date and time.

La classeDate ne représente pas une date réelle, mais à la place, elle spécifie un instant dans le temps, avec une précision de la milliseconde. L'année enDate commence à partir de 1900, alors que la plupart des opérations de date utilisent généralement l'heure Epoch qui commence à partir du 1er janvier 1970.

De plus, le décalage du jour, du mois et de l'année d'unDate est contre-intuitif. Les jours commencent à 0, tandis que le mois commence à 1. Pour accéder à l'un d'entre eux, nous devons utiliser la classeCalendar. Joda-Time offers a clean and fluent API for handling dates and time.

Joda-Time propose égalementsupport for eight calendar systems, tandis que Java n'en propose que 2: grégorien -java.util.GregorianCalendar et japonais -java.util.JapaneseImperialCalendar.

 3. Installer

Pour inclure la fonctionnalité de la bibliothèque Joda-Time, nous devons ajouter la dépendance suivante à partir deMaven Central:


    joda-time
    joda-time
    2.10

 4. Vue d'ensemble de la bibliothèque

Joda-Time modélise lesconcept of date and time en utilisant les classes du packageorg.joda.time.

Parmi ces classes les plus couramment utilisées sont:

  • LocalDate - représente une date sans heure

  • LocalTime - représente l'heure sans le fuseau horaire

  • LocalDateTime - représente à la fois la date et l'heure sans fuseau horaire

  • Instant - représente un moment exact en millisecondes depuis l'époque Java de 1970-01-01T00: 00: 00Z

  • Duration - représente la durée en millisecondes entre 2 points dans le temps

  • Period - similaire àDuration, mais permettant d'accéder aux composants individuels de l'objet date et heure, comme les années, mois, jours, etc.

  • Interval - représente l'intervalle de temps entre 2 instants

D'autres caractéristiques importantes sont lesdate parsers and formatters. Ceux-ci peuvent être trouvés dans le packageorg.joda.time.format.

Les classes spécifiques decalendar system and time zone se trouvent dans les packagesorg.joda.time.chrono and org.joda.time.tz.

Jetons un coup d'œil à quelques exemples dans lesquels nous utilisons les principales fonctionnalités de Joda-Time pour gérer la date et l'heure.

5. Représenter la date et l'heure

5.1. Date et heure actuelles

The current date, without time information, peut être obtenu en utilisant la méthodenow() à partir de the LocalDate class:

LocalDate currentDate = LocalDate.now();

Lorsque nous n'avons besoin que de l'heure actuelle, sans informations de date, nous pouvons utiliser la classeLocalTime:

LocalTime currentTime = LocalTime.now();

Pour obtenir unrepresentation of the current date and time without considering the time zone, we can use LocalDateTime:

LocalDateTime currentDateAndTime = LocalDateTime.now();

Maintenant, en utilisantcurrentDateAndTime, nous pouvons le convertir en d'autres types d'objets modélisant la date et l'heure.

On peut obtenir un objetDateTime (qui prend en compte le fuseau horaire) en utilisant la méthodetoDateTime(). Lorsque le temps n'est pas nécessaire, nous pouvons le convertir enLocalDate avec la méthodetoLocalDate(), et lorsque nous n'avons besoin que du temps, nous pouvons utilisertoLocalTime() pour obtenir un objetLocalTime:

DateTime dateTime = currentDateAndTime.toDateTime();
LocalDate localDate = currentDateAndTime.toLocalDate();
LocalTime localTime = currentDateAndTime.toLocalTime();

All the above methods have an overloaded method which accepts a DateTimeZone object pour nous aider à représenter la date ou l'heure dans le fuseau horaire spécifié:

LocalDate currentDate = LocalDate.now(DateTimeZone.forID("America/Chicago"));

En outre, Joda-Time offre une excellente intégration avec l'API Java Date et heure. Les constructeurs acceptent un objetjava.util.Date et aussi, nous pouvons utiliser la méthodetoDate() pour renvoyer un objetjava.util.Date:

LocalDateTime currentDateTimeFromJavaDate = new LocalDateTime(new Date());
Date currentJavaDate = currentDateTimeFromJavaDate.toDate();

5.2. Date et heure personnalisées

Pour représenter la date et l'heure personnalisées, Joda-Time nous fournit plusieurs constructeurs. Nous pouvons spécifier les objets suivants:

  • unInstant

  • un objet JavaDate

  • une représentationString de la date et de l'heure au format ISO

  • parties de la date et de l'heure: année, mois, jour, heure, minute, seconde, milliseconde

Date oneMinuteAgoDate = new Date(System.currentTimeMillis() - (60 * 1000));
Instant oneMinutesAgoInstant = new Instant(oneMinuteAgoDate);

DateTime customDateTimeFromInstant = new DateTime(oneMinutesAgoInstant);
DateTime customDateTimeFromJavaDate = new DateTime(oneMinuteAgoDate);
DateTime customDateTimeFromString = new DateTime("2018-05-05T10:11:12.123");
DateTime customDateTimeFromParts = new DateTime(2018, 5, 5, 10, 11, 12, 123);

Une autre façon de définir une date et une heure personnalisées consiste à analyser une représentationString donnée d'une date et d'une heure au format ISO:

DateTime parsedDateTime = DateTime.parse("2018-05-05T10:11:12.123");

Nous pouvons également analyser les représentations personnalisées d'une date et d'une heure en définissant unDateTimeFormatter personnalisé:

DateTimeFormatter dateTimeFormatter
  = DateTimeFormat.forPattern("MM/dd/yyyy HH:mm:ss");
DateTime parsedDateTimeUsingFormatter
  = DateTime.parse("05/05/2018 10:11:12", dateTimeFormatter);

6. Travailler avec la date et l'heure

6.1. Utilisation deInstant

UnInstant représente le nombre de millisecondes entre 1970-01-01T00: 00: 00Z et un instant donné. Par exemple, le moment actuel dans le temps peut être obtenu en utilisant le constructeur par défaut ou la méthodenow():

Instant instant = new Instant();
Instant.now();

Pour créer unInstant pour un moment personnalisé dans le temps, nous pouvons utiliser l'un des constructeurs ou utiliser les méthodesofEpochMilli() etofEpochSecond():

Instant instantFromEpochMilli
  = Instant.ofEpochMilli(milliesFromEpochTime);
Instant instantFromEpocSeconds
  = Instant.ofEpochSecond(secondsFromEpochTime);

Les constructeurs acceptent unString représentant une date et une heure au format ISO, un JavaDate ou une valeurlong représentant le nombre de millisecondes à partir de 1970-01-01T00: 00: 00Z:

Instant instantFromString
  = new Instant("2018-05-05T10:11:12");
Instant instantFromDate
  = new Instant(oneMinuteAgoDate);
Instant instantFromTimestamp
  = new Instant(System.currentTimeMillis() - (60 * 1000));

Lorsque la date et l'heure sont représentées sous forme deString, nous avons la possibilité d'analyser lesString en utilisant le format souhaité:

Instant parsedInstant
  = Instant.parse("05/05/2018 10:11:12", dateTimeFormatter);

Maintenant que nous savons ce que représenteInstant et comment nous pouvons en créer un, voyons comment il peut être utilisé.

Pour comparer aux objetsInstant, nous pouvons utilisercompareTo() car il implémente l'interfaceComparable, mais nous pouvons également utiliser les méthodes API Joda-Time fournies dans l'interfaceReadableInstant qui (t4) s implémente également:

assertTrue(instantNow.compareTo(oneMinuteAgoInstant) > 0);
assertTrue(instantNow.isAfter(oneMinuteAgoInstant));
assertTrue(oneMinuteAgoInstant.isBefore(instantNow));
assertTrue(oneMinuteAgoInstant.isBeforeNow());
assertFalse(oneMinuteAgoInstant.isEqual(instantNow));

Une autre fonctionnalité utile est queInstant can be converted to a DateTime object or event a Java Date:

DateTime dateTimeFromInstant = instant.toDateTime();
Date javaDateFromInstant = instant.toDate();

Lorsque nous avons besoin d'accéder à des parties d'une date et d'une heure, comme l'année, l'heure, etc., nous pouvons utiliser la méthodeget() et spécifier unDateTimeField:

int year = instant.get(DateTimeFieldType.year());
int month = instant.get(DateTimeFieldType.monthOfYear());
int day = instant.get(DateTimeFieldType.dayOfMonth());
int hour = instant.get(DateTimeFieldType.hourOfDay());

Maintenant que nous avons couvert la classeInstant, voyons quelques exemples de la façon dont nous pouvons utiliserDuration,Period etInterval.

6.2. Utilisation deDuration,Period etInterval

UnDuration représente le temps en millisecondes entre deux points dans le temps ou dans ce cas, il pourrait être de deuxInstants. We’ll use this when we need to add or subtract a specific amount of time to or from another Instant without considering chronology and time zones:

long currentTimestamp = System.currentTimeMillis();
long oneHourAgo = currentTimestamp - 24*60*1000;
Duration duration = new Duration(oneHourAgo, currentTimestamp);
Instant.now().plus(duration);

En outre, nous pouvons déterminer combien de jours, heures, minutes, secondes ou millisecondes la durée représente:

long durationInDays = duration.getStandardDays();
long durationInHours = duration.getStandardHours();
long durationInMinutes = duration.getStandardMinutes();
long durationInSeconds = duration.getStandardSeconds();
long durationInMilli = duration.getMillis();

La principale différence entrePeriod etDuration est quePeriod is defined in terms of its date and time components (years, months, hours, etc.) and doesn’t represent an exact number of milliseconds. Lors de l'utilisation des calculs de date et d'heurePeriodwill consider the time zone and daylight saving.

Par exemple, l'ajout d'unPeriod de 1 mois au 1er février entraînera la représentation de la date du 1er mars. En utilisantPeriod, la bibliothèque prendra en compte les années bissextiles.

Si nous devons utiliser unDuration, le résultat ne sera pas correct, car leDuration représente une durée fixe qui ne prend pas en compte la chronologie ou les fuseaux horaires:

Period period = new Period().withMonths(1);
LocalDateTime datePlusPeriod = localDateTime.plus(period);

UnInterval, comme son nom l'indique, représente l'intervalle de date et d'heure entre deux points fixes dans le temps représentés par deux objetsInstant:

Interval interval = new Interval(oneMinuteAgoInstant, instantNow);

La classe est utile lorsque nous devons vérifier si deux intervalles se chevauchent ou calculer l'écart entre eux. La méthodeoverlap() renverra lesInterval ounull qui se chevauchent quand ils ne se chevauchent pas:

Instant startInterval1 = new Instant("2018-05-05T09:00:00.000");
Instant endInterval1 = new Instant("2018-05-05T11:00:00.000");
Interval interval1 = new Interval(startInterval1, endInterval1);

Instant startInterval2 = new Instant("2018-05-05T10:00:00.000");
Instant endInterval2 = new Instant("2018-05-05T11:00:00.000");
Interval interval2 = new Interval(startInterval2, endInterval2);

Interval overlappingInterval = interval1.overlap(interval2);

La différence entre les intervalles peut être calculée en utilisant la méthodegap(), et lorsque nous voulons savoir si la fin d'un intervalle est égale au début d'un autre intervalle, nous pouvons utiliser la méthodeabuts():

assertTrue(interval1.abuts(new Interval(
  new Instant("2018-05-05T11:00:00.000"),
  new Instant("2018-05-05T13:00:00.000"))));

6.3. Opérations de date et heure

Certaines des opérations les plus courantes consistent à ajouter, soustraire et convertir une date et une heure. La bibliothèque fournit des méthodes spécifiques pour chacune des classesLocalDate,LocalTime,LocalDateTime etDateTime. Il est important de noter que ces classes sont immuables afin que chaque appel de méthode crée un nouvel objet de son type.

PrenonsLocalDateTime pour le moment actuel et essayons de changer sa valeur:

LocalDateTime currentLocalDateTime = LocalDateTime.now();

Pour ajouter un jour supplémentaire àcurrentLocalDateTime, nous utilisons la méthodeplusDays():

LocalDateTime nextDayDateTime = currentLocalDateTime.plusDays(1);

Nous pouvons également utiliser la méthodeplus() pour ajouter unPeriod ouDuration à noscurrentLocalDateTime:

Period oneMonth = new Period().withMonths(1);
LocalDateTime nextMonthDateTime = currentLocalDateTime.plus(oneMonth);

Les méthodes sont similaires pour les autres composants de date et d'heure, par exemple,plusYears() pour ajouter des années supplémentaires, plusSeconds () pour ajouter plus de secondes et ainsi de suite.

Pour soustraire un jour de noscurrentLocalDateTime, nous pouvons utiliser la méthodeminusDays():

LocalDateTime previousDayLocalDateTime
  = currentLocalDateTime.minusDays(1);

En plus des calculs avec la date et l’heure, nous pouvons également définir des parties individuelles de la date ou de l’heure. Par exemple, le réglage de l'heure sur 10 peut être obtenu en utilisant la méthodewithHourOfDay(). D'autres méthodes commençant par le préfixe“with” peuvent être utilisées pour définir les composants de cette date ou heure:

LocalDateTime currentDateAtHour10 = currentLocalDateTime
  .withHourOfDay(0)
  .withMinuteOfHour(0)
  .withSecondOfMinute(0)
  .withMillisOfSecond(0);

Un autre aspect important est que nous pouvons convertir un type de classe de date et heure en un autre. Pour ce faire, nous pouvons utiliser des méthodes spécifiques fournies par la bibliothèque:

  • toDateTime() - convertitLocalDateTime en un objetDateTime

  • toLocalDate() - convertitLocalDateTime en un objetLocalDate

  • toLocalTime () - convertit LocalDateTime en un objet LocalTime

  • toDate() - convertitLocalDateTime en un objet JavaDate

7. Travailler avec des fuseaux horaires

Joda-Time nous permet de travailler facilement avec différents fuseaux horaires et de changer de fuseau horaire. Nous avons la classe abstraiteDateTimeZone qui est utilisée pour représenter tous les aspects concernant un fuseau horaire.

The default time zone used by Joda-Time is selected from the user.timezone Java system property. L'API de la bibliothèque nous permet de spécifier, individuellement pour chaque classe ou calcul, quel fuseau horaire doit être utilisé. Par exemple, nous pouvons créer un objet LocalDateTime

Lorsque nous savons que nous utiliserons un fuseau horaire spécifique dans l'ensemble de l'application, nous pouvons définir le fuseau horaire par défaut:

DateTimeZone.setDefault(DateTimeZone.UTC);

A partir de maintenant, toutes les opérations de date et heure, sauf indication contraire, seront représentées dans le fuseau horaire UTC.

Pour voir tous les fuseaux horaires disponibles, nous pouvons utiliser la méthodegetAvailableIDs():

DateTimeZone.getAvailableIDs()

Lorsque nous devons représenter la date ou l'heure dans un fuseau horaire spécifique, nous pouvons utiliser l'une des classesLocalTime,LocalDate,LocalDateTime,DateTime et spécifier dans le constructeur le ObjetDateTimeZone:

DateTime dateTimeInChicago
  = new DateTime(DateTimeZone.forID("America/Chicago"));
DateTime dateTimeInBucharest
  = new DateTime(DateTimeZone.forID("Europe/Bucharest"));
LocalDateTime localDateTimeInChicago
  = new LocalDateTime(DateTimeZone.forID("America/Chicago"));

De même, lors de la conversion entre ces classes, nous pouvons spécifier le fuseau horaire souhaité. La méthodetoDateTime() accepte un objetDateTimeZone ettoDate() accepte l'objet java.util.TimeZone:

DateTime convertedDateTime
  = localDateTimeInChicago.toDateTime(DateTimeZone.forID("Europe/Bucharest"));
Date convertedDate
  = localDateTimeInChicago.toDate(TimeZone.getTimeZone("Europe/Bucharest"));

8. Conclusion

Joda-Time est une bibliothèque fantastique qui a commencé avec l'objectif principal de résoudre les problèmes du JDK concernant les opérations de date et d'heure. Elle est rapidement devenue la bibliothèquede facto pour la gestion de la date et de l'heure et récemment, ses principaux concepts ont été introduits dans Java 8.

Il est important de noter que l'auteur le considère comme“to be a largely finished project” et recommande de migrer le code existant pour utiliser l'implémentation Java 8.

Le code source de l'article est disponibleover on GitHub.