Рубрики
Без рубрики

Руководство по java.util.GregorianCalendar

Узнайте, как использовать класс GregorianCalendar Java

Автор оригинала: baeldung.

1. введение

В этом уроке мы быстро взглянем на класс GregorianCalendar .

2. Григорианский календарь

Григорианский календарь является конкретной реализацией абстрактного класса java.util.Календарь . Неудивительно, что григорианский календарь является наиболее широко используемым гражданским календарем в мире.

2.1. Получение экземпляра

Существует два варианта получения экземпляра GregorianCalendar: Calendar.getInstance() и использование одного из конструкторов.

Использование статического заводского метода Календарь.getInstance() это не рекомендуемый подход, так как он вернет экземпляр в локаль по умолчанию.

Он может вернуть Буддийский календарь для тайского или Японского Имперского календаря для Японии. Незнание типа возвращаемого экземпляра может привести к исключению 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;
}

Используя один из семи перегруженных конструкторов, мы можем инициализировать Календарь объект либо с датой и временем по умолчанию в зависимости от локали нашей операционной системы, либо мы можем указать комбинацию даты, времени, локали и часового пояса.

Давайте разберемся в различных конструкторах, с помощью которых может быть создан объект GregorianCalendar .

Конструктор по умолчанию инициализирует календарь с текущей датой и временем в часовом поясе и локали операционной системы:

new GregorianCalendar();

Мы можем указать год, месяц, день месяца, час дня, минуту и секунду для часового пояса по умолчанию с языковым стандартом по умолчанию:

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

Обратите внимание, что нам не нужно указывать hourOfDay, minute и second , поскольку существуют другие конструкторы без этих параметров.

Мы можем передать часовой пояс в качестве параметра для создания календаря в этом часовом поясе с языковым стандартом по умолчанию:

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

Мы можем передать локаль в качестве параметра для создания календаря в этой локали с часовым поясом по умолчанию:

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

Наконец, мы можем передать как часовой пояс, так и локаль в качестве параметров:

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

2.2. Новые Методы С Java 8

С Java 8 в Григорианский календарь были введены новые методы.

То от() метод получает экземпляр Григорианский календарь с языковым стандартом по умолчанию из объекта ZonedDateTime.

Используя getCalendarType () , мы можем получить тип экземпляра календаря. Доступные типы календаря – “григорий”, “буддийский” и “японский”.

Мы можем использовать это, например, чтобы убедиться, что у нас есть календарь определенного типа, прежде чем переходить к логике нашего приложения:

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

Вызов toZonedDateTime() мы можем преобразовать объект календаря в ZonedDateTime объект , представляющий ту же точку на временной шкале, что и этот GregorianCalendar.

2.3. Изменение Дат

Поля календаря можно изменить с помощью методов и() , roll() и set() .

Метод add() позволяет нам добавлять время в календарь в указанной единице на основе внутреннего набора правил календаря:

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

Мы также можем использовать метод add() для вычитания времени из объекта календаря:

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

Выполнение метода add() приводит к немедленному пересчету миллисекунд календаря и всех полей.

Обратите внимание, что использование add() также может изменить более высокие поля календаря (в данном случае МЕСЯЦ).

Метод roll() добавляет подписанную сумму в указанное поле календаря без изменения больших полей. Большее поле представляет собой большую единицу времени. Например, DAY_OF_MONTH больше, чем HOUR.

Давайте рассмотрим пример того, как свернуть месяцы.

В этом случае ГОД , являющийся большим полем, не будет увеличен:

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

Точно так же мы можем свернуть месяцы:

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

Мы можем напрямую установить для поля календаря указанное значение с помощью метода set () . Значение времени календаря в миллисекундах не будет пересчитано до следующего вызова get() , getTime() , add() или roll () .

Таким образом, многократные вызовы set() не вызывают ненужных вычислений.

Давайте рассмотрим пример, который установит поле месяца равным 3 (т. е. Апрель):

@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. Работа С XMLGregorianCalendar

JAXB позволяет сопоставлять классы Java с представлениями XML. Тип javax.xml.datatype.XMLGregorianCalendar может помочь в сопоставлении основных типов схем XSD, таких как xsd:date , xsd:time и xsd:DateTime .

Давайте рассмотрим пример преобразования из типа Григорианский календарь в тип XMLGregorianCalendar :

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

Как только объект календаря переведен в формат XML, его можно использовать в любых случаях использования, требующих сериализации даты, таких как обмен сообщениями или вызовы веб-служб.

Давайте рассмотрим пример преобразования из XMLGregorianCalendar типа обратно в Григорианский календарь :

@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. Сравнение Дат

Мы можем использовать метод Calendar classes compareTo() для сравнения дат. Результат будет положительным, если базовая дата находится в будущем, и отрицательным, если базовые данные находятся в прошлом данных, с которыми мы их сравниваем:

@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. Форматирование Дат

Мы можем преобразовать GregorianCalendar в определенный формат, используя комбинацию ZonedDateTime и DateTimeFormatter , чтобы получить желаемый результат:

@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. Получение Информации О Календаре

Григорианский календарь предоставляет несколько методов get, которые можно использовать для извлечения различных атрибутов календаря. Давайте рассмотрим различные варианты, которые у нас есть:

  • getActualMaximum(поле int) возвращает максимальное значение для указанного поля календаря с учетом текущих значений времени. В следующем примере будет возвращено значение 30 для поля DAY_OF_MONTH , поскольку июнь имеет 30 дней:

  • getActualMinimum(поле int) возвращает минимальное значение для указанного поля календаря с учетом текущих значений времени:

  • getGreatestMinimum(поле int) возвращает максимальное минимальное значение для данного поля календаря:

  • getLeastMaximum(поле int) Возвращает наименьшее максимальное значение для данного поля календаря. Для поля DAY_OF_MONTH это 28, потому что в феврале может быть только 28 дней:

  • getMaximum(поле int) возвращает максимальное значение для данного поля календаря:

  • getMinimum(поле int) возвращает минимальное значение для данного поля календаря:

  • getWeekYear() возвращает год недели , представленный этим GregorianCalendar :

  • getWeeksInWeekYear() возвращает количество недель в году недели для календарного года:

  • isLeapYear() возвращает true, если год является високосным:

3. Заключение

В этой статье мы рассмотрели некоторые аспекты Григорианского календаря .

Как всегда, пример кода доступен на GitHub .