Guide de java.util.GregorianCalendar

Guide de java.util.GregorianCalendar

1. introduction

Dans ce didacticiel, nous allons jeter un coup d'œil à la classeGregorianCalendar.

2. GregorianCalendar

GregorianCalendar est une implémentation concrète de la classe abstraitejava.util.Calendar. Sans surprise, le calendrier grégorienis the most widely used civil calendar in the world. 

2.1. Obtenir une instance

Il existe deux options disponibles pour obtenir une instance deGregorianCalendar:Calendar.getInstance() et en utilisant l'un des constructeurs.

L'utilisation de la méthode de fabrique statiqueCalendar.getInstance() n'est pas une approche recommandée car elle renverra une instance subjective aux paramètres régionaux par défaut.

Il peut renvoyer unBuddhistCalendar pour le thaï ou unJapaneseImperialCalendar pour le Japon. Ne pas connaître le type de l'instance renvoyée peut conduire à unClassCastException:

@Test(expected = ClassCastException.class)
public void test_Class_Cast_Exception() {
    TimeZone tz = TimeZone.getTimeZone("GMT+9:00");
    Locale loc = new Locale("ja", "JP", "JP");
    Calendar calendar = Calendar.getInstance(loc);
    GregorianCalendar gc = (GregorianCalendar) calendar;
}

En utilisant l'un des sept constructeurs surchargés, nous pouvons initialiser l'objetCalendar soit avec la date et l'heure par défaut en fonction des paramètres régionaux de notre système d'exploitation, soit nous pouvons spécifier une combinaison de date, heure, paramètres régionaux et fuseau horaire.

Comprenons les différents constructeurs par lesquels un objetGregorianCalendar peut être instancié.

Le constructeur par défaut initialisera le calendrier avec la date et l'heure actuelles dans le fuseau horaire et les paramètres régionaux du système d'exploitation:

new GregorianCalendar();

Nous pouvons spécifier leyear, month, dayOfMonth, hourOfDay, minute, et le second pour le fuseau horaire par défaut avec les paramètres régionaux par défaut:

new GregorianCalendar(2018, 6, 27, 16, 16, 47);

Notez que nous n'avons pas à spécifierhourOfDay, minute etsecond car il existe d'autres constructeurs sans ces paramètres.

Nous pouvons passer le fuseau horaire en tant que paramètre pour créer un calendrier dans ce fuseau horaire avec les paramètres régionaux par défaut:

new GregorianCalendar(TimeZone.getTimeZone("GMT+5:30"));

Nous pouvons passer les paramètres régionaux en tant que paramètre pour créer un calendrier dans ces paramètres régionaux avec le fuseau horaire par défaut:

new GregorianCalendar(new Locale("en", "IN"));

Enfin, nous pouvons passer le fuseau horaire et les paramètres régionaux en tant que paramètres:

new GregorianCalendar(TimeZone.getTimeZone("GMT+5:30"), new Locale("en", "IN"));

2.2. Nouvelles méthodes avec Java 8

Avec Java 8, de nouvelles méthodes ont été introduites dansGregorianCalendar.

La méthodefrom() obtient une instance deGregorianCalendar avec les paramètres régionaux par défaut à partir d'un objet ZonedDateTime.

Using getCalendarType() we can get the type of the calendar instance. Les types de calendrier disponibles sont «grégoire», «bouddhiste» et «japonais».

Nous pouvons utiliser ceci, par exemple, pour nous assurer de disposer d'un calendrier d'un certain type avant de poursuivre avec notre logique d'application:

@Test
public void test_Calendar_Return_Type_Valid() {
    Calendar calendar = Calendar.getInstance();
    assert ("gregory".equals(calendar.getCalendarType()));
}

Calling toZonedDateTime() we can convert the calendar object into a ZonedDateTime object qui représente le même point sur la chronologie que ceGregorianCalendar.

2.3. Modifier les dates

Les champs du calendrier peuvent être modifiés à l'aide des méthodesadd(),roll() etset().

The add() method allows us to add time to the calendar in a specified unit basé sur l'ensemble de règles internes de l'agenda:

@Test
public void test_whenAddOneDay_thenMonthIsChanged() {
    int finalDay1 = 1;
    int finalMonthJul = 6;
    GregorianCalendar calendarExpected = new GregorianCalendar(2018, 5, 30);
    calendarExpected.add(Calendar.DATE, 1);
    System.out.println(calendarExpected.getTime());

    assertEquals(calendarExpected.get(Calendar.DATE), finalDay1);
    assertEquals(calendarExpected.get(Calendar.MONTH), finalMonthJul);
}

Nous pouvons également utiliser la méthodeadd() pour soustraire le temps de l'objet calendrier:

@Test
public void test_whenSubtractOneDay_thenMonthIsChanged() {
    int finalDay31 = 31;
    int finalMonthMay = 4;
    GregorianCalendar calendarExpected = new GregorianCalendar(2018, 5, 1);
    calendarExpected.add(Calendar.DATE, -1);

    assertEquals(calendarExpected.get(Calendar.DATE), finalDay31);
    assertEquals(calendarExpected.get(Calendar.MONTH), finalMonthMay);
}

L’exécution de la méthodeadd() force un recalcul immédiat des millisecondes du calendrier et de tous les champs.

Notez que l'utilisation deadd() peut également modifier les champs de calendrier supérieurs (MONTH dans ce cas).

La méthoderoll() ajoute un montant signé au champ de calendrier spécifié sans modifier les plus grands champs. Un champ plus grand représente une unité de temps plus grande. Par exemple,DAY_OF_MONTH est supérieur àHOUR.

Voyons un exemple de cumul de mois.

Dans ce cas,YEAR étant un champ plus grand ne sera pas incrémenté:

@Test
public void test_whenRollUpOneMonth_thenYearIsUnchanged() {
    int rolledUpMonthJuly = 7, orginalYear2018 = 2018;
    GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
    calendarExpected.roll(Calendar.MONTH, 1);

    assertEquals(calendarExpected.get(Calendar.MONTH), rolledUpMonthJuly);
    assertEquals(calendarExpected.get(Calendar.YEAR), orginalYear2018);
}

De même, nous pouvons réduire les mois:

@Test
public void test_whenRollDownOneMonth_thenYearIsUnchanged() {
    int rolledDownMonthJune = 5, orginalYear2018 = 2018;
    GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
    calendarExpected.roll(Calendar.MONTH, -1);

    assertEquals(calendarExpected.get(Calendar.MONTH), rolledDownMonthJune);
    assertEquals(calendarExpected.get(Calendar.YEAR), orginalYear2018);
}

We can directly set a calendar field to a specified value using the set() method. La valeur de temps du calendrier en millisecondes ne sera pas recalculée avant que le prochain appel àget(),getTime(),add() ouroll() ne soit effectué.

Ainsi, plusieurs appels àset() ne déclenchent pas de calculs inutiles.

Voyons un exemple qui définira le champ du mois sur 3 (c.-à-d. Avril):

@Test
public void test_setMonth() {
    GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
    GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
    GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
    calendarExpected.set(Calendar.MONTH, 3);
    Date expectedDate = calendarExpected.getTime();

    assertEquals(expectedDate, calendarDemo.setMonth(calendarActual, 3));
}

2.4. Travailler avecXMLGregorianCalendar

JAXB permet de mapper des classes Java à des représentations XML. Le typejavax.xml.datatype.XMLGregorianCalendar peut aider à mapper les types de schéma XSD de base tels quexsd:date,xsd:time etxsd:dateTime.

Jetons un œil à un exemple de conversion du typeGregorianCalendar en typeXMLGregorianCalendar:

@Test
public void test_toXMLGregorianCalendar() throws Exception {
    GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
    DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
    GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
    GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
    XMLGregorianCalendar expectedXMLGregorianCalendar = datatypeFactory
      .newXMLGregorianCalendar(calendarExpected);

    assertEquals(
      expectedXMLGregorianCalendar,
      alendarDemo.toXMLGregorianCalendar(calendarActual));
}

Une fois que l'objet calendrier a été traduit au format XML, il peut être utilisé dans tous les cas d'utilisation nécessitant la sérialisation d'une date, comme la messagerie ou les appels de service Web.

Voyons un exemple de conversion du typeXMLGregorianCalendar enGregorianCalendar:

