Дата и время в Java
Java предоставляет несколько API для даты и времени. Ниже приведено сравнение основных категорий и сводка общих методов:
| Категория | Основные классы | Потокобезопасность | Изменяемость | Версия Java | Особенности |
|---|---|---|---|---|---|
| Устаревший Date | Date, Calendar,GregorianCalendar | нет | Изменяемый | 1.0+ | Много ошибок проектирования, не рекомендуется |
| Новый API даты и времени | LocalDate, LocalTime, LocalDateTime, ZonedDateTime, ChronoUnit | Да | Неизменяемый | 8+ | Хорошо продуман, рекомендуется |
| Отметка времени | Instant | Да | Неизменяемый | 8+ | Машинное время, с точностью до наносекунд |
| Форматирование | DateTimeFormatter | Да | Неизменяемый | 8+ | Потокобезопасный класс форматирования |
LocalDate/DateTimeFormatter
LocalDate/DateTimeFormatter — это классы дат, появившиеся в Java 8. LocalDate используется для представления даты без времени (год-месяц-день), а DateTimeFormatter — для форматирования и разбора объектов даты и времени.
Пример
import java.time.format.DateTimeFormatter;
public class ExampleTest {
public static void main(String[] args) {
// Получить текущую дату
LocalDate today = LocalDate.now();
System.out.println("Текущая дата: " + today);
// Создать конкретную дату
LocalDate nationalDay = LocalDate.of(2025, 10, 1);
System.out.println("Национальный день: " + nationalDay);
// Сложение и вычитание дат
LocalDate tomorrow = today.plusDays(1);
LocalDate nextMonth = today.plusMonths(1);
LocalDate lastYear = today.minusYears(1);
System.out.println("Завтра: " + tomorrow);
System.out.println("Следующий месяц: " + nextMonth);
System.out.println("Тот же день в прошлом году: " + lastYear);
}
}
Вывод приведенного выше примера:
当前日期: 2025-05-01 国庆节: 2025-10-01 明天: 2025-05-02 下个月: 2025-06-01 去年今天: 2024-05-01
-
В новых проектах следует отдавать предпочтение пакету java.time (Java 8+)
-
Избегайте использования устаревших классов Date и Calendar
-
Четко разграничивайте использование часовых поясов:
-
Часовой пояс не нужен: LocalDate/LocalTime/LocalDateTime
-
Требуется часовой пояс: ZonedDateTime
-
-
Учитывайте потокобезопасность при форматировании: используйте DateTimeFormatter вместо SimpleDateFormat
-
Взаимодействие с базой данных:
-
JDBC 4.2+ нативно поддерживает типы java.time
-
Более старые версии могут преобразовывать в java.sql.Date/Timestamp
-
1. LocalDate (Date)
Пример
LocalDate date = LocalDate.of(2023, Month.JUNE, 15);
int year = date.getYear(); // 2023
Month month = date.getMonth(); // JUNE
int day = date.getDayOfMonth(); // 15
LocalDate nextWeek = today.plusWeeks(1);
boolean isLeap = date.isLeapYear(); // Високосный ли год?
2. LocalTime (Время)
Пример
LocalTime time = LocalTime.of(14, 30, 45); // 14:30:45
int hour = time.getHour(); // 14
int minute = time.getMinute(); // 30
LocalTime nextHour = time.plusHours(1);
3. LocalDateTime (Дата и время)
Пример
LocalDateTime dt = LocalDateTime.of(2023, 6, 15, 14, 30);
LocalDateTime nextMonth = dt.plusMonths(1);
4. ZonedDateTime (Дата и время с часовым поясом)
Пример
ZonedDateTime nyTime = zdt.withZoneSameInstant(ZoneId.of("America/New_York"));
ZoneId zone = zdt.getZone(); // Получить часовой пояс
5. Instant (временная метка)
Пример
Instant later = now.plusSeconds(60); // 60 секунд спустя
long epochMilli = now.toEpochMilli(); // Получить временную метку в миллисекундах
Класс Date
Пакет java.util предоставляет класс Date для инкапсуляции текущей даты и времени. Класс Date предоставляет два конструктора для создания объектов Date.
Первый конструктор инициализирует объект текущей датой и временем.
Второй конструктор принимает параметр — количество миллисекунд, прошедших с 1 января 1970 года.
После создания объекта Date можно вызывать следующие методы.
| Нет. | Методы и описание |
|---|---|
| 1 |
boolean after(Date date) Возвращает true, если объект Date, вызывающий этот метод, находится после указанной даты; в противном случае возвращает false. |
| 2 |
boolean before(Date date) Возвращает true, если объект Date, вызывающий этот метод, находится до указанной даты; в противном случае возвращает false. |
| 3 |
Object clone( ) Возвращает копию этого объекта. |
| 4 |
int compareTo(Date date) Сравнивает объект Date, вызывающий этот метод, с указанной датой. Возвращает 0, если они равны. Возвращает отрицательное число, если вызывающий объект находится до указанной даты. Возвращает положительное число, если вызывающий объект находится после указанной даты. |
| 5 |
int compareTo(Object obj) Если obj имеет тип Date, операция эквивалентна compareTo(Date). В противном случае выбрасывается ClassCastException. |
| 6 |
boolean equals(Object date) Возвращает true, когда объект Date, вызывающий этот метод, равен указанной дате; в противном случае возвращает false. |
| 7 |
long getTime( ) Возвращает количество миллисекунд, прошедших с 1 января 1970 г., 00:00:00 GMT, представленное этим объектом Date. |
| 8 |
int hashCode( ) Возвращает значение хеш-кода этого объекта. |
| 9 |
void setTime(long time) Устанавливает время и дату, используя количество миллисекунд с 1 января 1970 г., 00:00:00 GMT. |
| 10 |
String toString( ) Преобразует этот объект Date в String вида: dow mon dd hh:mm:ss zzz yyyy, где: dow — день недели (Sun, Mon, Tue, Wed, Thu, Fri, Sat). |
Получение текущей даты и времени
Получение текущей даты и времени в Java просто: используйте метод toString() объекта Date для вывода текущей даты и времени, как показано ниже:
Пример
Результат компиляции и запуска приведенного выше примера выглядит следующим образом:
Mon May 04 09:51:52 CDT 2013
Сравнение дат
Java использует следующие три метода для сравнения двух дат:
- Используйте метод getTime() для получения двух дат (количество миллисекунд, прошедших с 1 января 1970 года), затем сравните эти два значения.
- Используйте методы before(), after() и equals(). Например, 12-е число месяца раньше 18-го, тогдаnew Date(99, 2, 12).before(new Date (99, 2, 18))возвращает true.
- Используйте метод compareTo(), который определён интерфейсом Comparable, а класс Date реализует этот интерфейс.
1. Сравнение с помощью метода getTime()
Этот метод сравнивает даты путём сравнения количества миллисекунд с 1 января 1970 года (эпоха Unix) у объектов даты.
Пример
public class DateComparison {
public static void main(String[] args) {
Date date1 = new Date(121, 5, 15); // 15 июня 2021 г.
Date date2 = new Date(121, 5, 20); // 20 июня 2021 г.
// Сравнение миллисекунд
if (date1.getTime() < date2.getTime()) {
System.out.println("date1 раньше date2");
} else if (date1.getTime() > date2.getTime()) {
System.out.println("date1 позже date2");
} else {
System.out.println("Две даты совпадают");
}
}
}
Вывод:
date1 在 date2 之前
2. Используйте методы before(), after() и equals()
Эти методы — встроенные методы сравнения класса Date с более понятной семантикой.
Пример
public class DateComparison {
public static void main(String[] args) {
Date date1 = new Date(121, 5, 15); // 15 июня 2021 г.
Date date2 = new Date(121, 5, 20); // 20 июня 2021 г.
// Используйте метод before()
System.out.println("date1 раньше date2? " + date1.before(date2));
// Используйте метод after()
System.out.println("date1 позже date2? " + date1.after(date2));
// Использовать метод equals()
System.out.println("Совпадают ли эти две даты? " + date1.equals(date2));
}
}
Вывод:
date1 在 date2 之前吗? true date1 在 date2 之后吗? false 两个日期相同吗? false
3. Использовать метод compareTo()
Класс Date реализует интерфейс Comparable и может сравниваться с помощью метода compareTo().
Пример
public class DateComparison {
public static void main(String[] args) {
Date date1 = new Date(121, 5, 15); // 15 июня 2021 г.
Date date2 = new Date(121, 5, 20); // 20 июня 2021 г.
int result = date1.compareTo(date2);
if (result < 0) {
System.out.println("date1 раньше date2");
} else if (result > 0) {
System.out.println("date1 позже date2");
} else {
System.out.println("Две даты совпадают");
}
}
}
Вывод:
date1 在 date2 之前
Форматирование дат с помощью SimpleDateFormat
SimpleDateFormat — это класс, который форматирует и разбирает даты с учётом локали. SimpleDateFormat позволяет выбрать любой пользовательский формат даты и времени для выполнения. Например:
Пример
SimpleDateFormat ft = new SimpleDateFormat ("yyyy-MM-dd hh:mm:ss");
Эта строка кода задаёт формат преобразования, где yyyy — полный год, MM — месяц, dd — день, а HH:mm:ss — часы, минуты и секунды.
Примечание: Некоторые форматы записываются в верхнем регистре, а некоторые — в нижнем; например, MM — месяц, mm — минуты; HH — 24-часовой формат, а hh — 12-часовой формат.
Результат компиляции и запуска приведенного выше примера выглядит следующим образом:
当前时间为: 2018-09-06 10:16:34
Коды форматирования даты и времени
Строка шаблона времени используется для указания формата времени. В этом шаблоне все буквы ASCII зарезервированы как буквы шаблона, определяемые следующим образом:
| Буква | Описание | Пример |
|---|---|---|
| G | Маркер эры | AD |
| y | Четырёхзначный год | 2001 |
| M | Month | Июль или 07 |
| d | День месяца | 10 |
| h | Час в формате A.M./P.M. (1~12) | 12 |
| H | Час суток (0~23) | 22 |
| m | Минуты | 30 |
| s | Секунды | 55 |
| S | Миллисекунды | 234 |
| E | День недели | Вторник |
| D | День года | 360 |
| F | День недели в месяце | 2 (вторая среда в июле) |
| w | Неделя в году | 40 |
| W | Неделя в месяце | 1 |
| a | Маркер A.M./P.M. | PM |
| k | Час дня (1~24) | 24 |
| K | Час в формате A.M./P.M. (0~11) | 10 |
| z | Часовой пояс | Восточное стандартное время |
| ' | Текстовый разделитель | Разделитель |
| " | Одинарная кавычка | ` |
Форматирование дат с помощью printf
Метод printf может очень легко форматировать время и дату. Используя двухбуквенный формат, он начинается с%t%t и заканчивается одной из букв в таблице ниже.
- %tY: Выводит четырёхзначный год, например: 2023
- %ty: Выводит двузначный год, например: 23
- %tm: Выводит двузначный месяц, например: 02
- %tB: Выводит полное название месяца, например: Февраль
- %tb: Выводит сокращение месяца, например: Фев
- %tA: Выводит полное название дня недели, например: Среда
- %ta: Выводит сокращение дня недели, например: Ср
- %td: Выводит двузначный день, например: 24
- %te: Выводит однозначное или двузначное число дня, например: 24 или 02
- %tH: Выводит час в 24-часовом формате, например: 23
- %tI: Выводит час в 12-часовом формате, например: 11
- %tM: Выводит минуты, например: 45
- %tS: Выводит секунды, например: 30
- %tp: Выводит время до полудня или после полудня, например: AM или PM
- %tZ: Выводит часовой пояс, например: GMT+08:00
|
Символ преобразования |
Описание |
Пример |
|---|---|---|
|
%tc |
Включает полную информацию о дате и времени |
Суббота, 27 октября, 14:21:20 CST 2007 |
|
%tF |
формат "год-месяц-день" |
2007-10-27 |
|
%tD |
формат "месяц/день/год" |
10/27/07 |
|
%tr |
формат "HH:MM:SS PM" (12-часовой формат) |
02:25:51 PM |
|
%tT |
формат "HH:MM:SS" (24-часовой формат) |
14:28:16 |
|
%tR |
формат "HH:MM" (24-часовой формат) |
14:28 |
ПодробнееprintfДополнительные примеры разбора см. в:Примеры printf в Java для форматированного вывода
Пример
Пример
public class DateFormatExample {
public static void main(String[] args) {
Date date = new Date();
System.out.printf("%tY-%tm-%td %tH:%tM:%tS %tZ", date, date, date, date, date, date, date);
}
}
Результат выполнения:
2023-02-24 13:34:45 GMT+08:00
Пример
Результат компиляции и запуска приведенного выше примера выглядит следующим образом:
全部日期和时间信息:星期一 九月 10 10:43:36 CST 2012 年-月-日格式:2012-09-10 月/日/年格式:09/10/12 HH:MM:SS PM格式(12时制):10:43:36 上午 HH:MM:SS格式(24时制):10:43:36 HH:MM格式(24时制):10:43
Если вам нужно многократно указывать дату, форматирование каждой части таким способом несколько сложно. Поэтому можно использовать строку формата, чтобы указать индекс аргумента, который нужно отформатировать.
Индекс должен непосредственно следовать за%% и должен заканчиваться на$$. Например:
Пример
Результат компиляции и запуска приведенного выше примера выглядит следующим образом:
Due date: February 09, 2014
В качестве альтернативы можно использовать флаг <. Он указывает, что ранее отформатированный аргумент должен быть использован снова. Например:
Пример
Результат компиляции и запуска приведенного выше примера выглядит следующим образом:
Due date: February 09, 2014
Символы преобразования, определяющие форматы даты, могут использовать указанный символ преобразования для создания новой строки из даты. Эти символы преобразования даты показаны ниже:
Пример
Вывод:
英文月份简称:May 本地月份简称:五月 英文月份全称:May 本地月份全称:五月 英文星期的简称:Thu 本地星期的简称:星期四 年的前两位数字(不足两位前面补0):20 年的后两位数字(不足两位前面补0):17 一年中的天数(即年的第几天):124 两位数字的月份(不足两位前面补0):05 两位数字的日(不足两位前面补0):04 月份的日(前面不补0):4
Разбор строк во время
Класс SimpleDateFormat имеет некоторые дополнительные методы, особенно parse(), который пытается разобрать строку в соответствии с форматом, хранящимся в данном объекте SimpleDateFormat. Например:
Пример
Результат компиляции и запуска приведенного выше примера выглядит следующим образом:
$ java DateDemo 1818-11-11 Parses as Wed Nov 11 00:00:00 GMT 1818 $ java DateDemo 2007-12-01 2007-12-01 Parses as Sat Dec 01 00:00:00 GMT 2007
Сон в Java
sleep() переводит текущий поток в приостановленное состояние (блокирует текущий поток), уступая CPU. Цель — не дать текущему потоку монополизировать ресурсы CPU, полученные процессом, оставив некоторое время для выполнения других потоков.
Вы можете заставить программу спать в течение одной миллисекунды или любого периода вплоть до срока службы вашего компьютера. Например, следующая программа будет спать 3 секунды:
Пример
Результат компиляции и запуска приведенного выше примера выглядит следующим образом:
Thu Sep 17 10:20:30 CST 2015 Thu Sep 17 10:20:33 CST 2015
Измерение времени
В следующем примере показано, как измерить интервал времени (в миллисекундах):
Пример
Результат компиляции и запуска приведенного выше примера выглядит следующим образом:
Fri Jan 08 09:48:47 CST 2016 Fri Jan 08 09:48:50 CST 2016 Difference is : 3019
Класс Calendar
Теперь мы умеем форматировать и создавать объект даты, но как задавать и получать отдельные части данных даты, например час, день или минуту? И как добавлять или вычитать значения из этих частей даты? Ответ — использовать класс Calendar.
Класс Calendar гораздо мощнее класса Date, а его реализация также сложнее, чем у класса Date.
Класс Calendar — абстрактный класс. На практике он реализует объекты конкретных подклассов. Процесс создания объекта прозрачен для программистов; достаточно использовать метод getInstance, чтобы создать его.
Создайте объект Calendar, представляющий текущую дату системы
Calendar c = Calendar.getInstance();//默认是当前日期
Создайте объект Calendar для указанной даты
Чтобы использовать класс Calendar для представления конкретного времени, нужно сначала создать объект Calendar, а затем задать параметры года, месяца и дня этого объекта.
//创建一个代表2009年6月12日的Calendar对象 Calendar c1 = Calendar.getInstance(); c1.set(2009, 6 - 1, 12);
Типы полей объектов класса Calendar
В классе Calendar следующие константы используются для представления различных значений. Фактически многие классы в JDK придерживаются этой идеи.
| Константа | Описание |
|---|---|
| Calendar.YEAR | Год |
| Calendar.MONTH | Month |
| Calendar.DATE | Date |
| Calendar.DAY_OF_MONTH | Date, точно такое же значение, как у поля выше. |
| Calendar.HOUR | Час в 12-часовом формате |
| Calendar.HOUR_OF_DAY | Час в 24-часовом формате |
| Calendar.MINUTE | Минута |
| Calendar.SECOND | second |
| Calendar.DAY_OF_WEEK | День недели |
Установка информации об объекте класса Calendar
Установка set
E.g.:
Calendar c1 = Calendar.getInstance();
Вызов:
public final void set(int year,int month,int date)
c1.set(2009, 6, 12);//把Calendar对象c1的年月日分别设这为:2009、6、12
Установка с использованием типов полей
Если вы задаёте только определённое поле, например значение даты, можно использовать следующий метод set:
public void set(int field,int value)
Установите дату, представленную объектом c1, на 10-е число; все остальные значения будут пересчитаны.
c1.set(Calendar.DATE,10);
Установите для года, представленного объектом c1, значение 2008; все остальные значения будут пересчитаны.
c1.set(Calendar.YEAR,2008);
Значение set для других атрибутов поля следует той же схеме.
Добавить настройку
Calendar c1 = Calendar.getInstance();
Добавьте 10 к дате объекта c1, то есть c1 представляет дату на 10 дней позже; все остальные значения будут пересчитаны.
c1.add(Calendar.DATE, 10);
Вычтите 10 из даты объекта c1, то есть c1 представляет дату на 10 дней раньше; все остальные значения будут пересчитаны.
c1.add(Calendar.DATE, -10);
Значение add для других атрибутов поля следует той же схеме.
Получение информации об объекте класса Calendar
Класс GregorianCalendar
Класс Calendar реализует григорианский календарь; GregorianCalendar — конкретная реализация класса Calendar.
Метод getInstance() класса Calendar возвращает объект GregorianCalendar, по умолчанию инициализированный текущей локалью и часовым поясом. GregorianCalendar определяет два поля: AD и BC. Они представляют две эры, определённые григорианским календарём.
Ниже перечислены несколько конструкторов объектов GregorianCalendar:
| Нет. | Конструктор и описание |
| 1 |
GregorianCalendar() Создает GregorianCalendar по умолчанию, используя текущее время в часовом поясе по умолчанию с локалью по умолчанию. |
| 2 |
GregorianCalendar(int year, int month, int date) Создает GregorianCalendar с заданными значениями даты в часовом поясе по умолчанию с локалью по умолчанию. |
| 3 |
GregorianCalendar(int year, int month, int date, int hour, int minute) Создает GregorianCalendar с заданными значениями даты и времени для часового пояса по умолчанию с локалью по умолчанию. |
| 4 |
GregorianCalendar(int year, int month, int date, int hour, int minute, int second) Создает GregorianCalendar с заданными значениями даты и времени для часового пояса по умолчанию с локалью по умолчанию. |
| 5 |
GregorianCalendar(Locale aLocale) Создает GregorianCalendar на основе текущего времени в часовом поясе по умолчанию с заданной локалью. |
| 6 |
GregorianCalendar(TimeZone zone) Создает GregorianCalendar на основе текущего времени в заданном часовом поясе с локалью по умолчанию. |
| 7 |
GregorianCalendar(TimeZone zone, Locale aLocale) Создает GregorianCalendar на основе текущего времени в заданном часовом поясе с заданной локалью. |
Вот список некоторых полезных методов, предоставляемых классом GregorianCalendar:
| Нет. | Метод и описание |
| 1 |
void add(int field, int amount) Добавляет указанное (знаковое) количество времени к заданному полю календаря в соответствии с правилами календаря. |
| 2 |
protected void computeFields() Преобразует значение миллисекунд UTC в значения полей времени. |
| 3 |
protected void computeTime() Переопределяет Calendar, преобразуя значения полей времени в значение миллисекунд UTC. |
| 4 |
boolean equals(Object obj) Сравнивает этот GregorianCalendar с указанным Object. |
| 5 |
int get(int field) Получает значение времени для указанного поля. |
| 6 |
int getActualMaximum(int field) Возвращает максимальное значение заданного поля для текущей даты. |
| 7 |
int getActualMinimum(int field) Возвращает минимальное значение заданного поля для текущей даты. |
| 8 |
int getGreatestMinimum(int field) Возвращает наибольшее минимальное значение заданного поля календаря для этого экземпляра GregorianCalendar. |
| 9 |
Date getGregorianChange() Получает дату изменения григорианского календаря. |
| 10 |
int getLeastMaximum(int field) Возвращает наименьшее максимальное значение заданного поля календаря для этого экземпляра GregorianCalendar. |
| 11 |
int getMaximum(int field) Возвращает максимальное значение указанного поля календаря для этого экземпляра GregorianCalendar. |
| 12 |
Date getTime() Возвращает текущее время календаря. |
| 13 |
long getTimeInMillis() Возвращает текущее время календаря, представленное в виде long. |
| 14 |
TimeZone getTimeZone() Возвращает часовой пояс. |
| 15 |
int getMinimum(int field) Возвращает минимальное значение указанного поля. |
| 16 |
int hashCode() Переопределяет hashCode. |
| 17 |
boolean isLeapYear(int year) 确定给定年份是否为闰年。 |
| 18 |
void roll(int field, boolean up) 在给定的时间字段上增加或减少(向上/向下)一个时间单位,而不更改更大的字段。 |
| 19 |
void set(int field, int value) 用给定值设置时间字段。 |
| 20 |
void set(int year, int month, int date) 设置年、月、日的值。 |
| 21 |
void set(int year, int month, int date, int hour, int minute) 设置年、月、日、小时和分钟的值。 |
| 22 |
void set(int year, int month, int date, int hour, int minute, int second) 设置年、月、日、小时、分钟和秒的值。 |
| 23 |
void setGregorianChange(Date date) Устанавливает дату изменения GregorianCalendar. |
| 24 |
void setTime(Date date) Устанавливает текущее время Calendar по заданной дате. |
| 25 |
void setTimeInMillis(long millis) Устанавливает текущее время Calendar с заданным значением long в миллисекундах. |
| 26 |
void setTimeZone(TimeZone value) Устанавливает текущий часовой пояс с заданным значением часового пояса. |
| 27 |
String toString() Возвращает строку, представляющую календарь. |
Пример
Пример
Результат компиляции и запуска приведенного выше примера выглядит следующим образом:
Date: Apr 22 2009 Time: 11:25:27 当前年份不是闰年
Полный список класса Calendar можно найти в стандартнойдокументации Java。
Другие расширения