В предыдущей статье «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, все статьи будут синхронизированы в публичном аккаунте.