Leitfaden für java.util.GregorianCalendar

Anleitung zu java.util.GregorianCalendar

1. Einführung

In diesem Tutorial werfen wir einen kurzen Blick auf dieGregorianCalendar-Klasse.

2. GregorianCalendar

GregorianCalendar ist eine konkrete Implementierung der abstrakten Klassejava.util.Calendar. Es überrascht nicht, dass der Gregorianische Kalenderis the most widely used civil calendar in the world. 

2.1. Eine Instanz bekommen

Es stehen zwei Optionen zur Verfügung, um eine Instanz vonGregorianCalendar:Calendar.getInstance() abzurufen und einen der Konstruktoren zu verwenden.

Die Verwendung der statischen Factory-MethodeCalendar.getInstance() ist kein empfohlener Ansatz, da eine Instanz subjektiv zum Standardgebietsschema zurückgegeben wird.

Es könnteBuddhistCalendar für Thai oderJapaneseImperialCalendar für Japan zurückgeben. Wenn Sie den Typ der zurückgegebenen Instanz nicht kennen, kann dies zuClassCastException: führen

@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;
}

Mit einem der sieben überladenen Konstruktoren können wir dasCalendar-Objekt entweder mit dem Standarddatum und der Standardzeit initialisieren, abhängig vom Gebietsschema unseres Betriebssystems, oder wir können eine Kombination aus Datum, Uhrzeit, Gebietsschema und Zeitzone angeben.

Lassen Sie uns die verschiedenen Konstruktoren verstehen, mit denen einGregorianCalendar-Objekt instanziiert werden kann.

Der Standardkonstruktor initialisiert den Kalender mit dem aktuellen Datum und der aktuellen Uhrzeit in der Zeitzone und dem Gebietsschema des Betriebssystems:

new GregorianCalendar();

Wir könnenyear, month, dayOfMonth, hourOfDay, minute und second für die Standardzeitzone mit dem Standardgebietsschema angeben:

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

Beachten Sie, dass wirhourOfDay, minute undsecond nicht angeben müssen, da es andere Konstruktoren ohne diese Parameter gibt.

Wir können die Zeitzone als Parameter übergeben, um einen Kalender in dieser Zeitzone mit dem Standardgebietsschema zu erstellen:

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

Wir können das Gebietsschema als Parameter übergeben, um einen Kalender in diesem Gebietsschema mit der Standardzeitzone zu erstellen:

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

Schließlich können wir die Zeitzone und das Gebietsschema als Parameter übergeben:

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

2.2. Neue Methoden mit Java 8

Mit Java 8 wurden neue Methoden fürGregorianCalendar. eingeführt

Die Methodefrom() ruft eine Instanz vonGregorianCalendar mit dem Standardgebietsschema von einem ZonedDateTime-Objekt ab.

Using getCalendarType() we can get the type of the calendar instance. Die verfügbaren Kalendertypen sind "Gregory", "Buddhist" und "Japanisch".

Wir können dies beispielsweise verwenden, um sicherzustellen, dass wir einen Kalender eines bestimmten Typs haben, bevor wir mit unserer Anwendungslogik fortfahren:

@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, der denselben Punkt auf der Zeitachse darstellt wie dieserGregorianCalendar.

2.3. Termine ändern

Die Kalenderfelder können mit den Methodenadd(),roll() undset() geändert werden.

The add() method allows us to add time to the calendar in a specified unit basierend auf dem internen Regelsatz des Kalenders:

@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);
}

Wir können auch die Methodeadd()verwenden, um die Zeit vom Kalenderobjekt zu subtrahieren:

@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);
}

Die Ausführung der Methodeadd()erzwingt eine sofortige Neuberechnung der Millisekunden des Kalenders und aller Felder.

Beachten Sie, dass die Verwendung vonadd() auch die höheren Kalenderfelder ändern kann (in diesem Fall MONAT).

Die Methoderoll() fügt dem angegebenen Kalenderfeld einen vorzeichenbehafteten Betrag hinzu, ohne die größeren Felder zu ändern. Ein größeres Feld repräsentiert eine größere Zeiteinheit. Zum Beispiel istDAY_OF_MONTH größer alsHOUR.

Sehen wir uns ein Beispiel für das Aufrollen von Monaten an.

In diesem Fall wirdYEAR, das ein größeres Feld ist, nicht erhöht:

