目录
- LocalTime、LocalDate、LocalDateTime 区别
- LocalTime、LocalDate、LocalDateTime 使用
- now 获取当前 时刻、日期、时间
- of 获取指定 时刻、日期、时间
- plus || minus 增加或者减少
- 更改指定的 时间
- isAfter || isBefore 比较大小
- compareTo 时间比较
- LocalTime、LocalDate、LocalDateTime 相互转化
- String 与 LocalTime、LocalDate、LocalDateTime 相互转化
- format && parse
- Jackson 全局配置
- Date 与 LocalDate、LocalDateTime 相互转化
- Long 与 LocalDate、LocalDateTime 相互转化
- 常用时间操作方法
- 两个时间相差时间
- Period.between(star,end)
- LocalDate.until
- Duration.between(star,end)
- TemporalAdjuster
- TemporalAdjusters 类中预定义实现
- 两个时间相差时间
LocalTime、LocalDate、LocalDateTime 区别
LocalTime、LocalDate、LocalDateTime是java8对日期、时间提供的新接口。
jdk1.8 之前的 SimpleDateFormat
是线程不安全的。DateTimeFormatter
是线程安全的
- LocalTime 用于
时刻
的计算(带有毫秒) - LocalDate 用于
日期
的计算 - LocalDateTime 用于
日期+时刻
的计算 - 额外补充 时间类型 默认格式:
Date
Tue Feb 01 00:00:00 CST 2022Timestamp
2022-01-01 00:00:00.0LocalDateTime
2022-01-01T00:00:00.000
LocalTime、LocalDate、LocalDateTime 使用now 获取当前 时刻、日期、时间
LocalTime now = LocalTime.now();>>> 获取当前时刻: 10:20:00.856LocalDate now = LocalDate.now();>>> 获取当前日期: 2023-04-13LocalDateTime now = LocalDateTime.now();>>> 获取当前时间: 2023-04-13T17:29:29.357
- LocalTime 获取当前时刻默认会带有毫秒,如果不需要毫秒的话,可以通过设置纳秒为0 保留秒
1秒 = 十亿纳秒
例如:LocalTime.now().withNano(0);
- LocalDateTime 获取当前日期,默认
toString
会带有T
用于区分日期
与时刻
,在项目中,可以通过全局序列化
,进行统一的时间格式输出为yyyy-MM-dd HH:mm:ss
of 获取指定 时刻、日期、时间
LocalTime ofTime = LocalTime.of(12, 0, 0);>>> 获取指定时刻: 12:00LocalDate ofTime = LocalDate.of(2023, 4, 13);>>> 获取指定日期: 2023-04-13LocalDateTime ofTime = LocalDateTime.of(2023,4,13,6,10,20,123);>>> 获取指定时间: 2023-04-13T06:10:20.000000001LocalDateTime ofTime = LocalDateTime.of(LocalDate.of(2023, 4, 13),LocalTime.of(12, 0, 0));>>> 获取指定时间: 2023-04-13T12:00
- LocalDateTime.of 的参数单位分别为 年、月、日、小时、分钟、秒、纳秒
- LocaTime 常用常量
// 一天开始时的午夜时刻,“00:00”LocalTime.MIDNIGHT// 支持的最小时刻 “00:00” 这是一天开始时的时刻。LocalTime.MIN// 支持的最大时刻 “23:59:59.999999999” 这是一天结束时的时刻LocalTime.MAX// 中午的时刻 “12:00”LocalTime.NOON
- 一些比较特殊的获取方式,例如:
// 根据秒数 获取 时刻 例如:第 150 秒的时刻是 00:02:30 (相似方法同理)LocalTime.ofSecondOfDay(150)>>> 获取指定时刻: 00:02:30// 获取指定年限 + 天数 得到日期,例如:获取2023年第120天的日期(相似方法同理)LocalDate.ofYearDay(2023, 120);>>> 获取2023年第120天的日期: 2023-04-30
plus || minus 增加或者减少
// 增加 1 星期(相似方法同理)LocalDateTime.now().plusWeeks(1);// 增加 1 天(相似方法同理)LocalDate.now().plusDays(1);// 增加 1 小时(相似方法同理)LocalTime.now().plusHours(1);LocalDateTime.now().plus(10L, ChronoUnit.DAYS);// 与之相反的 minus 就是减少的意思 不再举例子说明
更改指定的 时间
// 直接改变 指定时刻LocalTime.now().withHour(12);>>> 09:57:23.505 -> 12:57:23.505// 直接改变 指定日期LocalDate.now().withDayOfMonth(2);>>> 2023-04-14 -> 2023-04-02// 直接改变 指定时间LocalDateTime.now().withYear(2024);>>> 2023-04-14T09:59:20.034 -> 2024-04-14T09:59:20.034
- 其他
with
开头的方法大同小异,但要注意的是,如果改变的值是错误的时间,会报错的,例如:在2月份设置31天
isAfter || isBefore 比较大小
// 8:00LocalTime time_8 = LocalTime.of(8, 0, 0);// 9:00LocalTime time_9 = time_8.plusHours(1);boolean after = time_9.isAfter(time_8);>>> 判断 9:00 是不是在 8:00 之后 >> trueboolean before = time_9.isBefore(time_8);>>> 判断 9:00 是不是在 8:00 之前 >> false
- isAfter || isBefore 是无法比较是否相等的,
LocalDate
和LocalDateTime
均有此方法,用法都一样
compareTo 时间比较
// 8:00LocalTime time_8 = LocalTime.of(8, 0, 0);// 9:00LocalTime time_9 = time_8.plusHours(1);int i = time_9.compareTo(time_8);>>> i = 1int i = time_8.compareTo(time_9);>>> i = -1int i = time_8.compareTo(LocalTime.of(8, 0, 0));>>> i = 0
- 此方法可对比出时间是否相等,假设 A.compareTo(B);
- A > B = 1
- A < B = -1
- A = B = 0
LocalTime、LocalDate、LocalDateTime 相互转化
// LocalTime + LocalDate = LocalDateTimeLocalDateTime localDateTime = LocalTime.now().atDate(LocalDate.now());LocalDateTime localDateTime = LocalDate.now().atTime(LocalTime.now());LocalDateTime localDateTime = LocalDateTime.of(LocalTime.now(),LocalDate.now());// LocalDateTime 转 LocalDateLocalDate localDate = LocalDateTime.now().toLocalDate();// LocalDateTime 转 LocalTimeLocalTime localTime = LocalDateTime.now().toLocalTime();// 获取今日开始时间 2023-04-21T00:00LocalDateTime localDateTime = LocalDate.now().atStartOfDay();// 获取今日开始时间 2023-04-21T00:00LocalDateTime startDateTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);// 获取今日结束时间 2023-04-21T23:59:59.999999999LocalDateTime endDateTime = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
String 与 LocalTime、LocalDate、LocalDateTime 相互转化
主要使用 format
和 parse
进行转换,使用方法基本相同
使用 DateTimeFormatter.ofPattern()
定义时间格式,再进行转换DateTimeFormatter
线程安全
format && parse
LocalTime.now().toString;>>> 默认输出格式 10:50:25.323LocalDate.now().toString()>>> 默认输出格式 2023-04-14LocalDateTime.now().toString();>>> 默认输出格式 2023-04-14T15:59:40// LocalTime 转 String 自定义输出格式,例如:**时**分**秒 该转化的 00 不会被省略DateTimeFormatter localTimeFormat = DateTimeFormatter.ofPattern("HH时mm分ss秒");String time = LocalTime.now().format(localTimeFormat);>>> 09时11分00秒// LocalDateTime 转 StringDateTimeFormatter localTimeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");String time = LocalDateTime.now().format(localTimeFormat);>>> 2023-04-14 15:59:40// String 转 LocalDateTimeLocalDateTime time = LocalDateTime.parse("2023-04-14 15:59:40", localTimeFormat);
Jackson 全局配置
在Stringboot 中,可自定义配置 Jackson 的序列化输出,使接口在 输入输出 统一规范
简单举个例子
@Bean // 装载配置 @Primary @ConditionalOnMissingBean public ObjectMapper objectMapper() { ObjectMapper mapper = create(); log.info(">>>>> JackSon 全局设置成功,版本号:{}", mapper.version()); return mapper; } private static ObjectMapper create() { ObjectMapper objectMapper = new ObjectMapper(); // 创建自定义 时间转换 模板 JavaTimeModule timeModule = new JavaTimeModule(); // 定义统一的时间格式 DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.CHINA); // 序列化 添加 LocalDateTime 类 对应的时间格式 timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter)); // 反序列化 支持时间戳 timeModule.addDeserializer(LocalDateTime.class, new MillisOrLocalDateTimeDeserializer(dateTimeFormatter)); // 定义统一的日期格式 DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.CHINA); // 序列化 添加 LocalDate 类 对应的日期格式 timeModule.addSerializer(LocalDate.class, new LocalDateSerializer(dateFormatter)); // 反序列化 timeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(dateFormatter)); // 注册自定义模板 objectMapper.registerModules(createJavaTimeModules()); return objectMapper; }
Date 与 LocalDate、LocalDateTime 相互转化
// Date 转 LocalDateTimeLocalDateTime localDateTime = new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();// LocalDateTime 转 DateDate date = Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant());// Date转LocalDateLocalDate localDate = new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();// LocalDate 转 Date 需要先将 LocalDate 转 LocalDateTimeDate date= Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant());
Long 与 LocalDate、LocalDateTime 相互转化
ZoneOffset.of(“+8”) 和 ZoneOffset.ofHours(8) 意义相同
long timeMillis = System.currentTimeMillis();// 时间戳(Long) 转 LocalDateTimeLocalDateTime localDateTime = Instant.ofEpochMilli(timeMillis).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();// LocalDateTime 转 时间戳(Long) 秒级Long second = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8));// LocalDateTime 转 时间戳(Long) 毫秒级Long milliSecond = LocalDateTime.now().toInstant(ZoneOffset.ofHours(8)).toEpochMilli();// 时间戳(Long) 转 LocalDateLocalDate localDate = Instant.ofEpochMilli(timeMillis).atZone(ZoneOffset.ofHours(8)).toLocalDate();// LocalDate 转 时间戳(Long) 秒级Long second = LocalDate.now().atStartOfDay().toEpochSecond(ZoneOffset.ofHours(8));// LocalDate 转 时间戳(Long) 毫秒级Long milliSecond = LocalDate.now().atStartOfDay().toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
常用时间操作方法两个时间相差时间Period.between(star,end)
统计 相差几年几个月几天
获得一个由两个日期之间的年数、月数和天数组成的周期,如果结束在开始之前,则此方法的结果可能是一个负周期。负号在每一年、每一个月和每一天都是一样的。
LocalDateTime star = LocalDateTime.of(2022, 3, 15, 16, 37, 10);LocalDateTime end = LocalDateTime.of(2024, 4, 20, 16, 37, 10);Period period = Period.between(star.toLocalDate(), end.toLocalDate());System.out.println(">>> 两个时间相差:" + period.getYears() + "年" + period.getMonths() + "月" + period.getDays() + "日");>>> 两个时间相差:2年1月5日
LocalDate.until
- 方法1:
Period until(ChronoLocalDate endDateExclusive);
与Period.between()
的使用相同类似,统计 相差几年几个月几天,可参考上一个案例 - 方法2:
long until(Temporal endExclusive, TemporalUnit unit);
支持指定单位(按年或按月或按天)分别统计
// ChronoUnit 可选择要计算的日期单位 年、月、日、小时、分钟 等等LocalDateTime star = LocalDateTime.of(2024, 3, 20, 16, 37, 10);LocalDateTime end = LocalDateTime.of(2024, 3, 21, 16, 37, 10);long until = star.until(end, ChronoUnit.DAYS);System.out.println(">>> 两个时间相差:" + until + "天");>>> 两个时间相差:1天// 使用 LocalDateTime 计算相隔日期,即使差了 1分钟 1毫秒 也不会计算1天LocalDateTime star = LocalDateTime.of(2024, 3, 20, 16, 37, 10);LocalDateTime end = LocalDateTime.of(2024, 3, 21, 16, 37, 9);long until = star.until(end, ChronoUnit.DAYS);System.out.println(">>> 两个时间相差:" + until + "天");>>> 两个时间相差:0天// 使用 LocalDate 计算相隔时差LocalDate star = LocalDate.of(2024, 3, 20);LocalDate end = LocalDate.of(2024, 3, 21);long until = star.until(end, ChronoUnit.DAYS);System.out.println(">>> 两个时间相差:" + until + "天");>>> 两个时间相差:1天
Duration.between(star,end)
专业计算相隔时差,支持指定单位转化,天 到 纳秒 单位都支持
只能用 LocalDateTime
LocalDateTime star = LocalDateTime.of(2024, 3, 20, 16, 37, 10);LocalDateTime end = LocalDateTime.of(2024, 3, 21, 16, 37, 10);Duration duration = Duration.between(star, end);System.out.println(">>> 两个时间相差:" + duration.toDays() + "天");System.out.println(">>> 两个时间相差:" + duration.toHours() + "小时");System.out.println(">>> 两个时间相差:" + duration.toMinutes() + "分钟");System.out.println(">>> 两个时间相差:" + duration.toMillis() + "毫秒");System.out.println(">>> 两个时间相差:" + duration.toNanos() + "纳秒");>>> 两个时间相差:1天>>> 两个时间相差:24小时>>> 两个时间相差:1440分钟>>> 两个时间相差:86400000毫秒>>> 两个时间相差:86400000000000纳秒
TemporalAdjuster
TemporalAdjuster 是函数接口,在TemporalAdjusters 类中有很多预定义的实现。TemporalAdjuster仅有一个带Temporal对象参数的抽象方法adjustInto()。
TemporalAdjuster可以执行复杂的日期操作,例如,可以获得下一个星期日对于日期、当月的最后一天、下一年的第一天。当然也可以通过旧的java.util.Calendar api实现。不同的是,新api使用预定义的实现抽象出底层逻辑。
TemporalAdjusters 类中预定义实现
TemporalAdjusters类有很多预定义的static方法返回TemporalAdjuster对象,使用不同方式调节Temporal对象而与Temporal实现无关。
// 也可以使用 LocalDateTime 带时刻LocalDate localDate = LocalDate.now(); // 当月第一天localDate.with(TemporalAdjusters.firstDayOfMonth());// 当月最后一天localDate.with(TemporalAdjusters.lastDayOfMonth());// 今年的第一天localDate.with(TemporalAdjusters.firstDayOfYear());// 今年的最后一天localDate.with(TemporalAdjusters.lastDayOfYear());// 下个月的第一天localDate.with(TemporalAdjusters.firstDayOfNextMonth());// 下一年的第一天localDate.with(TemporalAdjusters.firstDayOfNextYear());// 这个月的最后一个星期日localDate.with(TemporalAdjusters.dayOfWeekInMonth(-1,DayOfWeek.SUNDAY));// 这个月的倒数第二个星期日localDate.with(TemporalAdjusters.dayOfWeekInMonth(-2,DayOfWeek.SUNDAY));// 这个月的第一个星期日localDate.with(TemporalAdjusters.dayOfWeekInMonth(-1,DayOfWeek.SUNDAY));// 这个月的第二个星期日localDate.with(TemporalAdjusters.dayOfWeekInMonth(-1,DayOfWeek.SUNDAY));// 下个月的最后一个星期日localDate.with(TemporalAdjusters.lastInMonth(DayOfWeek.SUNDAY));// 上个星期五localDate.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));// 上个最近的星期五,包含今天的判断 如果今天星期五 则会返回今天日期localDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.FRIDAY));// 下个星期一localDate.with(TemporalAdjusters.next(DayOfWeek.MONDAY));// 下个最近的星期一,包含今天的判断 如果今天是星期一 则会返回今天日期localDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY));