API даты и времени Java 8

Java задняя часть GitHub Безопасность

В предыдущей статье «Java API времени и даты» мы узнали о «традиционном API времени и даты», состоящем из Date, Calendar, DateFormat и т. д., но традиционный дизайн интерфейса обработки не очень удобен и сложен в использовании. Наконец, в Java 8 был переработан набор API со ссылкой на превосходную стороннюю библиотеку с открытым исходным кодом Joda-time.

Итак, в этой статье мы просто узнаем о новом интерфейсе обработки времени и даты.

Мгновенное представление момента

Как и Date, Instant представляет временную метку и используется для описания момента, но может описать более точный момент, чем Date. И Instant не зависит от часового пояса.

Дата может представлять моменты в миллисекундах максимум, в то время как Instant может представлять моменты в наносекундах. Например:

  • public static Instant now(): создать экземпляр Instant на основе текущего времени системы, представляющего текущий момент
  • public static Instant ofEpochSecond(long epochSecond): создайте экземпляр Instant, передав стандартное значение смещения времени
  • public static Instant ofEpochMilli(long epochMilli): создает экземпляр Instant непосредственно из миллисекундного значения.

Взгляните на код:

public static void main(String[] args){
    //创建 Instant 实例
    Instant instant = Instant.now();
    System.out.println(instant);

    Instant instant1 = Instant.ofEpochSecond(20);
    System.out.println(instant1);

    Instant instant2 = Instant.ofEpochSecond(30,100);
    System.out.println(instant2);

    Instant instant3 = Instant.ofEpochMilli(1000);
    System.out.println(instant3);
}

Выходной результат:

2018-04-23T02:43:10.973Z
1970-01-01T00:00:20Z
1970-01-01T00:00:30.000000100Z
1970-01-01T00:00:01Z

Можно видеть, что разница между Instant и Date заключается в том, что они не зависят от часового пояса и всегда связаны с часовым поясом Green Zero, то есть результатом вывода всегда является время Green Zero часового пояса.

LocalDate, который обрабатывает даты

В отличие от Calendar, который может обрабатывать как дату, так и время, современный API java.time разделяет дату и время и обрабатывает их в отдельных классах. LocalDate фокусируется на обработке информации, связанной с датой.

LocalDate по-прежнему является неизменяемым классом, он обращает внимание на часть времени года, месяца и дня Мы можем создать и инициализировать экземпляр LocalDate следующими методами:

  • public static LocalDate now(): обрезать информацию о годе-месяце-дне текущего системного времени и инициализировать объект экземпляра
  • public static LocalDate of(int year, int month, int dayOfMonth): явно указать информацию о годе, месяце и дне
  • public static LocalDate ofYearDay(int year, int dayOfYear): месяц и день месяца могут быть получены из dayOfYear
  • public static LocalDate ofEpochDay(long epochDay): смещение дня относительно времени часового пояса Green Zero

Взгляните на код:

public static void main(String[] args){
    //构建 LocalDate 实例
    LocalDate localDate = LocalDate.now();
    System.out.println(localDate);

    LocalDate localDate1 = LocalDate.of(2017,7,22);
    System.out.println(localDate1);

    LocalDate localDate2 = LocalDate.ofYearDay(2018,100);
    System.out.println(localDate2);

    LocalDate localDate3 = LocalDate.ofEpochDay(10);
    System.out.println(localDate3);
}

Выходной результат:

2018-04-23
2017-07-22
2018-04-10
1970-01-11

Следует отметить, что LocalDate вычисляет информацию о годе, месяце и дне на основе текущего времени в системе и часового пояса по умолчанию.

Кроме того, в LocalDate есть много общих методов для дат:

  • public int getYear(): получить информацию о годе
  • public int getMonthValue(): получить информацию о месяце
  • public int getDayOfMonth(): Получить текущий день месяца
  • public int getDayOfYear(): Получить текущий день в году
  • public boolean isLeapYear(): високосный ли это год
  • public int lengthOfYear(): узнать, сколько дней в этом году
  • public DayOfWeek getDayOfWeek(): возвращает информацию о неделе
  • и т.д

Эти методы хорошо известны и не будут повторяться здесь.

LocalTime для времени обработки

Подобно LocalDate, LocalTime фокусируется на обработке времени. Он обеспечивает различную обработку часов, минут, секунд и наносекунд. Мы все еще можем создать экземпляр LocalTime аналогичным образом.

  • public static LocalTime now(): получить временную часть содержимого в соответствии с текущим системным временем.
  • public static LocalTime of(int hour, int minute): явно передать час и минуту для создания экземпляра объекта
  • public static LocalTime of(int hour, int minute, int second): создать экземпляр, передав час, минуту и ​​секунду
  • public static LocalTime of(int hour, int minute, int second, int nanoOfSecond): создать экземпляр, передав часы, минуты, секунды и наносекунды
  • public static LocalTime ofSecondOfDay(long secondOfDay): передать длинное целочисленное значение, представляющее количество секунд, прошедших в текущем дне.
  • public static LocalTime ofNanoOfDay(long nanoOfDay): передать длинное целое число, представляющее количество наносекунд, прошедших за текущий день.

Точно так же LocalTime использует системный часовой пояс по умолчанию для обработки времени по умолчанию, см. код:

public static void main(String[] a){
    LocalTime localTime = LocalTime.now();
    System.out.println(localTime);

    LocalTime localTime1 = LocalTime.of(23,59);
    System.out.println(localTime1);

    LocalTime localTime2 = LocalTime.ofSecondOfDay(10);
    System.out.println(localTime2);
}

Выходной результат:

13:59:03.723
23:59
00:00:10

Конечно, LocalTime также инкапсулирует множество полезных методов инструментов, таких как:

  • public int getHour()
  • public int getMinute()
  • public int getSecond()
  • public int getNano()
  • public LocalTime withHour(int hour): измените свойство часа в текущем экземпляре LocalTime и верните новый экземпляр.
  • public LocalTime withMinute (целая минута): аналогично
  • public LocalTime withSecond(int second)
  • и т.д

Класс LocalDateTime объединяет LocalDate и LocalTime. Он может представлять информацию как о дате, так и о времени. Методы аналогичны, но есть часть содержимого преобразования, связанная с часовым поясом, о чем мы поговорим позже.

Обработка даты и времени в зависимости от часового пояса ZonedDateTime

Будь то наша LocalDate, или LocalTime, или даже LocalDateTime, они в основном не зависят от часового пояса, атрибут часового пояса не хранится внутри, и в основном используется системный часовой пояс по умолчанию. Часто в некоторых сценариях не хватает гибкости.

ZonedDateTime можно понимать как внешнюю инкапсуляцию LocalDateTime, которая хранит внутри экземпляр LocalDateTime, который специально используется для обычной обработки даты и времени. Кроме того, он определяет ZoneId и ZoneOffset для описания концепции часового пояса.

Большая разница между ZonedDateTime и LocalDateTime заключается в том, что последний не хранит часовой пояс внутри, поэтому он сильно зависит от системы.Часто изменение часового пояса может привести к несогласованности даты и времени в программе.

Последний может использовать ZoneId для сопоставления хранилища, передав имя часового пояса, или использовать ZoneOffset для хранения информации о часовом поясе, передав смещение от нулевого часового пояса.

Итак, существует несколько способов создания экземпляра ZonedDateTime:

  • public static ZonedDateTime now(): система вычисляет и сохраняет информацию о дате и времени в часовом поясе по умолчанию.
  • public static ZonedDateTime now (зона ZoneId): укажите часовой пояс
  • public static ZonedDateTime of (дата LocalDate, время LocalTime, зона ZoneId): укажите дату, время и часовой пояс
  • public static ZonedDateTime of(LocalDateTime localDateTime, ZoneId zone)
  • public static ZonedDateTime ofInstant (Instant Instant, ZoneId zone): создание объектов экземпляра по моменту и часовому поясу
  • и т.д

Посмотрите на код:

public static void main(String[] a){
    ZonedDateTime zonedDateTime = ZonedDateTime.now();
    System.out.println(zonedDateTime);

    LocalDateTime localDateTime = LocalDateTime.now();
    ZoneId zoneId = ZoneId.of("America/Los_Angeles");
    ZonedDateTime zonedDateTime1 = ZonedDateTime.of(localDateTime,zoneId);
    System.out.println(zonedDateTime1);

    Instant instant = Instant.now();
    ZoneId zoneId1 = ZoneId.of("GMT");
    ZonedDateTime zonedDateTime2 = ZonedDateTime.ofInstant(instant,zoneId1);
    System.out.println(zonedDateTime2);
}

Выходной результат:

2018-04-23T16:10:29.510+08:00[Asia/Shanghai]
2018-04-23T16:10:29.511-07:00[America/Los_Angeles]
2018-04-23T08:10:29.532Z[GMT]

Кратко объясните, во-первых, первый вывод должен быть в порядке, система сохраняет текущую системную дату и время и часовой пояс по умолчанию.

Во втором небольшом примере экземпляр LocalDateTime сохраняет текущую дату и время, не зависящие от часового пояса, то есть год, месяц, день, час, минуту и ​​секунду, а затем создает экземпляр ZonedDateTime и передает время в США. зона (Западная 7-я зона). Вы обнаружите, что дата и время выхода 16:29 в западном 7-м округе.

Такая дата и время, связанные с часовым поясом, могут решить проблему путаницы во времени в программе, вызванную изменением часового пояса. Поскольку я связываю часовой пояс, независимо от того, где работает ваша программа,дата + часовой поясОпределенный момент уже определен,Это равносильно тому, что когда я сохраняю определенный момент, я объясняю, что это определенное время в определенном часовом поясе, даже если вы поменяете регион, вы не будете разбирать это время по вашему текущему часовому поясу и использовать его непосредственно в Bar.

Третий небольшой пример более прямолинеен: при построении экземпляра ZonedDateTime задаются время и часовой пояс, а значением времени является количество прошедших миллисекунд относительно стандартного времени данного часового пояса.

Метод обработки других дат и времени, связанных с ZonedDateTime, такой же, как и у LocalDateTime, поскольку ZonedDateTime напрямую инкапсулирует объект экземпляра LocalDateTime, поэтому все связанные операции с датой и временем будут косвенно вызывать методы экземпляра LocalDateTime, и мы не будем повторяться. их.

формат даты и времени

В новом API даты и времени Java 8 DateTimeFormatter является основным классом для форматирования даты и времени.Самая большая разница между ним и предыдущим классом DateFormat заключается в том, что он является потокобезопасным, а другие операции в основном похожи. Посмотрим:

public static void main(String[] a){
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    LocalDateTime localDateTime = LocalDateTime.now();
    System.out.println(formatter.format(localDateTime));

    String str = "2008年08月23日 23:59:59";
    DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    LocalDateTime localDateTime2 = LocalDateTime.parse(str,formatter2);
    System.out.println(localDateTime2);

}

Выходной результат:

2018年04月23日 17:27:24
2008-08-23T23:59:59

Существует два основных случая форматирования: один — преобразовать дату и время в строку, а другой — заменить отформатированную строку объектом даты и времени.

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

Разница во времени

В реальных проектах мы часто сталкиваемся с ситуацией вычисления разницы между двумя временными точками, самый грубый способ — перевести их все в миллисекунды и выполнить вычитание, а в конце преобразовать обратно в объект даты и времени.

Но пакет java.time предоставляет метод для вычисления разницы между двумя датами и временем, давайте посмотрим.

Что касается расчета разницы во времени, то он в основном включает две категории:

  • Период: обрабатывает разницу между двумя датами.
  • Продолжительность: справиться с разницей между двумя временами

Например:

public static void main(String[] args){
    LocalDate date = LocalDate.of(2017,7,22);
    LocalDate date1 = LocalDate.now();
    Period period = Period.between(date,date1);
    System.out.println(period.getYears() + "年" +
            period.getMonths() + "月" +
            period.getDays() + "天");

    LocalTime time = LocalTime.of(20,30);
    LocalTime time1 = LocalTime.of(23,59);
    Duration duration = Duration.between(time,time1);
    System.out.println(duration.toMinutes() + "分钟");
}

Выходной результат:

0年9月1天
209分钟

Очевидно, что для вычисления разницы между днями года, месяцем и днем ​​достаточно использовать класс Period, а для вычисления разницы между часами, минутами, секундами и миллисекундами нужен класс Duration.

Наконец, мы вкратце узнали о новом API даты и времени в рамках пакета java.time, но не стали углубляться в уровень реализации исходного кода, чтобы представить его, потому что нижний уровень включает в себя большое количество системных интерфейсов, задействующих большое количество абстрактных классов и классов реализации Заинтересованные друзья могут прочитать исходный код jdk для более глубокого изучения.


Весь код, изображения, файлы в статье хранятся в облаке на моем GitHub:

(https://github.com/SingleYam/overview_java)

Добро пожаловать в публичный аккаунт WeChat: Gorky on the code, все статьи будут синхронизированы в публичном аккаунте.

image