Java >> Java tutorial >  >> Tag >> java.util

Guide til java.util.GregorianCalendar

1. Introduktion

I denne øvelse tager vi et hurtigt kig på Gregorian Calendar klasse.

2. Gregoriansk kalender

Gregoriansk kalender er en konkret implementering af den abstrakte klasse java.util.Calendar . Ikke overraskende er den gregorianske kalender den mest udbredte civile kalender i verden.

2.1. Få en instans

Der er to tilgængelige muligheder for at få en forekomst af GregorianCalendar: Calendar.getInstance() og ved at bruge en af ​​konstruktørerne.

Ved brug af den statiske fabriksmetode Calendar.getInstance()  er ikke en anbefalet tilgang, da den vil returnere en instans subjektiv til standardlokaliteten.

Det kan muligvis returnere en buddhistisk kalender for Thai eller JapaneseImperialCalendar for Japan. Hvis du ikke kender typen af ​​den forekomst, der returneres, kan det føre til en ClassCastException :

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

Ved at bruge en af ​​de syv overbelastede konstruktører kan vi initialisere Kalenderen objekt enten med standarddato og -klokkeslæt afhængigt af lokaliteten for vores operativsystem, eller vi kan angive en kombination af dato, tid, lokalitet og tidszone.

Lad os forstå de forskellige konstruktører, som en GregorianCalendar bruger objekt kan instansieres.

Standardkonstruktøren vil initialisere kalenderen med den aktuelle dato og klokkeslæt i operativsystemets tidszone og lokalitet:

new GregorianCalendar();

Vi kan angive år, måned, dayOfMonth, hourOfDay, minut , og anden for standardtidszonen med standardlokaliteten:

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

Bemærk, at vi ikke behøver at angive hourOfDay, minut og sekund da der er andre konstruktører uden disse parametre.

Vi kan videregive tidszonen som en parameter for at oprette en kalender i denne tidszone med standardlokaliteten:

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

Vi kan videregive lokaliteten som en parameter for at oprette en kalender i denne lokalitet med standardtidszonen:

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

Endelig kan vi sende både tidszone og lokalitet som parametre:

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

2.2. Nye metoder med Java 8

Med Java 8 er nye metoder blevet introduceret til GregorianCalendar.

Den fra() metode får en forekomst af GregorianCalendar med standardlokaliteten fra et ZonedDateTime-objekt.

Brug af getCalendarType() vi kan få typen af ​​kalenderforekomsten. De tilgængelige kalendertyper er 'gregory', 'buddhist' og 'japanese'.

Vi kan f.eks. bruge dette til at sikre, at vi har en kalender af en bestemt type, før vi går videre med vores applikationslogik:

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

Ringer toZonedDateTime() vi kan konvertere kalenderobjektet til et ZonedDateTime objekt der repræsenterer det samme punkt på tidslinjen som denne Gregorianske kalender.

2.3. Ændring af datoer

Kalenderfelterne kan ændres ved hjælp af metoderne add() , roll() og set() .

add() metode giver os mulighed for at tilføje tid til kalenderen i en specificeret enhed baseret på kalenderens interne regelsæt:

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

Vi kan også bruge add() metode til at trække tid fra kalenderobjektet:

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

Udførelse af add() metode fremtvinger en øjeblikkelig genberegning af kalenderens millisekunder og alle felter.

Bemærk, at du bruger add() kan også ændre de højere kalenderfelter (MÅNED i dette tilfælde).

 roll() metode tilføjer et underskrevet beløb til det angivne kalenderfelt uden at ændre de større felter. Et større felt repræsenterer en større tidsenhed. For eksempel DAY_OF_MONTH er større end HOUR.

Lad os se et eksempel på, hvordan man opruller måneder.

I dette tilfælde ÅR at være et større felt vil ikke blive forøget:

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

På samme måde kan vi rulle måneder ned:

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

Vi kan indstille et kalenderfelt direkte til en specificeret værdi ved hjælp af set() metode. Kalenderens tidsværdi i millisekunder genberegnes ikke før næste kald til get() , getTime() , add() eller roll() er lavet.

Således flere kald til set() udløs ikke unødvendige beregninger.

Lad os se et eksempel, som vil sætte månedsfeltet til 3 (dvs. 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. Arbejde med XMLGregorianCalendar

JAXB tillader kortlægning af Java-klasser til XML-repræsentationer.  javax.xml.datatype.XMLGregorianCalendar type kan hjælpe med at kortlægge de grundlæggende XSD-skematyper såsom xsd:date , xsd:tid og xsd:dateTime .

Lad os se på et eksempel på konvertering fra GregorianCalendar skriv i XMLGregorianCalendar type:

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

Når først kalenderobjektet er blevet oversat til XML-format, kan det bruges i alle brugstilfælde, der kræver, at en dato skal serialiseres, f.eks. beskeder eller webservicekald.

Lad os se et eksempel på, hvordan man konverterer fra XMLGregorianCalendar skriv tilbage i GregorianCalendar :

@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. Sammenligning af datoer

Vi kan bruge kalenderen klassernes compareTo() metode til at sammenligne datoer. Resultatet vil være positivt, hvis basisdatoen er i fremtiden og negativ, hvis basisdataene er i fortiden af ​​den dato, vi sammenligner dem med:

@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. Formatering af datoer

Vi kan konvertere GregorianCalendar til et bestemt format ved at bruge en kombination af ZonedDateTime og DateTimeFormatter for at få det ønskede output:

@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. Få oplysninger om kalenderen

Gregoriansk kalender giver flere get-metoder, som kan bruges til at hente forskellige kalenderattributter. Lad os se på de forskellige muligheder, vi har:

  • getActualMaximum(int field) returnerer den maksimale værdi for det angivne kalenderfelt under hensyntagen til de aktuelle tidsværdier. Følgende eksempel returnerer værdien 30 for DAY_OF_MONTH felt, fordi juni har 30 dage:
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(30 == calendar.getActualMaximum(calendar.DAY_OF_MONTH));
  • getActualMinimum(int field) returnerer minimumsværdien for det angivne kalenderfelt under hensyntagen til de aktuelle tidsværdier:
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(1 == calendar.getActualMinimum(calendar.DAY_OF_MONTH));
  • getGreatestMinimum(int field) returnerer den højeste minimumværdi for det givne kalenderfelt:
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(1 == calendar.getGreatestMinimum(calendar.DAY_OF_MONTH));
  • getLeastMaximum(int field) Returnerer den laveste maksimumværdi for det givne kalenderfelt. For DAY_OF_MONTH felt er dette 28, fordi februar kan have kun 28 dage:
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(28 == calendar.getLeastMaximum(calendar.DAY_OF_MONTH));
  • getMaximum(int field) returnerer den maksimale værdi for det givne kalenderfelt:
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(31 == calendar.getMaximum(calendar.DAY_OF_MONTH));
  • getMinimum(int field) returnerer minimumsværdien for det givne kalenderfelt:
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(1 == calendar.getMinimum(calendar.DAY_OF_MONTH));
  • getWeekYear() returnerer det år i ugen, der repræsenteres af denne Gregorianske kalender :
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(2018 == calendar.getWeekYear());
  • getWeeksInWeekYear() returnerer antallet af uger i ugeåret for kalenderåret:
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(52 == calendar.getWeeksInWeekYear());
  • isLeapYear() returnerer sandt, hvis året er et skudår:
    GregorianCalendar calendar = new GregorianCalendar(2018 , 5, 28);
    assertTrue(false == calendar.isLeapYear(calendar.YEAR));

3. Konklusion

I denne artikel udforskede vi visse aspekter af GregorianCalendar .

Som altid er prøvekoden tilgængelig på GitHub.


Java tag