@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);
}

Ebenso können wir Monate verlängern:

@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. Der Zeitwert des Kalenders in Millisekunden wird erst neu berechnet, wenn der nächste Aufruf vonget(),getTime(),add() oderroll() erfolgt.

Somit lösen mehrere Aufrufe vonset()keine unnötigen Berechnungen aus.

Sehen wir uns ein Beispiel an, in dem das Monatsfeld auf 3 gesetzt wird (d. H. April):

@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. Arbeiten mitXMLGregorianCalendar

JAXB ermöglicht die Zuordnung von Java-Klassen zu XML-Darstellungen. Der Typjavax.xml.datatype.XMLGregorianCalendar kann bei der Zuordnung der grundlegenden XSD-Schematypen wiexsd:date,xsd:time undxsd:dateTime hilfreich sein.

Schauen wir uns ein Beispiel an, um vom TypGregorianCalendarin den TypXMLGregorianCalendarzu konvertieren:

@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));
}

Sobald das Kalenderobjekt in das XML-Format übersetzt wurde, kann es in allen Anwendungsfällen verwendet werden, bei denen ein Datum serialisiert werden muss, z. B. bei Messaging- oder Webdienstaufrufen.

Sehen wir uns ein Beispiel an, wie der TypXMLGregorianCalendarwieder inGregorianCalendar konvertiert wird:

@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. Termine vergleichen

Wir können diecompareTo()-Methode derCalendar-Klassen verwenden, um Daten zu vergleichen. Das Ergebnis ist positiv, wenn das Basisdatum in der Zukunft liegt, und negativ, wenn die Basisdaten in der Vergangenheit des Datums liegen, mit dem wir sie vergleichen:

@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. Formatierungsdaten

Wir könnenGregorianCalendar in ein bestimmtes Format konvertieren, indem wir eine Kombination ausZonedDateTime undDateTimeFormatter verwenden, um die gewünschte Ausgabe zu erhalten:

@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. Informationen zum Kalender abrufen

GregorianCalendar bietet verschiedene Get-Methoden, mit denen verschiedene Kalenderattribute abgerufen werden können. Schauen wir uns die verschiedenen Optionen an, die wir haben:

  • getActualMaximum(int field) gibt den Maximalwert für das angegebene Kalenderfeld unter Berücksichtigung der aktuellen Zeitwerte zurück. Im folgenden Beispiel wird der Wert 30 für das FeldDAY_OF_MONTHzurückgegeben, da der Juni 30 Tage hat:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(30 == calendar.getActualMaximum(calendar.DAY_OF_MONTH));
  • getActualMinimum(int field) gibt den Mindestwert für das angegebene Kalenderfeld unter Berücksichtigung der aktuellen Zeitwerte zurück:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(1 == calendar.getActualMinimum(calendar.DAY_OF_MONTH));
  • getGreatestMinimum(int field) gibt den höchsten Mindestwert für das angegebene Kalenderfeld zurück:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(1 == calendar.getGreatestMinimum(calendar.DAY_OF_MONTH));
  • getLeastMaximum(int field) Gibt den niedrigsten Maximalwert für das angegebene Kalenderfeld zurück. Für das FeldDAY_OF_MONTHist dies 28, da der Februar möglicherweise nur 28 Tage hat:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(28 == calendar.getLeastMaximum(calendar.DAY_OF_MONTH));
  • getMaximum(int field) gibt den Maximalwert für das angegebene Kalenderfeld zurück:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(31 == calendar.getMaximum(calendar.DAY_OF_MONTH));
  • getMinimum(int field) gibt den Mindestwert für das angegebene Kalenderfeld zurück:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(1 == calendar.getMinimum(calendar.DAY_OF_MONTH));
  • getWeekYear() gibt dieyear of the week zurück, die durch dieseGregorianCalendar dargestellt werden:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(2018 == calendar.getWeekYear());
  • getWeeksInWeekYear() gibt die Anzahl der Wochen im Wochenjahr für das Kalenderjahr zurück:

    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(52 == calendar.getWeeksInWeekYear());
  • isLeapYear() gibt true zurück, wenn das Jahr ein Schaltjahr ist:

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

3. Fazit

In diesem Artikel haben wir bestimmte Aspekte vonGregorianCalendar untersucht.

Wie immer ist der Beispielcodeover on GitHub verfügbar.