@Test
public void test_toDate() throws DatatypeConfigurationException {
    GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
    DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
    XMLGregorianCalendar expectedXMLGregorianCalendar = datatypeFactory
      .newXMLGregorianCalendar(calendarActual);
    expectedXMLGregorianCalendar.toGregorianCalendar().getTime();
    assertEquals(
      calendarActual.getTime(),
      expectedXMLGregorianCalendar.toGregorianCalendar().getTime() );
}

2.5. Comparer des dates

Nous pouvons utiliser la méthodecompareTo() des classesCalendar pour comparer les dates. Le résultat sera positif si la date de base est future et négatif si les données de base se situent au-delà de la date à laquelle nous les comparons à:

@Test
public void test_Compare_Date_FirstDate_Greater_SecondDate() {
    GregorianCalendar firstDate = new GregorianCalendar(2018, 6, 28);
    GregorianCalendar secondDate = new GregorianCalendar(2018, 5, 28);
    assertTrue(1 == firstDate.compareTo(secondDate));
}

@Test
public void test_Compare_Date_FirstDate_Smaller_SecondDate() {
    GregorianCalendar firstDate = new GregorianCalendar(2018, 5, 28);
    GregorianCalendar secondDate = new GregorianCalendar(2018, 6, 28);
    assertTrue(-1 == firstDate.compareTo(secondDate));
}

@Test
public void test_Compare_Date_Both_Dates_Equal() {
    GregorianCalendar firstDate = new GregorianCalendar(2018, 6, 28);
    GregorianCalendar secondDate = new GregorianCalendar(2018, 6, 28);
    assertTrue(0 == firstDate.compareTo(secondDate));
}

2.6. Formatage des dates

Nous pouvons convertirGregorianCalendar dans un format spécifique en utilisant une combinaison deZonedDateTime etDateTimeFormatter pour obtenir la sortie souhaitée:

@Test
public void test_dateFormatdMMMuuuu() {
    String expectedDate = new GregorianCalendar(2018, 6, 28).toZonedDateTime()
      .format(DateTimeFormatter.ofPattern("d MMM uuuu"));
    assertEquals("28 Jul 2018", expectedDate);
}

2.7. Obtenir des informations sur le calendrier

GregorianCalendar fournit plusieurs méthodes get qui peuvent être utilisées pour récupérer différents attributs de calendrier. Examinons les différentes options dont nous disposons:

  • getActualMaximum(int field) renvoie la valeur maximale du champ de calendrier spécifié en tenant compte des valeurs d'heure actuelles. L'exemple suivant renvoie la valeur 30 pour le champDAY_OF_MONTH car juin a 30 jours:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(30 == calendar.getActualMaximum(calendar.DAY_OF_MONTH));
  • getActualMinimum(int field) renvoie la valeur minimale du champ de calendrier spécifié en tenant compte des valeurs d'heure actuelles:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(1 == calendar.getActualMinimum(calendar.DAY_OF_MONTH));
  • getGreatestMinimum(int field) renvoie la valeur minimale la plus élevée pour le champ de calendrier donné:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(1 == calendar.getGreatestMinimum(calendar.DAY_OF_MONTH));
  • getLeastMaximum(int field) Renvoie la valeur maximale la plus basse pour le champ de calendrier donné. Pour le champDAY_OF_MONTH, il s'agit de 28, car février peut ne comporter que 28 jours:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(28 == calendar.getLeastMaximum(calendar.DAY_OF_MONTH));
  • getMaximum(int field) renvoie la valeur maximale pour le champ de calendrier donné:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(31 == calendar.getMaximum(calendar.DAY_OF_MONTH));
  • getMinimum(int field) renvoie la valeur minimale du champ de calendrier donné:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(1 == calendar.getMinimum(calendar.DAY_OF_MONTH));
  • getWeekYear() renvoie leyear of the week  représenté par ceGregorianCalendar:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(2018 == calendar.getWeekYear());
  • getWeeksInWeekYear() renvoie le nombre de semaines dans l'année de la semaine pour l'année civile:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(52 == calendar.getWeeksInWeekYear());
  • isLeapYear() renvoie vrai si l'année est une année bissextile:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(false == calendar.isLeapYear(calendar.YEAR));

3. Conclusion

Dans cet article, nous avons exploré certains aspects deGregorianCalendar.

Comme toujours, l'exemple de code est disponibleover on GitHub.