Java Дата и время

⚡ Умное резюме

Java Обработка даты и времени сочетает в себе устаревшие классы java.util.Date и SimpleDateFormat с современным API java.time, представленным в [ссылка на API]. Java 8. Предоставляя разработчикам неизменяемые, потокобезопасные типы для точной работы с календарем.

  • 🕒 Дата завещания: Класс java.util.Date хранит значение момента времени в миллисекундах и выводит строку по умолчанию с помощью метода toString.
  • 🔤 Узорчатые буквы: SimpleDateFormat использует буквы, такие как yyyy, MM, dd, HH, mm, ss и zzz, для определения пользовательских форматов вывода.
  • Сравнение: Метод compareTo возвращает отрицательное, нулевое или положительное целое число для упорядочивания двух экземпляров Date в хронологическом порядке.
  • 🆕 Современный API: В java.time переменные LocalDate, LocalDateTime, ZonedDateTime и Instant заменяют объекты Date и Calendar неизменяемыми объектами.
  • 🧵 Безопасность потока: Класс DateTimeFormatter является неизменяемым и безопасным для совместного использования, в то время как SimpleDateFormat требует синхронизации или обертки ThreadLocal.
  • 🔁 совместимость: Преобразование между старым и новым API осуществляется с помощью вспомогательных функций Date.toInstant, Date.from и Calendar.toInstant.

Java Дата и время

Обработка дат и времени в Java Это стандартная часть построения логики планирования, регистрации временных меток, отчетов и журналов аудита. Прежде чем писать какой-либо код, полезно знать параметры, из которых состоит дата:

  • год (в двух или четырех цифрах).
  • месяц (в виде двух цифр, первых трех букв названия месяца или полного названия месяца).
  • даты (фактический номер дня месяца).
  • день (Название дня недели на указанную дату, например, воскресенье, понедельник, вторник).

Java Предоставляет доступ ко многим другим параметрам, описывающим момент времени на временной шкале, включая эпоху, неделю в году, часовой пояс и смещение. В разделах ниже каждый из них рассматривается на примерах, готовых к использованию.

Как использовать дату в Java

Отображение даты в Java

Java обеспечивает Date класс в java.util Этот класс хранит конкретный момент времени с точностью до миллисекунды и предлагает вспомогательные методы для вывода, сравнения и форматирования этого момента. Чтобы получить текущую дату и время, создайте экземпляр класса с помощью его конструктора по умолчанию:

import java.util.Date;

class Date_Ex1 {
    public static void main(String args[]) {
        // Instantiate a Date object by invoking its constructor
        Date objDate = new Date();
        // Display the Date and Time using toString()
        System.out.println(objDate.toString());
    }
}

Выход:

Wed Nov 29 06:36:22 UTC 2017

В примере дата выводится в формате toString по умолчанию. Чтобы отобразить тот же момент времени в другом формате, сначала нужно понять, какие символы форматирования используются. Java использует.

SimpleDateFormat: анализ и форматирование дат

SimpleDateFormat класс в java.text преобразует Date преобразует объект в форматированную строку и анализирует форматированную строку обратно в объект. DateВ ней используются буквенные шаблоны, которые соответствуют компонентам даты или времени. В таблице ниже перечислены все поддерживаемые буквы:

ПисьмоКомпонент даты или времениПример
GОбозначение эпохиAD
yГод2026
MМесяц в годуиюль или июль или 07
wНеделя в году27
WНеделя в месяц2
DДень в году189
dДень в месяце10
FДень недели в месяце2
EНазвание дня неделивторник или вторник
uНомер дня недели (1 = Monday, 7 = воскресенье)1
aмаркер AM или PMPM
HЧас в день (0-23)0
kЧас в день (1-24)24
KЧас в утра или вечера (0-11)0
hЧас в утра или вечера (1-12)12
mМинута в час30
sСекунда в минуту55
Sмиллисекунды978
zЧасовой пояс (название)Тихоокеанское стандартное время; ТИХООКЕАНСКОЕ СТАНДАРТНОЕ ВРЕМЯ; GMT-08: 00
ZЧасовой пояс (смещение RFC 822)-0800
XЧасовой пояс (смещение по стандарту ISO 8601)-08 или -0800 или -08:00

Вам не нужно запоминать всю таблицу. Обращайтесь к ней всякий раз, когда создаете новый шаблон.

Как использовать SimpleDateFormat

SimpleDateFormat это подкласс DateFormat Это позволяет форматировать и анализировать даты, используя указанные выше буквенные шаблоны. Объедините буквы, чтобы точно описать строку, которую вы хотите получить или прочитать.

