jdk1.8后引入了新的日期时间处理API,相比传统的date操作更加简便,date中的SimpleDateFormat也是非线程安全的。
新的API是标准的ISO-8601日历系统,位于java.time包下,且所有类都是不可变类型、线程安全。
废话不多说,开干。
1、获取当前日期时间
now()
:静态方法,根据当前时间创建对象。例如:获取当前日期,当前时间,当前日期时间
java
复制代码
//获取当前日期 LocalDate nowDate = LocalDate.now(); System.out.println("获取当前日期:"+nowDate); //获取当前时间 LocalTime nowTime = LocalTime.now(); System.out.println("获取当前时间:"+nowTime); //获取当前日期时间 LocalDateTime nowDateTime = LocalDateTime.now(); System.out.println("获取当前日期时间:"+nowDateTime);
输出:
💡 获取当前日期:2023-05-11
💡 获取当前时间:11:10:10.453
💡 获取当前日期时间:2023-05-11T11:10:10.454
2、日期时间格式化
DateTimeFormatter
:静态格式化类,提供了ofPattern,ofLocalizedDate,format等格式化方法。
方法 | 描述 |
---|---|
ofPattern(String pattern) | 格式化样式定义,例如:yyyy-MM-dd等 |
format(TemporalAccessor temporal) | 执行格式化,返回字符串类型的时间样式,如:2023-05-11 |
ofLocalizedDate(FormatStyle dateStyle) | 返回特定区域的日期格式。FormatStyle提供了四种类型,分别是:FULL、LONG,SHORT、MEDIUM |
ofLocalizedTime(FormatStyle dateStyle) | 返回特定区域的时间格式。 |
ofLocalizedDateTime(FormatStyle dateStyle) | 返回特定区域的日期时间格式 |
💡 注:在使用
ofLocalizedTime
,ofLocalizedDateTime
中的FormatStyle.FULL
,FormatStyle.LONG
时由于时区信息问题,通常不存储在LocalTime,LocalDateTime对象中,因此会报取不到值的错误。如:
java
复制代码
private static final DateTimeFormatter TIME_DTF = DateTimeFormatter.ofPattern("hh:mm:ss"); private static final DateTimeFormatter DATE_DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd"); private static final DateTimeFormatter DATE_TIME_DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"); //格式化 System.out.println("日期格式化:" + DATE_DTF.format(nowDate)); System.out.println("时间格式化:" + TIME_DTF.format(nowTime)); System.out.println("日期时间格式化:" + DATE_TIME_DTF.format(nowDateTime)); System.out.println("日期样式:" + DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(nowDate)); System.out.println("日期样式:" + DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).format(nowDate)); System.out.println("日期样式:" + DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).format(nowDate)); System.out.println("日期样式:" + DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG).format(nowDate)); //System.out.println("时间样式:" + DateTimeFormatter.ofLocalizedTime(FormatStyle.FULL).format(LocalTime.now())); System.out.println("时间样式:" + nowTime.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.MEDIUM))); // System.out.println("时间样式:" + nowTime.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.LONG))); System.out.println("时间样式:" + nowTime.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT))); System.out.println("日期时间样式:" + DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).format(nowDateTime));
输出:
💡 日期格式化:2023-05-11
💡 时间格式化:11:43:48
💡 日期时间格式化:2023-05-11 11:43:48
💡 日期样式:2023年5月11日 星期四
💡 日期样式:2023-5-11
💡 日期样式:23-5-11
💡 日期样式:2023年5月11日
💡 时间样式:11:43:48
💡 时间样式:上午11:43
💡 日期时间样式:2023-5-11 11:43:48
3、获取日期的年月日
在Date中获取月份是从0开始的,因此真正的月份是需要加1的。而LocalDate提供的方法则不需要。
getYear()
:获取年份,返回int,
getMonthValue()
:获取月份值,相当于是getMonth().getValue()。
getMonth()
:获取的是月份枚举类型,存储的是英文的月份,可以通过getValue()获取int的月份
getDayOfMonth()
:获取月份中第几天,
getDayOfYear()
:获取当前日期在一年中的第几天。
getDayOfWeek()
:获取星期,返回DayOfWeek枚举,保存英文星期,通过getValue()获取数字星期几。
java
复制代码
//获取年月日 int year = nowDate.getYear(); int monthValue = nowDate.getMonthValue(); int month = nowDate.getMonth().getValue(); int day = nowDate.getDayOfMonth(); int dayOfYear = nowDate.getDayOfYear(); int dayOfWeek = nowDate.getDayOfWeek().getValue(); System.out.println("year:" + year + ",monthValue:" + monthValue + ",month:" + month + ",day:" + day + ",dayOfYear:" + dayOfYear + ",dayOfWeek:" + dayOfWeek );
输出:
💡 year:2023,monthValue:5,month:5,day:11,dayOfYear:131,dayOfWeek:4
4、时间转换
时间转换,包括Date转LocalDate、LocalTime、LocalDateTime;LocalDateTime转Date,String转LocalDate、LocalTime、LocalDateTime等。
parse(CharSequence text)
:将字符串转成对应的LocalDate,LocalTime,LocalDateTime。
LocalDate of(int year, int month, int dayOfMonth)
/LocalDate of(int year, Month month, int dayOfMonth)
:设置年月日,转成LocalDate。
如下面代码:
java
复制代码
//of() LocalDate ofDate = LocalDate.of(2022, Month.JANUARY, 31); System.out.println("of方法转LocalDate;" + ofDate); //String转LocalDate,LocalTime,LocalDateTime String date = "2020-01-01"; String time = "11:22:33"; String dateTime = "2021-09-06T09:51:51"; LocalDate localDate = LocalDate.parse(date); LocalTime localTime= LocalTime.parse(time); LocalDateTime localDateTime = LocalDateTime.parse(dateTime); System.out.println("String转LocalDate,LocalTime,LocalDateTime,LocalDate;" + localDate + ",LocalTime:" + localTime + ",LocalDateTime:"+localDateTime); //date转LocalDate,LocalTime,LocalDateTime Date date1 = new Date(); LocalDate localDate1 = LocalDateTime.ofInstant(date1.toInstant(), ZoneId.systemDefault()).toLocalDate(); LocalDateTime localDateTime1 = LocalDateTime.ofInstant(date1.toInstant(), ZoneId.systemDefault()); LocalTime localTime1 = LocalDateTime.ofInstant(date1.toInstant(), ZoneId.systemDefault()).toLocalTime(); System.out.println("date转LocalDate,LocalTime,LocalDateTime,LocalDate;" + localDate1 + ",LocalTime:" + localTime1 + ",LocalDateTime:"+localDateTime1); //LocalDateTime转Date Date from = Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()); System.out.println("LocalDateTime转Date;" + from );
输出:
💡 of方法转LocalDate;2022-01-31
💡String转LocalDate,LocalTime,LocalDateTime,LocalDate;2020-01-01,LocalTime:11:22:33,LocalDateTime:2021-09-06T09:51:51
💡 date转LocalDate,LocalTime,LocalDateTime,LocalDate;2023-05-11,LocalTime:14:30:02.562,LocalDateTime:2023-05-11T14:30:02.562
💡 LocalDateTime转Date;Thu May 11 14:30:02 CST 2023
5、日期比较
LocalDate中提供了equals,isAfter,isBefore等方法来对日期进行比较,这对于我们业务代码中时间判断带来了很大的方法。
equals(Object obj)
:对比两个日期是否相等,查看源码会发现,首先比较的是对象是否一样,然后分别做年,月,日的差是否等于0来进行比较。true:表示相等,false:表示不相等
compareTo(ChronoLocalDate other)
:比较日期,0:表示相等,正数:表示大于,负数:表示小于。
isAfter(ChronoLocalDate other)
:日期是否在other之后,true:表示是,false:表示否。相当于compareTo正负数。
isBefore(ChronoLocalDate other)
:日期是否在other之前,true:表示是,false:表示否。相当于compareTo正负数。
java
复制代码
//时间比较 LocalDate firDate = LocalDate.of(2022, 11, 23); LocalDate secDate = LocalDate.of(2023, 11, 23); LocalDate thrDate = LocalDate.of(2021, 11, 23); //equals System.out.println("equals:" + firDate.equals(secDate)); //compareTo System.out.println("compareTo1:" + secDate.compareTo(thrDate)); System.out.println("compareTo2:" + thrDate.compareTo(firDate)); //isAfter System.out.println("isAfter:" + firDate.isAfter(secDate)); System.out.println("isAfter:" + secDate.isAfter(thrDate)); //isBefore System.out.println("isBefore:" + firDate.isBefore(secDate)); System.out.println("isBefore:" + secDate.isBefore(thrDate));
输出:
💡 equals:false
💡 compareTo1:2
💡 compareTo2:-1
💡 isAfter:false
💡 isAfter:true
💡 isBefore:true
💡 isBefore:false
6、检查周期性日期
在日常生活中,有许多纪念意义的日期,比如说生日,国庆等等。这时候需要进行周期性检查来做一些提醒,比如:老婆的生日,这要是忘了估计跪榴莲都是轻的。哈哈哈
MonthDay这个类,就提供了of,from来获取月份与当前月份中第几天,然后使用equals进行比较即可。
java
复制代码
//周期性检查 LocalDate birthDay = LocalDate.of(1991, 5, 11); MonthDay birthMonth = MonthDay.of(birthDay.getMonth(), birthDay.getDayOfMonth()); MonthDay nowMonth = MonthDay.from(nowDate); if (Objects.equals(birthMonth,nowMonth)){ System.out.println("生日到了!"); } else { System.out.println("万幸,还好生日还没到呢,差点忘了......!"); }
输出:
💡 生日到了!
7、日期计算
前段时间做了一个需求,需要获取前13个月的日期,这是使用LocalDate就比较方便,来看看LocalDate提供的方法。
提前:
minus(long amountToSubtract, TemporalUnit unit)
:计算提前的日期,ChronoUnit实现了TemporalUnit接口,提供了各种日期类型,例如:ChronoUnit.MONTHS,表示日期。
minusMonths(long monthsToSubtract)
:计算提前月份的日期。
minusDays(long daysToSubtract)
:计算提前天数的日期。
minusWeeks(long weeksToSubtract)
:计算提前星期的日期。
minusYears(long yearsToSubtract)
:计算提前年份的日期。
推后:
plus(long amountToSubtract, TemporalUnit unit)
:计算推后的日期,ChronoUnit实现了TemporalUnit接口,提供了各种日期类型,例如:ChronoUnit.MONTHS,表示日期。
plusMonths(long monthsToSubtract)
:计算推后月份的日期。
plusDays(long daysToSubtract)
:计算推后天数的日期。
plusWeeks(long weeksToSubtract)
:计算推后星期的日期。
plusYears(long yearsToSubtract)
:计算推后年份的日期。
java
复制代码
LocalDate nowDate = LocalDate.now(); //日期计算 //提前 System.out.println("两个月前的日期:" + nowDate.minusMonths(2)); System.out.println("20天前的日期:" + nowDate.minusDays(20)); System.out.println("1星期前的日期:" + nowDate.minusWeeks(1)); System.out.println("1年前的日期:" + nowDate.minusYears(1)); System.out.println("1个月前的日期:" + nowDate.minus(1, ChronoUnit.MONTHS)); //推后 System.out.println("两个月后的日期:" + nowDate.plusMonths(2)); System.out.println("20天后的日期:" + nowDate.plusDays(20)); System.out.println("1星期后的日期:" + nowDate.plusWeeks(1)); System.out.println("1年后的日期:" + nowDate.plusYears(1)); System.out.println("1个月后的日期:" + nowDate.plus(1,ChronoUnit.MONTHS));
输出:
💡 两个月前的日期:2023-03-11
💡 20天前的日期:2023-04-21
💡 1星期前的日期:2023-05-04
💡 1年前的日期:2022-05-11
💡 1个月前的日期:2023-04-11
💡 两个月后的日期:2023-07-11
💡 20天后的日期:2023-05-31
💡 1星期后的日期:2023-05-18
💡 1年后的日期:2024-05-11
💡 1个月后的日期:2023-06-11
8、处理时区
java8将时区也分离了出来,用ZoneId来处理特定时区。
ZoneDateTime
:表示某时区下的时间。
java
复制代码
//时区 ZonedDateTime of = ZonedDateTime.of(nowDateTime, ZoneId.of("Asia/Shanghai")); System.out.println("时区:" + of);
输出:
💡 时区:2023-05-11T16:17:11.479+08:00[Asia/Shanghai]
9、获取时间戳
java8提供了Instant类来对时间戳进行操作。
java
复制代码
System.out.println("时间戳:" + Instant.now().getEpochSecond());
时间戳返回的是秒级别的数据。 输出:
时间戳:1683794339
10、闰年判断
isLeapYear()
:可以直接查询日期是否为闰年。true:表示是,false:表示否。
java
复制代码
boolean leapYear = nowDate.isLeapYear(); if (leapYear){ System.out.println("闰年!"); } else { System.out.println("不是闰年!"); }
输出:
💡 不是闰年!
11、获取第一天和最后一天
有时候我们业务需要获取当月或当年的第一天日期或最后一天日期,TemporalAdjusters类提供了一些方法可以直接实现。
TemporalAdjusters.lastDayOfMonth()
:月份的最后一天日期。
TemporalAdjusters.firstDayOfMonth()
:月份的第一天日期。
TemporalAdjusters.lastDayOfYear()
:年份的最后一天日期。
TemporalAdjusters.firstDayOfYear()
:年份的第一天日期。
例如:获取当月/当年的第一天日期和最后一天日期。
java
复制代码
//获取当月第一天和最后一天 LocalDate lastDay = nowDate.with(TemporalAdjusters.lastDayOfMonth()); LocalDate firstDay = nowDate.with(TemporalAdjusters.firstDayOfMonth()); System.out.println("当月第一天:"+firstDay + ";当月最后一天:" + lastDay); //获取当年第一天和最后一天 LocalDate lastYearDay = nowDate.with(TemporalAdjusters.lastDayOfYear()); LocalDate firstYearDay = nowDate.with(TemporalAdjusters.firstDayOfYear()); System.out.println("当年第一天:"+firstYearDay + ";当月最后一天:" + lastYearDay);
输出:
💡 当月第一天:2023-05-01;当月最后一天:2023-05-31
💡 当年第一天:2023-01-01;当月最后一天:2023-12-31
上述就是我在工作用到的一些java8日期时间的方法,存在完整的地方,希望对大家有用,大家也可以写写自己在工作当中使用的日期时间方法,一起来学习学习。