Datalbi  
Créé le 17/05/2016 par Laurent Bourcier

Java SE 8 Programmer : Date et Heure

La classe java.util.Date

C'est la première classe apparue en Java. Aujourd'hui, les méthodes sont presque toutes deprecated mis à part la méthode getTime

// Retourne le nombre de millisecondes depuis le 01-01-1970
long now = new Date().getTime();

Les classe java.util.Calendar et GregorianCalendar

La classe Calendar est une classe abstraite. Elle peut représenter n'importe quel calendrier mais actuellement, seul le calendrier grégorien est implémenté.

Deux méthodes pour avoir un objet Calendar :

Calendar g1 = new GregorianCalendar();
Calendar g2 = Calendar.getInstance();

Calendar gère la date mais aussi l'heure à la milliseconde près.

Positionner la date et l'heure :

Calendar  myCalendar;
myCalendar = Calendar.getInstance();

myCalendat.set(Calendar.YEAR,2016);
myCalendat.set(Calendar.MONTH,4);       // Mois de 0 a 11
myCalendat.set(Calendar.DAY_OF_MONTH,26);
myCalendat.set(Calendar.HOUR_OF_DAY,13);  // Heure de 0 a 23
myCalendat.set(Calendar.MINUTE,0);
myCalendat.set(Calendar.SECOND,0);
myCalendat.set(Calendar.MILLISECOND,0);

Récupérer la date et l'heure :

Calendar  myCalendar;
myCalendar = Calendar.getInstance();

System.out.println(myCalendat.get(Calendar.YEAR,2016));
System.out.println(myCalendat.get(Calendar.MONTH,4));       // Mois de 0 a 11
System.out.println(myCalendat.get(Calendar.DAY_OF_MONTH,26));
System.out.println(myCalendat.get(Calendar.HOUR_OF_DAY,13));  // Heure de 0 a 23
System.out.println(myCalendat.get(Calendar.MINUTE,0));
System.out.println(myCalendat.get(Calendar.SECOND,0));
System.out.println(myCalendat.get(Calendar.MILLISECOND,0));

Opérations sur la date et l'heure :

Calendar  myCalendar;
myCalendar = Calendar.getInstance();

myCalendat.add(Calendar.MONTH,1));
myCalendar.getWeekYear();

Le package java.time

Le package java.time a été introduit dans la version Java 1.8.

Il s'appuie sur le standard ISO-8601 et utilise le calendrier grégorien. Pour utiliser un autre calendrier, il faut utiliser java.time.chrono, qui gère les calendriers non ISO.

La précision va jusqu'à la nanoseconde.

Le package est organisé comme suit :

Chaque classe possède une méthode now() qui renvoie un objet représentant la date/heure en cours.

Les enumerations java.time.DayOfWeek et java.time.Month

Local lc = new Locale("fr");

// Affichage de lundi
DayOfMonth monday = DayOfMonth.MONDAY;
System.out.println(monday.getDisplayName(TextStyle.FULL, lc));

// Affichage de aout
Month august = Mont.AUGUST;
System.out.println(august.getDisplayName(TextStyle.FULL, lc));

Les classe java.time.Year, java.time.YearMonth et java.time.MonthDay

La classe Year représente une année. Exemple pour savoir si c'est une année bissextile :

Year year = Year.of(2010);
boolean isLeap = year.isLeap();

La classe YearMonth représente le mois d'une année. Exemple pour récupérer le nombre de jours de ce mois :

YearMonth february = YearMonth.of(2016, Month.FEBRUARY);
int number_of_days = february.lengthOfMonth;

La classe MonthDay représente le jour d'un mois.

MonthDay day = MonthDay.of(Month.FEBRUARY, 1);

La classe java.time.LocalDateTime

La classe LocalDataTime possède beaucoup de méthodes.

LocalDateTime d, d2;

d = LocalDateTime.of(2016, Month.APRIL, 26);
d = LocalDateTime.now();
d2 = d.plusMonths(1);               // ajoute un mois au champs mois/annee puis diminue le jour du mois s'il n'est pas valide.
d2 = d.minusDays(1);                // retranche un jour
d2 = d.withDayOfMonth(Month.MAY);   // renvoie une date/time avec un mois différent
DayOfWeek dow = d.getDayOfWeek;     // renvoie le jour de la semaine
String str = d.toString();          // retourne 2016-04-26T13:25:20

Les classes java.time.ZoneId et java.time.ZoneOffset

La classe ZoneId fournit un identifiant unique d'un timezone.

La classe ZoneOffset fournit l'offset par rapport au temps Greenwich/UTC.

ZoneId myZoneId = ZoneId.systemDefault();
String str = myZoneId.getId();     // Renvoie "Europe/Paris"
String str = myZoneId.getDispkayName(TextStyle.FULL, new Locale("fr"));  // Renvoie "Heure d'Europe centrale"

