JDK8 常用的时间操作
注意:LocalDateTime是不可变并且线程安全的
获取月初月末的时间 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import java.time.LocalDate;import java.time.LocalDateTime;import java.time.LocalTime;import java.time.format.DateTimeFormatter;import java.time.temporal.TemporalAdjusters;public class TestTime { public static void main (String[] args) { LocalDate currDate = LocalDate.now(); DateTimeFormatter localDateTimeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss" ); LocalDate firstDayOfMonth = currDate.with(TemporalAdjusters.firstDayOfMonth()); LocalDateTime startTime = LocalDateTime.of(firstDayOfMonth, LocalTime.MIN); LocalDate lastDayOfMonth = currDate.with(TemporalAdjusters.lastDayOfMonth()); LocalDateTime endTime = LocalDateTime.of(lastDayOfMonth, LocalTime.MAX); System.out.println(localDateTimeFormat.format(startTime)); System.out.println(localDateTimeFormat.format(endTime)); } }
输出:
1 2 2022 -08-01 00 :00 :00 2022 -08-31 23 :59 :59
获取当前的时间 1 2 3 4 LocalDateTime localDateTime = LocalDateTime.now(); System.out.println(localDateTime); # 时间戳 Instant.now().toEpochMilli();
使用DateTimeFormatter来格式化时间
DateTimeFormatter是JDK8用来替代线程不安全的SimpleDateFormat,用来进行时间的格式化
现在我们来格式化时间的输出
1 2 3 4 LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("LocalDateTime.now 输出:" + localDateTime);String fmtDate = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss" )); System.out.println("格式化后的时间:" + fmtDate);
上述代码输出为:
2021-08-17T10:03:56.249 格式化后的时间:2021-08-17 10:03:56
时间格式转时间戳 将Instant
在Java日期时间API类(java.time.Instant
)代表在时间线上一个特定的时刻。瞬间被定义为自原点(称为epoch
)以来的偏移量。原点是 1970 年 1 月 1 日 - 00:00 - 格林这是标准时间 (GMT)
1 2 3 long timeLong = LocalDateTime.now().toInstant(ZoneOffset.of("+8" )).toEpochMilli(); System.out.println("LocalDateTime获取的时间戳:" + timeLong); System.out.println("系统获取的时间戳:" + System.currentTimeMillis());
上述代码输出为:
LocalDateTime获取的时间戳:1629166353154 系统获取的时间戳:1629166353155
特定时间转为时间戳:
1 2 3 LocalDateTime specificTime = LocalDateTime.of(2021 , Month.DECEMBER, 17 , 21 , 57 , 00 );long specificTimeX = specificTime.toInstant(ZoneOffset.of("+8" )).toEpochMilli(); System.out.println("特定时间的时间戳:" + specificTimeX);
时间戳转时间 1 2 LocalDate localDate = Instant.ofEpochMilli(1629166353155L ).atZone(ZoneOffset.ofHours(8 )).toLocalDate(); System.out.println("时间戳:1629166353155 的时间为:" + localDate);
或者转成LocalDateTime以后然后进行格式化
1 2 3 4 LocalDateTime date = LocalDateTime.ofInstant(Instant.ofEpochMilli(1629166353155L ), ZoneId.systemDefault());String dateFmt = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss" )); System.out.println("时间戳转换为时间输出:" + date); System.out.println("时间戳转换为时间并格式化输出:" + dateFmt);
上述代码输出为:
时间戳转换为时间输出:2021-08-17T10:12:33.155 时间戳转换为时间并格式化输出:2021-08-17 10:12:33
对时间进行加减 对天数进行加减
1 2 3 4 LocalDateTime localDateTime = LocalDateTime.now(); System.out.println("当前日期加一天,使用plusDays:" + localDateTime.plusDays(1 )); System.out.println("当前日期减一天,使用minusDays:" + localDateTime.minusDays(1 )); System.out.println("当前日期减一天,使用plusDays:" + localDateTime.plusDays(-1 ));
上述代码输出为:
当前日期加一天,使用plusDays:2021-08-18T10:44:25.153 当前日期减一天,使用minusDays:2021-08-16T10:44:25.153 当前日期减一天,使用plusDays:2021-08-16T10:44:25.153
获取一个月后的时间
1 LocalDateTime localDateTime = LocalDateTime.now().plusMonths(1 );
获取一个月前的时间
1 LocalDateTime localDateTime2 = LocalDateTime.now().minusMonths(1 );
其他的类似得就不多举例了,归总如下:
1 2 3 4 5 6 7 8 plusYears() plusMonths() plusWeeks() plusDays() plusHours() plusMinutes() plusSeconds() plusNanos()
上面都是获取未来的时间,想要获取历史时间,把plus
换成minus
即可
获取时间差 有时候我们想获取两个时间的差值,这个时候我们就会用到java.time.Duration
,使用到的方法如下
1 Duration.between(p1, p2)
如果对象的类型不同,则根据第一个对象的类型计算持续时间。
例p1类型是LocalTime,则p2将转换为LocalTime,指定的时间对象必须支持SECONDS单元,不然会报错。例如:
1 2 3 4 LocalDate localDate = LocalDate.of(2021 , 12 , 13 );LocalDateTime localDateTime9 = LocalDateTime.parse("2008-12-13T10:15:11" );Duration erroDuration = Duration.between(localDate, localDateTime9); System.out.println(erroDuration.toMillis());
结果就是报错:
1 2 3 4 Exception in thread "main" java.time.DateTimeException: Invalid value for MonthOfYear (valid values 1 - 12 ) : 13 at java.time.temporal.ValueRange.checkValidValue(ValueRange.java:311 ) at java.time.temporal.ChronoField.checkValidValue(ChronoField.java:703 ) at java.time.LocalDate.of(LocalDate.java:267 )
为了完全准确,应支持NANOS单元或NANO_OF_SECOND字段。 如果结束在开始之前,则此方法的结果可能是负周期。 为了保证在结果上获得正持续时间调用abs() 。
1 2 3 4 LocalDateTime localDateTime = LocalDateTime.now().plusMonths(1 );LocalDateTime localDateTime2 = LocalDateTime.now().minusMonths(1 );Duration duration = Duration.between(localDateTime, localDateTime2); System.out.println("两个时间差天数:" + duration.abs().toDays());
上述代码输出为:
两个时间差天数:61
获取相差的小时
1 System.out.println("两个时间差小时:" + duration.abs().toHours());
上述代码输出为:
两个时间差小时:1488
其他的类似得就不多举例了,归总如下:
toMinutes() // 时间差值转为分钟
toMillis() // 时间差值转为毫秒
toNanos() // 时间差值转为纳秒
字符串转 LocalDateTime 1 2 3 4 5 6 7 8 9 10 11 public static LocalDateTime toLocalDateTime (String dateTime, String format) { if (!StringUtils.hasLength(dateTime)) { return null ; } format = Optional.ofNullable(format).orElse("yyyy-MM-dd HH:mm:ss" ); DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format); return LocalDateTime.parse(dateTime, formatter); }
获取指定时间的起止日期 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public static LocalDateTime getStartOrEndOfDay (LocalDateTime today, Boolean isFirst) { LocalDateTime resDate = LocalDateTime.now(); if (today == null ) { today = resDate; } if (isFirst) { resDate = today.withHour(0 ).withMinute(0 ).withSecond(0 ); } else { resDate = today.withHour(23 ).withMinute(59 ).withSecond(59 ); } return resDate; }
获取指定日期所属周的开始与结束时间 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public static LocalDateTime getStartOrEndDayOfWeek (LocalDateTime today, Boolean isFirst) { LocalDateTime resDate = LocalDateTime.now(); if (today == null ) { today = resDate; } if (isFirst) { resDate = today.with(DayOfWeek.MONDAY); } else { resDate = today.with(DayOfWeek.SUNDAY); } resDate = DateUtil.getStartOrEndOfDay(resDate, isFirst); return resDate; }