文章目录

  • 一、JDK8中日期时间API的介绍
    • 1.1、LocalDate、LocalTime、LocalDateTime的使用
    • 2.2、Instant类的使用
    • 2.3、DateTimeFormatter的使用
    • 2.4、ZoneId, ZonedDateTime, Clock, TemporalAdjuster
    • 2.5、参考:与传统日期处理的转换
  • 二、时间工具类

一、JDK8中日期时间API的介绍

java.time包介绍 : https://www.yiibai.com/javatime/javatime_instant.html

1、新日期时间API出现的背景

如果我们可以跟别人说:“我们在1502643933071见面,别晚了!”那么就再简单不过了。但是我们希望时间与昼夜和四季有关,于是事情就变复杂了。JDK 1.0中包含了一个java.util.Date类,但是它的大多数方法已经在JDK 1.1引入Calendar类之后被弃用了。而Calendar并不比Date好多少。它们面临的问题是:

  • 可变性:像日期和时间这样的类应该是不可变的。
  • 偏移性:Date中的年份是从1900开始的,而月份都从0开始。
  • 格式化:格式化只对Date有用,Calendar则不行。
  • 此外,它们也不是线程安全的;不能处理闰秒等。
import org.junit.Test;
import java.util.Date;/*** jdk 8中日期时间API的测试**/
public class JDK8DateTimeTest {@Testpublic void testDate(){//偏移量Date date1 = new Date(2020,9,8);System.out.println(date1);  //Fri Oct 08 00:00:00 CST 3920Date date2 = new Date(2020 - 1900,9 - 1,8);System.out.println(date2); //Tue Sep 08 00:00:00 CST 2020}
}

第三次引入的API是成功的,并且Java 8中引入的java.time API 已经纠正了过去的缺陷,将来很长一段时间内它都会为我们服务。

Java 8 吸收了Joda-Time 的精华,以一个新的开始为Java 创建优秀的API。新的java.time 中包含了所有关于 本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。历史悠久的Date 类新增了toInstant() 方法,用于把Date 转换成新的表示形式。这些新增的本地化时间日期API 大大简化了日期时间和本地化的管理。

  • LocalDate:表示日期,包含:年月日。格式为:2020-01-13
  • LocalTime:表示时间,包含:时分秒。格式为:16:39:09.307
  • LocalDateTime:表示日期时间,包含:年月日 时分秒。格式为:2020-01-13T16:40:59.138
  • DateTimeFormatter:日期时间格式化类
  • Instant:时间戳类
  • Duration:用于计算 2 个时间(LocalTime,时分秒)之间的差距
  • Period:用于计算 2 个日期(LocalDate,年月日)之间的差距
  • ZonedDateTime:包含时区的时间

1.1、LocalDate、LocalTime、LocalDateTime的使用

  • LocalDate、LocalTime、LocalDateTime 类是其中较重要的几个类,它们的实例是不可变的对象,分别表示使用ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息。

    • LocalDate代表IOS格式(yyyy-MM-dd)的日期,可以存储生日、纪念日等日期。
    • LocalTime表示一个时间,而不是日期。
    • LocalDateTime是用来表示日期和时间的,这是一个最常用的类之一
  • 注:ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法,也就是公历。
import org.junit.Test;import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;/*** jdk 8中日期时间API的测试*/
public class JDK8DateTimeTest {/*** LocalDate、LocalTime、LocalDateTime的使用**/@Testpublic void test1(){//now():获取当前的日期、时间、日期+时间LocalDate localDate = LocalDate.now();LocalTime localTime = LocalTime.now();LocalDateTime localDateTime = LocalDateTime.now();System.out.println(localDate);System.out.println(localTime);System.out.println(localDateTime);//of():设置指定的年、月、日、时、分、秒。没有偏移量LocalDateTime localDateTime1 = LocalDateTime.of(2020, 10, 6, 13, 23, 43);System.out.println(localDateTime1);//getXxx():获取相关的属性System.out.println(localDateTime.getDayOfMonth());System.out.println(localDateTime.getDayOfWeek());System.out.println(localDateTime.getMonth());System.out.println(localDateTime.getMonthValue());System.out.println(localDateTime.getMinute());//体现不可变性//withXxx():设置相关的属性LocalDate localDate1 = localDate.withDayOfMonth(22);System.out.println(localDate);System.out.println(localDate1);LocalDateTime localDateTime2 = localDateTime.withHour(4);System.out.println(localDateTime);System.out.println(localDateTime2);//不可变性LocalDateTime localDateTime3 = localDateTime.plusMonths(3);System.out.println(localDateTime);System.out.println(localDateTime3);LocalDateTime localDateTime4 = localDateTime.minusDays(6);System.out.println(localDateTime);System.out.println(localDateTime4);}
}

2.2、Instant类的使用

  • Instant:时间线上的一个瞬时点。这可能被用来记录应用程序中的事件时间戳

  • java.time包通过值类型Instant提供机器视图,不提供处理人类意义上的时间单位。Instant表示时间线上的一点,而不需要任何上下文信息,例如,时区。概念上讲,它只是简单的表示自1970年1月1日0时0分0秒(UTC)开始的秒数。因为java.time包是基于纳秒计算的,所以Instant的精度可以达到纳秒级。

(1 ns = 10-9s) 1秒= 1000毫秒=106微秒=109纳秒

时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。

import org.junit.Test;import java.time.*;/*** jdk 8中日期时间API的测试*/
public class JDK8DateTimeTest {/*** Instant的使用*/@Testpublic void test2(){//now():获取本初子午线对应的标准时间Instant instant = Instant.now();System.out.println(instant);    //2020-05-10T09:55:55.561Z//添加时间的偏移量OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));//东八区System.out.println(offsetDateTime); //2020-05-10T18:00:00.641+08:00//toEpochMilli():获取自1970年1月1日0时0分0秒(UTC)开始的毫秒数  ---> Date类的getTime()long milli = instant.toEpochMilli();System.out.println(milli);  //1589104867591//ofEpochMilli():通过给定的毫秒数,获取Instant实例  -->Date(long millis)Instant instant1 = Instant.ofEpochMilli(1550475314878L);System.out.println(instant1);   //2019-02-18T07:35:14.878Z}
}

2.3、DateTimeFormatter的使用

java.time.format.DateTimeFormatter 类:该类提供了三种格式化方法:

  • 预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIME
  • 本地化相关的格式。如:ofLocalizedDateTime(FormatStyle.LONG)
  • 自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)

import org.junit.Test;import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.TemporalAccessor;/*** jdk 8中日期时间API的测试*/
public class JDK8DateTimeTest {/*** DateTimeFormatter:格式化或解析日期、时间*     类似于SimpleDateFormat*/@Testpublic void test3(){//方式一:预定义的标准格式。如:ISO_LOCAL_DATE_TIME;ISO_LOCAL_DATE;ISO_LOCAL_TIMEDateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;//格式化:日期-->字符串LocalDateTime localDateTime = LocalDateTime.now();String str1 = formatter.format(localDateTime);System.out.println(localDateTime);System.out.println(str1);//2020-05-10T18:26:40.234//解析:字符串 -->日期TemporalAccessor parse = formatter.parse("2020-05-10T18:26:40.234");System.out.println(parse);//方式二://本地化相关的格式。如:ofLocalizedDateTime()//FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT :适用于LocalDateTimeDateTimeFormatter formatter1 = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);//格式化String str2 = formatter1.format(localDateTime);System.out.println(str2);//2020年5月10日 下午06时26分40秒//本地化相关的格式。如:ofLocalizedDate()//FormatStyle.FULL / FormatStyle.LONG / FormatStyle.MEDIUM / FormatStyle.SHORT : 适用于LocalDateDateTimeFormatter formatter2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);//格式化String str3 = formatter2.format(LocalDate.now());System.out.println(str3);//2020-5-10//重点: 方式三:自定义的格式。如:ofPattern(“yyyy-MM-dd hh:mm:ss”)DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");//格式化String str4 = formatter3.format(LocalDateTime.now());System.out.println(str4);//2020-05-10 06:26:40//解析TemporalAccessor accessor = formatter3.parse("2020-05-10 06:26:40");System.out.println(accessor);}
}

2.4、ZoneId, ZonedDateTime, Clock, TemporalAdjuster