// Pour savoir si on est en heure d'ete :
boolean isDaylightSaving = myZoneId.getRules().isDayLightSaving(ZonedDateTime.now().toInstant());

// Creation de ZoneOffset :
ZoneOffset offset;
offset = ZoneOffset.of(myZoneId);
int seconds = offset.getTotalSeconds();

La méthode getRules() permet de connaitre les regles de cette zone, telles que le passage à l'heure d'été.

La classe java.time.ZonedDateTime

La classe ZonedDateTime combine LocalDateTime et ZoneId. Elle est utilisée pour stocker une date/heure avec Time Zone.

DateTimeFormatter format;
LocalDateTime localDt;
ZoneId zone;
ZonedDateTime zonedDt;

format = DateTimeFormatter.ofPattern("YYYY-MM-DD HH:mm:ss");
localDt = LocalDateTime.of(2012, Month.APRIL, 26);
zone = ZoneId.of("Europe/Paris");

zonedDt = ZonedDateTime.of(localDt, zone);
System.out.println(zonedDt.format(format));

// Ou encore plus simple :
System.out.println(ZonedDateTime.now(), DateTimeFormatter.ISO_ZONED_DATE_TIME);

// Convertion dans une autre zone :
zone2 = ZoneId.of("Asia/Tokyo");
zonedDt2 = zonedDt.withZoneSameInstant(zone2);

Les classe java.time.OffsetDateTime et OffsetTime

La classe OffsetDateTime combine LocalDateTime et ZoneOffset.

La classe OffsetTime combine LocalTime et ZoneOffset (mais il est rare qu'on n'ai pas besoin de la date en général).

DateTimeFormatter format;
LocalDateTime localDt;
ZoneOffset offset;
OffsetDateTime offsetDt;

format = DateTimeFormatter.ofPattern("YYYY-MM-DD HH:mm:ss");
localDt = LocalDateTime.of(2012, Month.APRIL, 26);
offset = ZoneOffset.of("+01:00");

offsetDt = OffsetDateTime.of(localDt, offset);
System.out.println(offsetDt.format(format));

La classe java.time.Instant

La classe Instant représente un instant dans le temps. La précision est la nanoseconde.

Elle permet de convertir des instant en secondes depuis EPOCH. Elle contient les méthodes minusXXX et plusXXX.

Instant instant = Instant.now();
long secondsFromEpoch = instant.getEpochSecond();

Les classes java.time.Duration et java.time.Period

La classe Duration représente la durée entre deux instants en terme de secondes, de nanosecondes.

Elle permet de convertir des instant en secondes depuis EPOCH. Elle contient les méthodes minusXXX et plusXXX.

La classe Period représente la durée entre deux instants en terme d'années, de mois, de jours.

Instant instant1 = Instant.now();
...
Instant instant2 = Instant.now();
long ns = Duration.between(instant1, instant2).toNanos();

LocalDate today = LocalDate.now();
LocalDate birthday = LocalDate.of(1972, Month.APRIL, 26);
Period p = Period.between(birthday, today);
System.out.println("You are "+p.getYears()+" years, "+p.getMonths()+" months, "+p.getDays()+" days old.");

La classe java.time.format.DateTimeFormatter (parse et format)

La plupart des classes temporelles possèdent une méthode parse et un méthode format, qui prennent en paramètre un object de la classe DateTimeFormatter.

DateTimeFormatter format;
ZonedDateTime zonedDt, zonedDt2;

format = DateTimeFormatter.ofPattern("YYYY-MM-DD HH:mm:ss");
zonedDt = ZonedDateTime.of(2012, Month.APRIL, 26);

// Formatting
System.out.println(zonedDt.format(format));
// Parsing
zonedDt2 = ZonedDateTime.parse(strInput, format);

Les principaux formats sont :

Le package java.time.temporal

Ce package offre des interfaces sur les objets date/heure.

Par exemple, l'interface temporalAccessor dispose des méthodes get(TemporalField field), getLong(TemporalField field).

Ainsi, des méthodes peuvent manipuler des objets de l'interface TemporalAccessor, quelquesoit la classe d'origine (LocalDateTime, ZonedDateTime, OffsetDateTime).

La classe TemporalAdjusters (avec un s) implémente l'interface TemporalAdjuster (sans s). Elle permet, entre autre, d'avoir les premier et dernier jours de l'année ou du mois par le biais de méthodes statiques.

LocalDate date = LocalDate.now();

// with est une méthode de l'interface Temporal et LocalDate implémente cette interface.
date2 = date.with(Adjusters.firstDayOfYear()); 
date3 = date.with(Adjusters.lastDayOfMonth());
date4 = date.with(Adjusters.next(DayOfWeek.MONDAY);
date5 = date.with(Month.JULY);