Java Дата и час

⚡ Умно обобщение

Java Работата с дата и час комбинира наследените класове java.util.Date и SimpleDateFormat с модерния API java.time, въведен в Java 8, предоставяйки на разработчиците непроменяеми, нишкоустойчиви типове за точна работа с календара.

  • 🕒 Дата на наследяване: Класът java.util.Date съхранява момент в милисекунди и отпечатва низ по подразбиране чрез toString.
  • 🔤 Букви с шаблони: SimpleDateFormat използва букви като гггг, MM, дд, чч, мм, сс и ззз, за ​​да дефинира персонализирани изходни формати.
  • ️ Сравнение: Методът compareTo връща отрицателно, нулево или положително цяло число, за да подреди хронологично два екземпляра на Date.
  • 🆕 Съвременен API: LocalDate, LocalDateTime, ZonedDateTime и Instant в java.time заместват 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Час в AM или PM (0-11)0
hЧас в AM или PM (1-12)12
mМинута в час30
sСекунда в минута55
SМилисекунда978
zЧасова зона (име)Тихоокеанско стандартно време; PST; GMT-08:00
ZЧасова зона (RFC 822 отместване)-0800
XЧасова зона (отместване по ISO 8601)-08 или -0800 или -08:00

Не е нужно да запомняте цялата таблица. Обръщайте се към нея всеки път, когато изграждате нов модел.

Как да използвате SimpleDateFormat

SimpleDateFormat е подклас на DateFormat което ви позволява да форматирате и анализирате дати, използвайки горните букви от шаблона. Комбинирайте буквите, за да опишете точния низ, който искате да генерирате или прочетете.

Например:

  1. Изисква се формат на датата: 2012.10.23 г. 20:20:45 PSTПодходящият шаблон за форматиране е 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: Форматиране на дати в Modern 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.
  • Винаги посочвайте езикова променлива (Locale). Имената на месеците и дните се променят в зависимост от локала по подразбиране на JVM, което прави модели като MMM намлява EEE непреносим. Предайте локал изрично (например Locale.ENGLISH).
  • Бъдете ясни относно часовите зони. LocalDateTime няма зона, така че конвертирайте в ZonedDateTime or Instant винаги когато точният момент е от значение, особено за лог файлове, колони от база данни и мрежови полезни товари.
  • Внимателно конвертирайте между двата API. употреба date.toInstant(), Date.from(instant), и calendar.toInstant().atZone(zone) на границата между стария и съвременния код.
  • Съхранявайте времевите отметки в UTC. Упорствайте и transmit дати като UTC ( Instant или низ по ISO 8601) и се конвертира в потребителската зона само при показване.

Въпроси и Отговори

Извикайте 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“. Винаги указвайте локал, за да могат имената на месеците да се възпроизводят.

С legacy 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Прегледайте всяко предложение за правилните букви за шаблон, езикова променлива и часова зона, преди да го направите.

Обобщете тази публикация с: