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 .