  • ZoneId:该类中包含了所有的时区信息,一个时区的ID,如Europe/Paris
  • ZonedDateTime:一个在ISO-8601日历系统时区的日期时间,如2007-12-03T10:15:30+01:00Europe/Paris。
    • 其中每个时区都对应着ID,地区ID都为“{区域}/{城市}”的格式,例如:Asia/Shanghai等
import org.junit.Test;import java.time.*;
import java.util.Set;/*** jdk 8中日期时间API的测试*/
public class JDK8DateTimeTest {@Testpublic void test1(){//ZoneId:类中包含了所有的时区信息// ZoneId的getAvailableZoneIds():获取所有的ZoneIdSet<String> zoneIds= ZoneId.getAvailableZoneIds();for(String s: zoneIds) {System.out.println(s);}// ZoneId的of():获取指定时区的时间LocalDateTime localDateTime= LocalDateTime.now(ZoneId.of("Asia/Tokyo"));System.out.println(localDateTime);//ZonedDateTime:带时区的日期时间// ZonedDateTime的now():获取本时区的ZonedDateTime对象ZonedDateTime zonedDateTime= ZonedDateTime.now();System.out.println(zonedDateTime);// ZonedDateTime的now(ZoneId id):获取指定时区的ZonedDateTime对象ZonedDateTime zonedDateTime1= ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));System.out.println(zonedDateTime1);}
}
  • Clock:使用时区提供对当前即时、日期和时间的访问的时钟。
  • 持续时间:Duration,用于计算两个“时间”间隔
  • 日期间隔:Period,用于计算两个“日期”间隔
  • TemporalAdjuster : 时间校正器。有时我们可能需要获取例如:将日期调整到“下一个工作日”等操作。
  • TemporalAdjusters : 该类通过静态方法(firstDayOfXxx()/lastDayOfXxx()/nextXxx())提供了大量的常用TemporalAdjuster 的实现。
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;import org.junit.Test;public class JDK8APITest {@Testpublic void test2(){//Duration:用于计算两个“时间”间隔,以秒和纳秒为基准LocalTime localTime= LocalTime.now();LocalTime localTime1= LocalTime.of(15, 23, 32);//between():静态方法,返回Duration对象,表示两个时间的间隔Duration duration= Duration.between(localTime1, localTime);System.out.println(duration);System.out.println(duration.getSeconds());System.out.println(duration.getNano());LocalDateTime localDateTime= LocalDateTime.of(2016, 6, 12, 15, 23, 32);LocalDateTime localDateTime1= LocalDateTime.of(2017, 6, 12, 15, 23, 32);Duration duration1= Duration.between(localDateTime1, localDateTime);System.out.println(duration1.toDays());}
}
import java.time.Period;
import org.junit.Test;public class JDK8APITest {@Testpublic void test3(){//Period:用于计算两个“日期”间隔,以年、月、日衡量LocalDate localDate= LocalDate.now();LocalDate localDate1= LocalDate.of(2028, 3, 18);Period period= Period.between(localDate, localDate1);System.out.println(period);System.out.println(period.getYears());System.out.println(period.getMonths());System.out.println(period.getDays());Period period1= period.withYears(2);System.out.println(period1);}
}

2.5、参考:与传统日期处理的转换

二、时间工具类

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;public class DateTimeUtils {public static final String PATTERN_YYYY_MM_DD = "yyyy-MM-dd";public static final String PATTERN_YYYY_MM_DD_HH = "yyyy-MM-dd HH";public static final String PATTERN_YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";public static final String PATTERN_YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";public static final String PATTERN_YYYY_MM_DD_HH_MM_SS_SSS = "yyyy-MM-dd HH:mm:ss.SSS";public static final String PATTERN_YYYY_MM_DD_T_HH_MM_SS_SSS_Z = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";public static final String PATTERN_YYYYMMDD = "yyyyMMdd";public static final String PATTERN_YYYYMMDDHH = "yyyyMMddHH";public static final String PATTERN_YYYYMMDDHHMM = "yyyyMMddHHmm";public static final String PATTERN_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";public static final String PATTERN_YYYYMMDDHHMMSSSSS = "yyyyMMddHHmmssSSS";public static final String PATTERN_HH_MM = "HH:mm";public static final String PATTERN_HH_MM_SS = "HH:mm:ss";public static final String PATTERN_HHMMSS = "HHmmss";public static final String[] WEEKS = {"一", "二", "三", "四", "五", "六", "日"};public static final String[] DAYS = {"今天", "明天", "后天"};public static final DateTimeFormatter FORMATTER_YYYY_MM_DD = DateTimeFormatter.ofPattern(PATTERN_YYYY_MM_DD).withZone(ZoneId.systemDefault());public static final DateTimeFormatter FORMATTER_YYYY_MM_DD_HH = DateTimeFormatter.ofPattern(PATTERN_YYYY_MM_DD_HH).withZone(ZoneId.systemDefault());public static final DateTimeFormatter FORMATTER_YYYY_MM_DD_HH_MM = DateTimeFormatter.ofPattern(PATTERN_YYYY_MM_DD_HH_MM).withZone(ZoneId.systemDefault());public static final DateTimeFormatter FORMATTER_YYYY_MM_DD_HH_MM_SS = DateTimeFormatter.ofPattern(PATTERN_YYYY_MM_DD_HH_MM_SS).withZone(ZoneId.systemDefault());public static final DateTimeFormatter FORMATTER_YYYY_MM_DD_HH_MM_SS_SSS = DateTimeFormatter.ofPattern(PATTERN_YYYY_MM_DD_HH_MM_SS_SSS).withZone(ZoneId.systemDefault());public static final DateTimeFormatter FORMATTER_YYYYMMDD = DateTimeFormatter.ofPattern(PATTERN_YYYYMMDD).withZone(ZoneId.systemDefault());public static final DateTimeFormatter FORMATTER_YYYYMMDDHH = DateTimeFormatter.ofPattern(PATTERN_YYYYMMDDHH).withZone(ZoneId.systemDefault());public static final DateTimeFormatter FORMATTER_YYYYMMDDHHMM = DateTimeFormatter.ofPattern(PATTERN_YYYYMMDDHHMM).withZone(ZoneId.systemDefault());public static final DateTimeFormatter FORMATTER_YYYYMMDDHHMMSS = DateTimeFormatter.ofPattern(PATTERN_YYYYMMDDHHMMSS).withZone(ZoneId.systemDefault());public static final DateTimeFormatter FORMATTER_YYYYMMDDHHMMSSSSS = DateTimeFormatter.ofPattern(PATTERN_YYYYMMDDHHMMSSSSS).withZone(ZoneId.systemDefault());public static final DateTimeFormatter FORMATTER_HH_MM = DateTimeFormatter.ofPattern(PATTERN_HH_MM).withZone(ZoneId.systemDefault());public static final DateTimeFormatter FORMATTER_HH_MM_SS = DateTimeFormatter.ofPattern(PATTERN_HH_MM_SS).withZone(ZoneId.systemDefault());public static final DateTimeFormatter FORMATTER_HHMMSS = DateTimeFormatter.ofPattern(PATTERN_HHMMSS).withZone(ZoneId.systemDefault());public static final DateTimeFormatter FORMATTER_YYYY_MM_DD_T_HH_MM_SS_SSS_Z = DateTimeFormatter.ofPattern(PATTERN_YYYY_MM_DD_T_HH_MM_SS_SSS_Z).withZone(ZoneId.systemDefault());private static final Map<String, DateTimeFormatter> FORMATTERS = new ConcurrentHashMap<String, DateTimeFormatter>();static {FORMATTERS.put(PATTERN_YYYY_MM_DD, FORMATTER_YYYY_MM_DD);FORMATTERS.put(PATTERN_YYYY_MM_DD_HH, FORMATTER_YYYY_MM_DD_HH);FORMATTERS.put(PATTERN_YYYY_MM_DD_HH_MM, FORMATTER_YYYY_MM_DD_HH_MM);FORMATTERS.put(PATTERN_YYYY_MM_DD_HH_MM_SS, FORMATTER_YYYY_MM_DD_HH_MM_SS);FORMATTERS.put(PATTERN_YYYY_MM_DD_HH_MM_SS_SSS, FORMATTER_YYYY_MM_DD_HH_MM_SS_SSS);FORMATTERS.put(PATTERN_YYYYMMDD, FORMATTER_YYYYMMDD);FORMATTERS.put(PATTERN_YYYYMMDDHH, FORMATTER_YYYYMMDDHH);FORMATTERS.put(PATTERN_YYYYMMDDHHMM, FORMATTER_YYYYMMDDHHMM);FORMATTERS.put(PATTERN_YYYYMMDDHHMMSS, FORMATTER_YYYYMMDDHHMMSS);FORMATTERS.put(PATTERN_YYYYMMDDHHMMSSSSS, FORMATTER_YYYYMMDDHHMMSSSSS);FORMATTERS.put(PATTERN_HH_MM, FORMATTER_HH_MM);FORMATTERS.put(PATTERN_HH_MM_SS, FORMATTER_HH_MM_SS);FORMATTERS.put(PATTERN_HHMMSS, FORMATTER_HHMMSS);FORMATTERS.put(PATTERN_YYYY_MM_DD_T_HH_MM_SS_SSS_Z, FORMATTER_YYYY_MM_DD_T_HH_MM_SS_SSS_Z);}private DateTimeUtils() {}/*** 格式化日期** @param temporal 日期,常见的实现类:*                 {@link LocalDateTime},*                 {@link LocalDate},*                 {@link LocalTime},*                 {@link ZonedDateTime}*                 {@link Instant}* @param pattern  格式* @return 被格式化后的日期字符串* @see LocalDateTime* @see LocalDate* @see LocalTime* @see Instant* @see ZonedDateTime*/public static String format(TemporalAccessor temporal, String pattern) {return FORMATTERS.getOrDefault(pattern, DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault())).format(temporal);}/*** 解析字符串日期** @param dateStr 日期字符串* @param pattern 格式* @return LocalDateTime*/public static LocalDateTime parseLocalDateTime(String dateStr, String pattern) {return LocalDateTime.parse(dateStr, FORMATTERS.getOrDefault(pattern, DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.of("Asia/Shanghai"))));}/*** 解析字符串日期** @param dateStr 日期字符串* @param pattern 格式* @return LocalDate*/public static LocalDate parseLocalDate(String dateStr, String pattern) {return LocalDate.parse(dateStr, FORMATTERS.getOrDefault(pattern, DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault())));}/*** 解析字符串时间** @param timeStr 时间字符串* @param pattern 格式* @return LocalTime*/public static LocalTime parseLocalTime(String timeStr, String pattern) {return LocalTime.parse(timeStr, FORMATTERS.getOrDefault(pattern, DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault())));}/*** 相差多少年** @param from 日期1 inclusive* @param to   日期2 exclusive* @return 如果from大于to则会返回负数* @see LocalDateTime* @see LocalDate* @see Instant* @see ZonedDateTime*/public static long betweenYears(Temporal from, Temporal to) {return ChronoUnit.YEARS.between(from, to);}/*** 相差多少月** @param from 日期1 inclusive* @param to   日期2 exclusive* @return 如果from大于to则会返回负数* @see LocalDateTime* @see LocalDate* @see Instant* @see ZonedDateTime*/public static long betweenMonths(Temporal from, Temporal to) {return ChronoUnit.MONTHS.between(from, to);}/*** 相差多少周** @param from 日期1 inclusive* @param to   日期2 exclusive* @return 如果from大于to则会返回负数* @see LocalDateTime* @see LocalDate* @see Instant* @see ZonedDateTime*/public static long betweenWeeks(Temporal from, Temporal to) {return ChronoUnit.WEEKS.between(from, to);}/*** 相差多少天** @param from 日期1 inclusive* @param to   日期2 exclusive* @return 如果from大于to则会返回负数* @see LocalDateTime* @see LocalDate* @see Instant* @see ZonedDateTime*/public static long betweenDays(Temporal from, Temporal to) {return ChronoUnit.DAYS.between(from, to);}/*** 相差多少小时** @param from 日期1 inclusive* @param to   日期2 exclusive* @return 如果from大于to则会返回负数* @see LocalDateTime* @see Instant* @see ZonedDateTime* @see LocalTime*/public static long betweenHours(Temporal from, Temporal to) {return ChronoUnit.HOURS.between(from, to);}/*** 相差多少分钟** @param from 日期1 inclusive* @param to   日期2 exclusive* @return 如果from大于to则会返回负数* @see LocalDateTime* @see Instant* @see ZonedDateTime* @see LocalTime*/public static long betweenMinutes(Temporal from, Temporal to) {return ChronoUnit.MINUTES.between(from, to);}/*** 相差多少秒** @param from 日期1 inclusive* @param to   日期2 exclusive* @return 如果from大于to则会返回负数* @see LocalDateTime* @see Instant* @see ZonedDateTime* @see LocalTime*/public static long betweenSeconds(Temporal from, Temporal to) {return ChronoUnit.SECONDS.between(from, to);}/*** {@param from} 和 {@param to} 是否同一天** @param localDate1 日期1* @param localDate2 日期2* @return true {@param from} 和 {@param to} 同一天,否则 false*/public static boolean isSameDay(LocalDate localDate1, LocalDate localDate2) {return localDate1.compareTo(localDate2) == 0;}/*** {@param from} 和 {@param to} 是否同一天** @param localDateTime1 日期1* @param localDateTime2 日期2* @return true {@param from} 和 {@param to} 同一天,否则 false*/public static boolean isSameDay(LocalDateTime localDateTime1, LocalDateTime localDateTime2) {return isSameDay(localDateTime1.toLocalDate(), localDateTime2.toLocalDate());}/*** 返回只包含日期,不包含时间属性的日期** @return 只包含日期的日期*/public static LocalDateTime getOnlyDay() {return LocalDateTime.now().truncatedTo(ChronoUnit.DAYS);}/*** 返回只包含日期,不包含时间属性的日期** @param localDateTime 原始日期* @return 只包含日期的日期*/public static LocalDateTime getOnlyDay(LocalDateTime localDateTime) {return localDateTime.truncatedTo(ChronoUnit.DAYS);}/*** LocalDateTime 转 Date** @param localDateTime 需要转换的日期* @return Date 类型的日期*/public static Date toDate(LocalDateTime localDateTime) {return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());}/*** LocalDate 转 Date,时间部分初始化为00:00:00.0000000** @param localDate 需要转换的日期* @return Date 类型的日期*/public static Date toDate(LocalDate localDate) {return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());}/*** Date 转 LocalDateTime** @param date 需要转换的日期* @return LocalDateTime 类型的日期*/public static LocalDateTime toLocalDateTime(Date date) {return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());}/*** 毫秒转LocalDateTime** @param millis 毫秒数* @return LocalDateTime 类型的日期*/public static LocalDateTime toLocalDateTime(long millis) {return LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault());}/*** LocalDate转LocalDateTime** @param localDate LocalDate* @return LocalDateTime 类型的日期*/public static LocalDateTime toLocalDateTime(LocalDate localDate) {return LocalDateTime.of(localDate, LocalTime.MIN);}/*** Date 转 LocalDate** @param date 需要转换的日期* @return LocalDate 类型的日期*/public static LocalDate toLocalDate(Date date) {return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).toLocalDate();}/*** 毫秒 转 LocalDate** @param millis 需要转换的日期* @return LocalDate 类型的日期*/public static LocalDate toLocalDate(long millis) {return LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault()).toLocalDate();}/*** 获取毫秒** @param localDateTime 日期* @return 毫秒*/public static long toMillis(LocalDateTime localDateTime) {return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();}/*** 获取毫秒(处在00:00:00.0000000时刻的毫秒)** @param localDate 日期* @return 毫秒*/public static long toMillis(LocalDate localDate) {return localDate.atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();}/*** 判断是否是合法的日期** @param dateStr 日期字符串* @param pattern 日期的格式* @return true 合法,false 不合法*/public static boolean isValid(String dateStr, String pattern) {try {DateTimeFormatter formatter = FORMATTERS.getOrDefault(pattern, DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault()));//之所以最后比较一遍是为了处理2月份的情况//比如,dateStr=2020-02-30 12:12:56, pattern=yyyy-MM-dd HH:mm:ss,//当使用parse方法时是不报错的,因为会自动处理为2020-02-29 12:12:56,//但是上面的情况不是我们想要的,因此最后比较一下即可return dateStr.equals(formatter.format(formatter.parse(dateStr)));} catch (Exception e) {//ignore}return false;}/*** 在指定日期上增加天数,然后返回只包含日期属性的日期** @param localDateTime 日期* @param days          需要增加的天数* @return 只包含日期属性的日期*/public static LocalDateTime getOnlyDay4FutureDate(LocalDateTime localDateTime, long days) {return localDateTime.plusDays(days).truncatedTo(ChronoUnit.DAYS);}/*** 是否是今天** @param localDateTime 日期* @return true 是今天,false 不是今天*/public static boolean isToday(LocalDateTime localDateTime) {return isSameDay(localDateTime.toLocalDate(), LocalDate.now());}/*** 是否是今天** @param localDate 日期* @return true 是今天,false 不是今天*/public static boolean isToday(LocalDate localDate) {return isSameDay(localDate, LocalDate.now());}/*** 判断目标日期是否在日期区间内** @param target 目标日期* @param left   左边界日期,exclusive* @param right  右边界日期,exclusive* @return true 在,false 不在*/public static boolean isInRange(LocalDate target, LocalDate left, LocalDate right) {return target.isAfter(left) && target.isBefore(right);}/*** 判断目标日期是否在日期区间内** @param target 目标日期* @param left   左边界日期,exclusive* @param right  右边界日期,exclusive* @return true 在,false 不在*/public static boolean isInRange(LocalDateTime target, LocalDateTime left, LocalDateTime right) {return target.isAfter(left) && target.isBefore(right);}/*** 比较目标时间点是否在区间中* 注意:此方法会涉及到次日逻辑,也就说{@param left} 可能大于 {@param right}* 比如:left:22:0,right:08:00,则表示时间段段是昨天22:00到次日08:00,因此target=03:00 也是合理的** @param target 目标时间* @param left   左边界,格式HH:mm,exclusive* @param right  右边界,格式HH:mm,exclusive* @return true 在,false 不在* @see #PATTERN_HH_MM*/public static boolean isInRange(LocalTime target, LocalTime left, LocalTime right) {return (target.isAfter(left) && target.isBefore(right))|| (left.isAfter(right) && (target.isBefore(right) || target.isAfter(left)));}/*** 比较目标时间点是否在区间中* 注意:此方法会涉及到隔天逻辑,也就说{@param left} 可能大于 {@param right}* 比如:left:22:0,right:08:00,则表示时间段段是昨天22:00到次日08:00,因此target=03:00 也是合理的** @param target 目标时间* @param left   左边界,格式HH:mm,exclusive* @param right  右边界,格式HH:mm,exclusive* @return true 在,false 不在* @see #PATTERN_HH_MM*/public static boolean isInRange(LocalDateTime target, String left, String right) {LocalTime tt = target.toLocalTime();LocalTime lt = parseLocalTime(left, PATTERN_HH_MM);LocalTime rt = parseLocalTime(right, PATTERN_HH_MM);return isInRange(tt, lt, rt);}/*** 比较目标时间点是否在区间中* 注意:此方法会涉及到隔天逻辑,也就说{@param left} 可能大于 {@param right}* 比如:left:22:0,right:08:00,则表示时间段段是昨天22:00到次日08:00,因此target=03:00 也是合理的** @param target 目标时间* @param left   左边界,格式HH:mm,exclusive* @param right  右边界,格式HH:mm,exclusive* @return true 在,false 不在* @see #PATTERN_HH_MM*/public static boolean isInRange(String target, String left, String right) {LocalTime tt = parseLocalTime(target, PATTERN_HH_MM);LocalTime lt = parseLocalTime(left, PATTERN_HH_MM);LocalTime rt = parseLocalTime(right, PATTERN_HH_MM);return isInRange(tt, lt, rt);}/*** 返回指定小时和分钟的日期** @param time 时间 HH:mm* @return 指定小时和分钟的日期* @see #PATTERN_HH_MM*/public static LocalDateTime getDateTimeByHourMinute(String time) {LocalTime localTime = parseLocalTime(time, PATTERN_HH_MM);return getDateTimeByHourMinute(localTime.getHour(), localTime.getMinute());}/*** 返回指定小时和分钟的日期** @param hour   小时* @param minute 分钟* @return*/public static LocalDateTime getDateTimeByHourMinute(int hour, int minute) {return LocalDateTime.of(LocalDateTime.now().toLocalDate(), LocalTime.of(hour, minute));}/*** 获取某月的第一天,时间是午夜** @param year  年份* @param month 月份,1-12* @return 返回该月的第一天,时间是午夜*/public static LocalDateTime getStartDayOfMonth(int year, int month) {return LocalDateTime.of(LocalDate.of(year, month, 1),LocalTime.MIN);}/*** 获取某月的第一天,时间是午夜** @param localDateTime 日期* @return 返回该月的第一天,时间是午夜*/public static LocalDateTime getStartDayOfMonth(LocalDateTime localDateTime) {return LocalDateTime.of(localDateTime.withDayOfMonth(1).toLocalDate(),LocalTime.MIN);}/*** 获取某月的第一天** @param localDate 日期* @return 返回该月的第一天*/public static LocalDate getStartDayOfMonth(LocalDate localDate) {return localDate.withDayOfMonth(1);}/*** 获取每月的最后一天** @param year  年份* @param month 月份,1-12* @return 返回该月的最后一天*/public static LocalDateTime getEndDayOfMonth(int year, int month) {return LocalDateTime.of(LocalDate.now().withYear(year).withMonth(month).with(TemporalAdjusters.lastDayOfMonth()),LocalTime.MAX);}/*** 获取某月的最后一天** @param localDateTime 日期* @return 返回该月的最后一天*/public static LocalDateTime getEndDayOfMonth(LocalDateTime localDateTime) {return LocalDateTime.of(localDateTime.with(TemporalAdjusters.lastDayOfMonth()).toLocalDate(),LocalTime.MAX);}/*** 获取某月的最后一天** @param localDate 日期* @return 返回该月的最后一天*/public static LocalDate getEndDayOfMonth(LocalDate localDate) {return localDate.with(TemporalAdjusters.lastDayOfMonth());}/*** 时间字符串转时间戳,时间以半点为分界:* 小于半点(<30),向下取整;大于等于半点(>=30),向上取整** @param time 时间,格式 yyyy-MM-dd HH:mm,如 2020-10-30 17:20* @return 毫秒数* @see #PATTERN_YYYY_MM_DD_HH_MM*/public static long truncateByHalfHour(String time) {LocalDateTime localDateTime = parseLocalDateTime(time, PATTERN_YYYY_MM_DD_HH_MM);return toMillis(truncateByHalfHour(localDateTime));}/*** 时间以半点(30分)为分界:* 小于半点(<30),向下取整;大于等于半点(>=30),向上取整** @param localDateTime* @return LocalDateTime*/public static LocalDateTime truncateByHalfHour(LocalDateTime localDateTime) {LocalDateTime resultTime = localDateTime.getMinute() < 30 ?localDateTime.withMinute(0): localDateTime.withMinute(0).plusHours(1);return resultTime;}/*** 获取中间日期,比如* start = 2020-04-11 21:17* end = 2030-02-27 15:21* ====》mid = 2025-03-21 06:19** @param start 开始日期* @param end   结束日期* @return 获取中间日期,并返回分钟数被5归化的日期* @see #PATTERN_YYYY_MM_DD_HH_MM*/public static LocalDateTime getMiddleTime(LocalDateTime start, LocalDateTime end) {long sm = start.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();long em = end.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();long mills = sm + (em - sm) / 2;return LocalDateTime.ofInstant(Instant.ofEpochMilli(mills), ZoneId.systemDefault());}/*** 获取向offset时间偏移量之后的整时间点* 将时间中的分钟调整为{@param offset}的倍数,然后再偏移{@param offset}** @param localDateTime* @param offsetMinutes 分钟的偏移量* @return LocalDateTime*/public static LocalDateTime getAfterTimeOffset(LocalDateTime localDateTime, int offsetMinutes) {int minute = localDateTime.getMinute();minute = (minute / offsetMinutes + 1) * offsetMinutes - minute;localDateTime.plusMinutes(minute);return localDateTime.plusMinutes(minute);}/*** 获取一天的开始时间00:00:00.00000000** @param localDateTime 日期* @return*/public static LocalDateTime getStartTimeOfDay(LocalDateTime localDateTime) {return LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MIN);}/*** 获取一天的结束时间23:59:59.99999999** @param localDateTime 日期* @return*/public static LocalDateTime getEndTimeOfDay(LocalDateTime localDateTime) {return LocalDateTime.of(localDateTime.toLocalDate(), LocalTime.MAX);}/*** 时间戳转localDateTIme* @param timestamp* @return*/public static LocalDateTime getDateTimeOfTimestamp(long timestamp) {Instant instant = Instant.ofEpochMilli(timestamp);ZoneId zone = ZoneId.systemDefault();return LocalDateTime.ofInstant(instant, zone);}/*** localDateTIme转String* @param localDateTime* @param format* @return*/public static String getLocalDateTimeStr(LocalDateTime localDateTime,String format){DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format);return localDateTime.format(formatter);}}
package com.hellobike.hlog.portal.utils;import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;/*** com.hellobike.hlog.portal.utils** @author litao* @date 2021/1/11 8:45 下午*/
public class TimeAggStrategyUtil {private static final long FIVE_MINUTE = 5 * 60 * 1000;private static final long FIFTEEN_MINUTE = 15 * 60 * 1000;private static final long THIRTY_MINUTE = 30 * 60 * 1000;private static final long ONE_HOUR = 1 * 60 * 60 * 1000;private static final long THREE_HOUR = 3 * 60 * 60 * 1000;private static final long SIX_HOUR = 6 * 60 * 60 * 1000;private static final long TWELVE_HOUR = 12 * 60 * 60 * 1000;private static final long ONE_DAY = 1 * 24 * 60 * 60 * 1000;private static final long THREE_DAY = 3 * 24 * 60 * 60 * 1000;private static final long SEVEN_DAY = 7 * 24 * 60 * 60 * 1000;private static final long FORTY_DAY = 14 * 24 * 60 * 60 * 1000;public static DateHistogramInterval getDateAggregationInterval(LocalDateTime startTime, LocalDateTime endTime) {Duration between = Duration.between(startTime, endTime);long duration = between.toMillis();if (duration <= FIVE_MINUTE) {return DateHistogramInterval.seconds(30);}if (duration <= ONE_HOUR) {return DateHistogramInterval.MINUTE;}if (duration <= THREE_HOUR) {return DateHistogramInterval.minutes(5);}if (duration <= TWELVE_HOUR) {return DateHistogramInterval.minutes(10);}if (duration <= ONE_DAY) {return DateHistogramInterval.minutes(30);}if (duration <= THREE_DAY) {return DateHistogramInterval.HOUR;}if (duration <= SEVEN_DAY) {return DateHistogramInterval.hours(3);}return DateHistogramInterval.hours(6);}public static String getDateAggregationFormat(LocalDateTime startTime, LocalDateTime endTime) {Duration between = Duration.between(startTime, endTime);long duration = between.toMillis();if (duration >= ONE_DAY) {return "yyyy-MM-dd HH:mm:ss";}return "HH:mm:ss";}public static String getDateAggregationFormat() {return "yyyy-MM-dd HH:mm:ss";}public static long getTimeDifference(Date startTime, Date endTime) {try {startTime = dateFormat2Date(startTime);endTime = dateFormat2Date(endTime);} catch (ParseException e) {e.printStackTrace();}return endTime.getTime() - startTime.getTime();}public static long getTodayStartTime() {//设置时区Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));calendar.set(Calendar.HOUR_OF_DAY, 0);calendar.set(Calendar.MINUTE, 0);calendar.set(Calendar.SECOND, 0);return calendar.getTimeInMillis();}public static String timeFormat(Long time) {SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");return sdf.format(new Date(time));}public static String dateFormat(Long time) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");return sdf.format(new Date(time));}public static String dateFormat2(Long time) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");return sdf.format(new Date(time));}public static String hLogDateFormat(Long time) {SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");return sdf.format(new Date(time));}public static String dateToFormat(Date time) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");return sdf.format(time);}public static Date dateFormat2Date(Date time) throws ParseException {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");return sdf.parse(sdf.format(time));}}// 获取指定date的零点和11.59public static Date getStartEndOfDay(Date date, TemporalAdjuster adjuster) {LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());LocalDateTime startOfDay = localDateTime.with(adjuster);return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());}

重学Java8新特性(四) : 日期时间API、LocalDateTime、DateTimeFormatter、开发中时间工具类(常用)相关推荐

  1. Java8新特性总结 -5.Stream API函数式操作流元素集合

    所有示例代码打包下载 : 点击打开链接 Java8新特性 : 接口新增默认方法和静态方法 Optional类 Lambda表达式 方法引用 Stream API - 函数式操作流元素集合 Date/T ...

  2. Java8新特性【函数式编程API、新时间日期处理API、Optional容器类】总结

    文章目录 1.Lambda表达式 1.1什么是Lambda表达式 1.2从匿名类到 Lambda 的转换 1.3Lambda表达式语法 2.函数式接口 2.1什么是函数式接口 2.2自定义函数式接口 ...

  3. java8新特性七-Date Time API

    Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理. 在旧版的 Java 中,日期时间 API 存在诸多问题,其中有: 非线程安全 − java.ut ...

  4. Java8新特性之三:Stream API

    Java8的两个重大改变,一个是Lambda表达式,另一个就是本节要讲的Stream API表达式.Stream 是Java8中处理集合的关键抽象概念,它可以对集合进行非常复杂的查找.过滤.筛选等操作 ...

  5. python如何实现日期格式的转换_python开发中时间格式如何转化?

    如果给出大家这样的一道题,给定一个12小时AM/PM格式的时间,将其转换为军用(24小时)时间.并且是利用python去实现,大家可以做到吗?先给大家分析下,这里是一个12小时制度和24小时的来回转换 ...

  6. Java8新特性——Map的新方法

    今天是高考的日子,是大四师兄师姐答辩毕业的日子.一代又来,一代又去.好久没写博客,借此特殊日子整理一下前不久学java8新特性时写的代码,留下痕迹.(本博客的代码根据 java8新特性教程 学习整理, ...

  7. java8新特性-lambda表达式入门学习

    定义 jdk8发布新特性中,lambda是一大亮点之一.lambda表达式能够简化我们对数据的操作,减少代码量,大大提升我们的开发效率.Lambda 表达式"(lambda expressi ...

  8. List 集合去重方式与 java8新特性stream去重

    以下介绍五种 - 不同的方法去除 Java 中 ArrayList 中的重复数据 1.使用 LinkedHashSet 删除 arraylist 中的重复数据 LinkedHashSet 是在一个 A ...

  9. 【小家java】java8新特性之---全新的日期、时间API(JSR 310规范),附SpringMVC、Mybatis中使用JSR310的正确姿势

    [小家java]java5新特性(简述十大新特性) 重要一跃 [小家java]java6新特性(简述十大新特性) 鸡肋升级 [小家java]java7新特性(简述八大新特性) 不温不火 [小家java ...

最新文章

  1. 生物信息通识技术研讨会
  2. C++ 播放音频流(PCM裸流)
  3. POJ 2186 popular cow 有向图的强联通问题 Tarjan算法
  4. list中抽出某一个字段的值_使用LINQ获取List列表中的某个字段值
  5. Rocketmq集群工作流程
  6. 当我们在聊 Serverless 时你应该知道这些 | CSDN博文精选
  7. elipse手机设备显示Target unknown或者offline解决方法
  8. 帕雷诺的个展“共此时”在沪开幕 体验真实与虚妄的交错人生
  9. UnityShader21:程序纹理
  10. kaggle项目:基于随机森林模型的心脏病人预测分类
  11. dmx512如何帧同步_stm32实现DMX512协议发送与接收(非标)
  12. Node-RED中建立Websocket客户端连接
  13. Oracle数字转汉字过程,oracle中如何将字符和数字转成中文
  14. 编译程序和解释程序的本质
  15. 毕业了,异地恋只能分手吗?
  16. CentOS6.5安装NVIDIA的显卡驱动
  17. SA387Gr22Cl2美标容器板介绍,SA387Gr22Cl2钢板规格8-90mm厚
  18. SLAM编程:坐标变换
  19. 事物认识分析基本方法(转)
  20. AdminLTE入门使用

热门文章

  1. 3~4矩阵的压缩存储(下)【详解】
  2. java i18n_Java如何支持I18N?
  3. 如何将一个页面另存为一个单独文件?
  4. APP渗透—MobSF安全评估、frida、r0capture抓包
  5. dvd清洗碟效果好吗_dvd影碟机 教你如何正确保养DVD影碟机
  6. 数学模型转化为计算机语言,在高等数学教学中体现数学建模思想的方法
  7. Android开发UI之隐藏导航栏
  8. 一张图 综合交通 解决方案_构建区域综合交通枢纽 京津冀将形成“一张图”
  9. 中国电信商务领航定制网关(2-1)端口映射
  10. 鲸鱼算法(WOA)优化的BP神经网络预测,WOA-BP回归预测,多输入单输出模型。