Класс Calendar в Java
Класс Calendar — это абстрактный класс в Java для работы с датами и временем. Он находится вjava.utilпакете. Этот класс предоставляет ряд методов для работы с полями даты и времени (такими как год, месяц, день, час, минута и т. д.) и позволяет выполнять вычисления и сравнения дат.
Зачем нужен класс Calendar?
В Java, хотя класс Date также может представлять даты и время, он имеет следующие ограничения:
- Большинство методов устарело
- Не поддерживает интернационализацию
- Ограниченная функциональность вычисления дат
Класс Calendar решает эти проблемы и предоставляет более мощные и гибкие возможности работы с датой и временем.
Базовое использование класса Calendar
Получение экземпляра Calendar
Поскольку Calendar — абстрактный класс, мы не можем создать его экземпляр напрямую. Стандартный способ получения экземпляра Calendar:
Пример
Этот метод возвращает экземпляр Calendar (обычно GregorianCalendar) на основе часового пояса и локали по умолчанию.
Установка даты и времени
Мы можем использоватьset()метод для установки различных полей объекта Calendar:
Пример
calendar.set(2023, Calendar.NOVEMBER, 15);
// Установить год, месяц, день, час, минуту и секунду
calendar.set(2023, Calendar.NOVEMBER, 15, 14, 30, 0);
Примечание: нумерация месяцев начинается с нуля: 0 соответствует январю, а 11 — декабрю. Чтобы избежать путаницы, рекомендуется использовать константы, определённые в классе Calendar (например, Calendar.JANUARY, Calendar.FEBRUARY и т. д.).
Получение информации о дате и времени
Используйтеget()метод для получения различных полей объекта Calendar:
Пример
int month = calendar.get(Calendar.MONTH); // Получить месяц (0-11)
int day = calendar.get(Calendar.DAY_OF_MONTH);// Получить день
int hour = calendar.get(Calendar.HOUR_OF_DAY);// Получить час (24-часовой формат)
int minute = calendar.get(Calendar.MINUTE); // Получить минуту
int second = calendar.get(Calendar.SECOND); // Получить секунду
Общие методы класса Calendar
Вычисление даты
Класс Calendar предоставляет удобные методы вычисления даты:
Пример
calendar.add(Calendar.DAY_OF_MONTH, 10);
// Вычесть 3 месяца из текущего месяца
calendar.add(Calendar.MONTH, -3);
Сравнение дат
Мы можем использоватьcompareTo()метод для сравнения двух объектов Calendar:
Пример
Calendar cal2 = Calendar.getInstance();
cal2.add(Calendar.DAY_OF_MONTH, 1);
int result = cal1.compareTo(cal2);
// result < 0 означает, что cal1 раньше, чем cal2
// result == 0 означает, что cal1 равен cal2
// result > 0 означает, что cal1 позже, чем cal2
Получение временной метки
Вы можете использоватьgetTimeInMillis()метод для получения временной метки (в миллисекундах), представленной объектом Calendar:
Пример
Вы также можете использоватьgetTime()метод, чтобы преобразовать его в объект Date:
Пример
Расширенное использование класса Calendar
Установка часового пояса
Мы можем задать конкретный часовой пояс для объекта Calendar:
Пример
calendar.setTimeZone(timeZone);
Операции с полями Calendar
Класс Calendar предоставляетroll()метод, который может прокрутить поле, не затрагивая другие поля:
Пример
calendar.roll(Calendar.MONTH, true); // Or calendar.roll(Calendar.MONTH, 1);
获取一周的第一天
不同地区对一周的第一天定义不同(有些使用周日,有些使用周一):
Пример
综合示例
Пример
import java.util.GregorianCalendar;
import java.text.SimpleDateFormat;
public class CalendarDemo {
public static void main(String[] args) {
// 1. 获取一个 Calendar 实例(默认使用当前日期和时间)
Calendar calendar = Calendar.getInstance();
// 2. 获取各个字段的值
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1; // Месяц начинается с 0, поэтому добавьте 1
int day = calendar.get(Calendar.DAY_OF_MONTH);
int hour = calendar.get(Calendar.HOUR_OF_DAY); // 24-часовой формат
int minute = calendar.get(Calendar.MINUTE);
int second = calendar.get(Calendar.SECOND);
System.out.printf("Текущее время: %d год %d месяц %d день %d:%d:%d%n",
year, month, day, hour, minute, second);
// 3. Установите конкретную дату и время
calendar.set(2023, Calendar.MAY, 15, 10, 30, 0); // 15 мая 2023 г. 10:30:00
// 4. Используйте SimpleDateFormat для форматированного вывода
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("Время после установки: " + sdf.format(calendar.getTime()));
// 5. Арифметика с датами
calendar.add(Calendar.DAY_OF_MONTH, 5); // Добавить 5 дней
calendar.add(Calendar.HOUR, -3); // Вычесть 3 часа
System.out.println("Время после вычисления: " + sdf.format(calendar.getTime()));
// 6. Сравнить даты
Calendar anotherCalendar = new GregorianCalendar(2023, Calendar.JUNE, 1);
System.out.println("Результат сравнения: " +
(calendar.before(anotherCalendar) ? "до" : "после"));
// 7. Получить день недели (воскресенье=1, суббота=7)
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
System.out.println("День недели" + getChineseWeekday(dayOfWeek));
}
private static String getChineseWeekday(int dayOfWeek) {
String[] weekdays = {"", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
return weekdays[dayOfWeek];
}
}
Результат вывода:
当前时间: 2023年5月15日 14:25:36 设置后的时间: 2023-05-15 10:30:00 运算后的时间: 2023-05-20 07:30:00 比较结果: 之前 星期二
Замечания о классе Calendar
Месяцы нумеруются с нуля: В классе Calendar месяцы нумеруются с нуля (0=январь, 11=декабрь), что легко может привести к ошибкам.
Изменяемость: Объекты Calendar изменяемы; изменение одного объекта Calendar влияет на все места, которые ссылаются на него.
Потокобезопасность: Класс Calendar не является потокобезопасным, и в многопоточных средах требуется дополнительная синхронизация.
Производительность: Частое создание экземпляров Calendar влияет на производительность; подумайте о повторном использовании экземпляров.
Проблемы с часовым поясом: По умолчанию используется системный часовой пояс, и для приложений, работающих в нескольких часовых поясах, требуется особое внимание.
Альтернатива в Java 8
Начиная с Java 8, новый API даты и времени (java.timepackage) был представлен, обеспечивая более современный и удобный способ работы с датами и временем. Если вы используете Java 8 или новее, рекомендуется отдавать предпочтение новому API:
Пример
LocalDate date = LocalDate.now();
LocalDateTime dateTime = LocalDateTime.now();
ZonedDateTime zonedDateTime = ZonedDateTime.now();
Новый API решает многие проблемы класса Calendar, включая лучшую потокобезопасность, более интуитивный дизайн API и более мощную функциональность.
Общие методы класса Java Calendar
Ниже приведены общие методы класса java.util.Calendar:
Основные методы
| Метод | Описание | Пример |
|---|---|---|
static Calendar getInstance() |
Получает экземпляр Calendar с часовым поясом и локалью по умолчанию | Calendar cal = Calendar.getInstance() |
static Calendar getInstance(TimeZone zone) |
Получает экземпляр Calendar с указанным часовым поясом | Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+8")) |
static Calendar getInstance(Locale locale) |
Получает экземпляр Calendar с указанной локалью | Calendar cal = Calendar.getInstance(Locale.CHINA) |
static Calendar getInstance(TimeZone zone, Locale locale) |
Получает экземпляр Calendar с указанными часовым поясом и локалью | Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"), Locale.CHINA) |
Константы полей (основные)
| Поле | Описание | Диапазон значений |
|---|---|---|
Calendar.YEAR |
Поле года | - |
Calendar.MONTH |
Поле месяца | 0-11 (0 означает январь) |
Calendar.DATEилиCalendar.DAY_OF_MONTH |
Количество дней в месяце | 1-31 |
Calendar.DAY_OF_WEEK |
День недели | 1-7 (1 означает воскресенье) |
Calendar.HOUR |
Час в 12-часовом формате | 0-11 |
Calendar.HOUR_OF_DAY |
Час в 24-часовом формате | 0-23 |
Calendar.MINUTE |
Минуты | 0-59 |
Calendar.SECOND |
second | 0-59 |
Calendar.MILLISECOND |
Миллисекунды | 0-999 |
Calendar.AM_PM |
AM или PM | 0 (AM) или 1 (PM) |
Методы операций с датой и временем
| Метод | Описание | Пример |
|---|---|---|
int get(int field) |
Получить значение указанного поля | int year = cal.get(Calendar.YEAR) |
void set(int field, int value) |
Установить значение указанного поля | cal.set(Calendar.MONTH, 5)(установить на июнь) |
void set(int year, int month, int date) |
Установить год, месяц, день | cal.set(2023, 5, 15)(15 июня 2023) |
void set(int year, int month, int date, int hourOfDay, int minute) |
Установить год, месяц, день, час, минуту | cal.set(2023, 5, 15, 14, 30) |
void set(int year, int month, int date, int hourOfDay, int minute, int second) |
Установить год, месяц, день, час, минуту, секунду | cal.set(2023, 5, 15, 14, 30, 45) |
void add(int field, int amount) |
Добавить или вычесть указанное количество времени | cal.add(Calendar.DATE, 5)(добавить 5 дней) |
void roll(int field, int amount) |
Добавить или вычесть количество времени без изменения более крупных полей | cal.roll(Calendar.DATE, 5)(изменяет только поле дня) |
Методы сравнения времени
| Метод | Описание | Пример |
|---|---|---|
boolean after(Object when) |
Определить, находится ли этот Calendar после указанного времени | cal1.after(cal2) |
boolean before(Object when) |
Определить, находится ли этот Calendar до указанного времени | cal1.before(cal2) |
int compareTo(Calendar anotherCalendar) |
Сравнить хронологический порядок двух объектов Calendar | cal1.compareTo(cal2) |
Другие полезные методы
| Метод | Описание | Пример |
|---|---|---|
long getTimeInMillis() |
Вернуть значение времени этого Calendar (в миллисекундах) | long millis = cal.getTimeInMillis() |
void setTimeInMillis(long millis) |
Установить Calendar с заданным значением времени в миллисекундах | cal.setTimeInMillis(1626345600000L) |
Date getTime() |
Вернуть объект Date, представляющий значение времени этого Calendar | Date date = cal.getTime() |
void setTime(Date date) |
Установить время Calendar с помощью заданного Date | cal.setTime(new Date()) |
void clear() |
Очистить все значения полей | cal.clear() |
void clear(int field) |
Очистить значение указанного поля | cal.clear(Calendar.HOUR) |
boolean isSet(int field) |
Определить, установлено ли указанное поле | if(cal.isSet(Calendar.YEAR)) |