Например:

  1. Требуемый формат даты: 2012.10.23 20:20:45 по тихоокеанскому стандартному времениСоответствующий шаблон форматирования: yyyy.MM.dd HH:mm:ss zzz.
  2. Требуемый формат даты: 09:30:00 AM 23-May-2012Соответствующий шаблон форматирования: hh:mm:ss a dd-MMM-yyyy.

Наконечник: Часы, регистр букв. Заглавные буквы. M месяц, строчными буквами m минутный. Заглавная буква. H это 24-часовые часы, строчные буквы h Это 12-часовые часы. Перепутав их, вы получите некорректный результат, который не будет отображаться автоматически.

Приведённая ниже программа выводит текущую дату дважды: один раз в формате по умолчанию, а второй раз с использованием шаблона SimpleDateFormat:

import java.text.SimpleDateFormat;
import java.util.Date;

class TestDates_Format {
    public static void main(String args[]) {
        // Current system date and time is assigned to objDate
        Date objDate = new Date();
        System.out.println(objDate);

        // Build the target pattern and format the date
        String strDateFormat = "hh:mm:ss a dd-MMM-yyyy";
        SimpleDateFormat objSDF = new SimpleDateFormat(strDateFormat);
        System.out.println(objSDF.format(objDate));
    }
}

Выход:

Wed Nov 29 06:31:41 UTC 2017
06:31:41 AM 29-Nov-2017

Пример сравнения дат

Пример сравнения дат

Самый надежный способ заказать два Date объекты — это compareTo() Этот метод возвращает отрицательное целое число, если вызывающий момент времени наступил раньше, ноль, если оба момента времени совпадают, и положительное целое число, если вызывающий момент времени наступил позже. Приведенный ниже фрагмент кода анализирует две строковые даты и выводит их относительный порядок:

import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.util.Date;

class TestDates_Compare {
    public static void main(String args[]) throws ParseException {

        SimpleDateFormat objSDF = new SimpleDateFormat("dd-MM-yyyy");
        Date dt_1 = objSDF.parse("20-08-1981");
        Date dt_2 = objSDF.parse("12-10-2012");

        System.out.println("Date1 : " + objSDF.format(dt_1));
        System.out.println("Date2 : " + objSDF.format(dt_2));

        // compareTo returns > 0 when dt_1 is after dt_2
        if (dt_1.compareTo(dt_2) > 0) {
            System.out.println("Date 1 occurs after Date 2");
        }
        // compareTo returns < 0 when dt_1 is before dt_2
        else if (dt_1.compareTo(dt_2) < 0) {
            System.out.println("Date 1 occurs before Date 2");
        }
        // compareTo returns 0 when both dates are equal
        else {
            System.out.println("Both are the same date");
        }
    }
}

Выход:

Date1 : 20-08-1981
Date2 : 12-10-2012
Date 1 occurs before Date 2

Примечание: В исходном коде использовался следующий шаблон dd-mm-yyyy, Строчные буквы mm Буква обозначает минуту, а не месяц, поэтому парсер молча выдал неверное значение месяца. В приведенном выше исправлении используется верхний регистр. MM для месяца, какая буква является правильным образцом?

Java 8. Современный API для работы с датами и временем (java.time)

Java 8 ввел java.time Пакет, переработанный API, вдохновленный библиотекой Joda-Time. Новые классы являются неизменяемыми, потокобезопасными и разделяют человеческий календарь от машинной временной шкалы. Наиболее распространенные типы:

  • LocalDate для даты без указания времени или часового пояса (например, день рождения).
  • LocalTime для отображения времени по настенным часам без даты или часового пояса.
  • LocalDateTime для даты и времени без указания часового пояса.
  • ZonedDateTime для даты и времени с учетом конкретного часового пояса.
  • OffsetDateTime для даты и времени со смещением UTC, но без указания именованной зоны.
  • Instant для метки времени машины, измеренной от начала эпохи UNIX.
  • Duration и Period для сумм, привязанных ко времени и дате.

В приведенном ниже примере с помощью современного API отображаются текущая дата, время, метка времени и часовой пояс:

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.Instant;
import java.time.ZoneId;

class ModernDateDemo {
    public static void main(String args[]) {
        LocalDate today = LocalDate.now();
        LocalDateTime now = LocalDateTime.now();
        ZonedDateTime zoned = ZonedDateTime.now(ZoneId.of("Asia/Kolkata"));
        Instant epoch = Instant.now();

        System.out.println("LocalDate     : " + today);
        System.out.println("LocalDateTime : " + now);
        System.out.println("ZonedDateTime : " + zoned);
        System.out.println("Instant       : " + epoch);
    }
}

Для каждого типа существуют свои заводские методы (now, of, parse) и неизменяемые операции (plusDays, minusHours, withYear) которые возвращают новое значение вместо изменения исходного объекта.

DateTimeFormatter: Форматирование дат в современном формате Java

DateTimeFormatter in java.time.format заменяет SimpleDateFormatОн использует тот же стиль буквенных шаблонов, является неизменяемым и безопасен для совместного использования в разных потоках без дополнительной синхронизации. Класс также предоставляет готовые константы, такие как ISO_LOCAL_DATE и ISO_ZONED_DATE_TIME для стандартных форматов.

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

class FormatterDemo {
    public static void main(String args[]) {
        LocalDateTime now = LocalDateTime.now();

        DateTimeFormatter iso = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        DateTimeFormatter human = DateTimeFormatter.ofPattern("hh:mm:ss a dd-MMM-yyyy");

        System.out.println(now.format(iso));
        System.out.println(now.format(human));

        LocalDateTime parsed = LocalDateTime.parse("2026-07-04T09:30:00", iso);
        System.out.println("Parsed back : " + parsed);
    }
}

Для сравнения двух дат в современном API вызовите isBefore, isAfter или isEqualЭти методы читаются понятнее, чем... compareTo и работать со всеми java.time класса.

Безопасность резьбовых соединений и лучшие практики для Java Дата и время

Оба формата java.util.Date и SimpleDateFormat предшествовали современному периоду JavaИ у каждого из них есть свои известные недостатки. Следуйте приведенным ниже рекомендациям, чтобы обеспечить корректную обработку дат в рабочем коде:

  • Предпочтительнее использовать `java.time` вместо `Date` и `Calendar`. Новые типы данных являются неизменяемыми и потокобезопасными, а также более точно моделируют предметную область (даты без времени, время без зон и т. д.).
  • Не используйте один и тот же SimpleDateFormat в разных потоках. Этот класс хранит внутреннее состояние парсинга и не является потокобезопасным. Оберните его в ThreadLocalсинхронизировать на экземпляре или переключиться на DateTimeFormatter.
  • Всегда указывайте локаль. Названия месяцев и дней меняются в зависимости от локали JVM по умолчанию, что приводит к таким закономерностям, как... MMM и EEE Непереносимый. Укажите локаль явно (например, Locale.ENGLISH).
  • Укажите часовые пояса четко. LocalDateTime зона отсутствует, поэтому преобразуйте в ZonedDateTime or Instant В тот момент, когда важен точный момент, особенно для логов, столбцов баз данных и сетевых данных.
  • При преобразовании между двумя API следует проявлять осторожность. Используйте date.toInstant(), Date.from(instant) и calendar.toInstant().atZone(zone) на границе между устаревшим и современным кодом.
  • Сохраняйте метки времени в формате UTC. Упорствовать и transmit даты в формате UTC (an Instant или строку ISO 8601) и преобразовывать в пользовательскую зону только при отображении.

Часто задаваемые вопросы (FAQ)

Для получения даты и времени в системном часовом поясе используйте метод LocalDateTime.now() из пакета java.time, а для получения только даты — метод LocalDate.now(). В более старых версиях программы... JavaИспользуйте new java.util.Date() для получения текущего момента времени.

java.util.Date представляет собой момент времени в миллисекундах с начала эпохи и является изменяемым. LocalDate моделирует календарную дату без указания времени или часового пояса, является неизменяемым и потокобезопасным, а также предлагает более понятные методы, такие как plusDays и isBefore.

Нет. SimpleDateFormat хранит изменяемое состояние парсинга и выдает неверные результаты при совместном использовании несколькими потоками. Оберните его в ThreadLocal, синхронизируйте на экземпляре или переключитесь на DateTimeFormatter, который является неизменяемым и безопасным.

Передайте точную строку «yyyy-MM-dd». MM в верхнем регистре обозначает месяц, mm в нижнем регистре — минуту. Для получения полной даты и времени используйте «yyyy-MM-dd HH:mm:ss». Всегда указывайте локаль, чтобы названия месяцев отображались корректно.

При работе с устаревшими типами данных Date используйте compareTo, который возвращает отрицательное, нулевое или положительное целое число. При работе с java.time вызовите isBefore, isAfter или isEqual для LocalDate или Instant. Оба подхода учитывают хронологический порядок.

Вызовите метод `date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()`. Чтобы вернуться назад, используйте `Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant())`. Выбирайте зону явно, когда важен точный момент времени.

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

Да. GitHub Copilot предлагает шаблоны DateTimeFormatter, преобразования ZonedDateTime и JUnit тесты на локально-зависимый вывод. RevПеред подтверждением просмотрите каждое предложение, указав правильные буквы шаблона, регион и часовой пояс.

Подведем итог этой публикации следующим образом: