目录
一.引言
二.LocalDateTime 获取与格式化
1.获取当前时间 LocalDateTime
2.根据时间戳获取 LocalDateTime
3.指定时间获取 LocalDateTime
4.根据指定样式数据获取 LocalDateTime
5.LocalDateTime 格式化
三.LocalDateTime 读取时间细节
1.获取年-Year
2.获取月-Month
3.获取日-Day
4.获取时-Hour
5.获取分-Minute
6.获取秒-Second
7.获取时间戳-TimeStamp
8.TimeUtil 工具类
四.LocalDateTime 修改
1.加一年
2.加一月
3.加一天
4.通过 `with` 修改
4.1 指定年份
4.2 firstDayOfYear 今年第一天
4.3 dayOfWeekInMonth 本月的第几个周几
4.4 firstDayOfMonth 当月第一天
4.5 firstDayOfNextMonth 下月第一天
4.6 firstDayOfNextYear 明年第一天
4.7 firstInMonth 本月第一个周几
4.8 lastDayOfYear 本年最后一天
4.9 lastInMonth 本月最后一个周几
4.10 next 下一个周几
4.11 previous 上一个周几
4.12 nextOrSame 下一个周几且是否当日
4.13 previousOrSame 上一个周几且是否当日
五.LocalDateTime 与时间间隔 Duration
1.差几天
2.差几小时
3.差几分钟
4.差几秒
5.差几毫秒
6.差几纳秒
7.DurationUtil 工具类
六.总结
开发中遇到需要判断是否周末即 is_weekend 的逻辑需求,这里使用 LocalDateTime 解决问题并记录下该类的其他用法,方便后续查阅。
import java.time.format.DateTimeFormatter
首先介绍如何生成 LocalDateTime 类。
该方法开发环境中比较常见,一般是 Object 内加载一次获取当前相关的时间语义状态。
// 获取当前时间 val localDateTime = LocalDateTime.now()
2023-04-11T14:09:17.712
多见于数据分析,将日志中的时间戳转化并统计相关指标。实际分析时将时间戳换成自己的时间戳即可。
val currentTimeStamp = System.currentTimeMillis() / 1000 val localDateTimeByTs = LocalDateTime.ofEpochSecond(currentTimeStamp, 0, ZoneOffset.ofHours(8))
2023-04-11T14:12:25
LocalDateTime 提供方法可以直接指定年月日、小时分钟秒...
val localDateTimeByAssign = LocalDateTime.of(2023, 3, 5, 10, 20, 30)
下面指定 2023 年 3 月 5 日 10 点 20 分 30 秒:
2023-03-05T10:20:30
val time = "2023-04-19 13:00:00" val localDateTimeFromStr = LocalDateTime.parse(time, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) println(localDateTimeFromStr)
常用于日志解析不同格式的时间数据使用。
2023-04-19T13:00
格式化多见于日志输出,因为 '2023-03-05T10:20:30' 这样的字符串并不适合我们任务解析与标识,大家可以自定义不同的格式化在 ofPattern 中。
val localDateTime = LocalDateTime.now() val dateTimeFormat = DateTimeFormatter.ofPattern("yyyyMMddHHmm") val dataTimeFormatV2 = DateTimeFormatter.ofPattern("yyyy-MM-dd") println(dateTimeFormat.format(localDateTime)) println(dataTimeFormatV2.format(localDateTime))
202304111416 2023-04-11
import java.time.temporal.{ChronoField, ChronoUnit} // 获取当前时间 val localDateTime = LocalDateTime.now()
val year = localDateTime.getYear val year2 = localDateTime.get(ChronoField.YEAR)
val month = localDateTime.getMonth val month2 = localDateTime.get(ChronoField.MONTH_OF_YEAR)
这里推荐大家使用第二种,第一种 getMonth 返回的是 Month 类,打印结果为: "APRIL" 而不是 Int 的月份。
val dayOfMonth = localDateTime.get(ChronoField.DAY_OF_MONTH) val dayOfWeek = localDateTime.get(ChronoField.DAY_OF_WEEK)
DAY_OF_MONTH 是这个月的第几天即我们常说的今天几号
DAY_OF_WEEK 是当前周的第几天及我们常说的今天周几,其范围为 1-7,博主的需求其实用到了这一行就够了,is_weekend 判断 dayOfWeek 是不是 6-7 即可。
val hour = localDateTime.get(ChronoField.HOUR_OF_DAY)
val minute = localDateTime.get(ChronoField.MINUTE_OF_HOUR)
val second = localDateTime.get(ChronoField.SECOND_OF_MINUTE)
val localDateTime = LocalDateTime.now() println(localDateTime.toEpochSecond(ZoneOffset.ofHours(8)))
1681195918
如果需要毫秒形式需要补 000
def getTimeDetail(isNow: Boolean): mutable.HashMap[String, Int] = { val timeMap = mutable.HashMap[String, Int]() // 获取当前时间 val localDateTime = LocalDateTime.now() val year = localDateTime.getYear val year2 = localDateTime.get(ChronoField.YEAR) val month = localDateTime.getMonth val month2 = localDateTime.get(ChronoField.MONTH_OF_YEAR) val dayOfMonth = localDateTime.get(ChronoField.DAY_OF_MONTH) val dayOfWeek = localDateTime.get(ChronoField.DAY_OF_WEEK) val isWeekend = if (dayOfWeek.equals(6) || dayOfWeek.equals(7)) 1 else 0 val hour = localDateTime.get(ChronoField.HOUR_OF_DAY) val minute = localDateTime.get(ChronoField.MINUTE_OF_HOUR) val second = localDateTime.get(ChronoField.SECOND_OF_MINUTE) timeMap.put("year", year) timeMap.put("month", month2) timeMap.put("day", dayOfMonth) timeMap.put("week", dayOfWeek) timeMap.put("hour", hour) timeMap.put("minute", minute) timeMap.put("second", second) timeMap.put("isWeekend", isWeekend) println(s"年 $year $year2 月: $month 月: $month2 日期: $dayOfMonth 周: $dayOfWeek") timeMap }
直接调用该方法获取全部所需时间信息:
Map(second -> 6, hour -> 14, week -> 2, year -> 2023, minute -> 53, month -> 4, isWeekend -> 0, day -> 11)
除了获取指定时间 LocaDateTime 外,有时候还需要对时间做适当修改。
val plusYearV1 = localDateTime.plusYears(1) val plusYearV2 = localDateTime.plus(1, ChronoUnit.YEARS)
2024-04-11T14:59:40.311
// 加一月 val plusMonthV1 = localDateTime.plusMonths(1) val plusMonthV2 = localDateTime.minus(1, ChronoUnit.MONTHS)
val plusDayV1 = localDateTime.plusDays(1) val plusDayV2 = localDateTime.plus(1, ChronoUnit.DAYS)
val withYearV1 = localDateTime.withYear(2021) val withYearV2 = localDateTime.`with`(ChronoField.YEAR, 2020)
println(localDateTime.`with`(firstDayOfYear)) 2023-01-01T15:11:32.817
返回本月的第一个周五:
println(localDateTime.`with`(dayOfWeekInMonth(1, DayOfWeek.FRIDAY))) 2023-04-07T15:16:02.061
返回本月的最后一个周一:
println(localDateTime.`with`(dayOfWeekInMonth(-1, DayOfWeek.MONDAY))) 2023-04-24T15:18:31.713
println(localDateTime.`with`(firstDayOfMonth())) 2023-04-01T15:20:29.200
println(localDateTime.`with`(firstDayOfNextMonth())) 2023-05-01T15:20:51.163
println(localDateTime.`with`(firstDayOfNextYear())) 2024-01-01T15:21:31.954
本月第一个周五
println(localDateTime.`with`(firstInMonth(DayOfWeek.FRIDAY))) 2023-04-07T15:22:26.534
println(localDateTime.`with`(lastDayOfYear)) 2023-12-31T15:24:25.833
本月最后一个周一
println(localDateTime.`with`(lastInMonth(DayOfWeek.MONDAY))) 2023-04-24T15:25:26.660
下一个周一
println(localDateTime.`with`(next(DayOfWeek.MONDAY))) 2023-04-17T15:26:42.145
上一个周五
println(localDateTime.`with`(previous(DayOfWeek.FRIDAY))) 2023-04-07T15:27:26.763
下一个周五,不是当日所以正常返回
println(localDateTime.`with`(nextOrSame(DayOfWeek.FRIDAY))) 2023-04-14T15:29:15.985
下一个周二,是当日所以返回当前日期即命中了 Same
println(localDateTime.`with`(nextOrSame(DayOfWeek.TUESDAY))) 2023-04-11T15:30:20.639
这里 nextOrSame 和 next 可以看作是大于等于和大于的区别。
上一个周五
println(localDateTime.`with`(previousOrSame(DayOfWeek.FRIDAY))) 2023-04-07T15:31:55.037
上一个周二
println(localDateTime.`with`(previousOrSame(DayOfWeek.TUESDAY))) 2023-04-11T15:31:30.415
和上面的 nextOrSame 同理,这里 previouesOrSame 和 previous 可以看作是小于等于和小于的区别。
Duration 与 LocalDateTime 集合可以计算两个时间类之间的差距。
val from = LocalDateTime.of(2022, 1, 1, 0, 0, 0) val to = LocalDateTime.of(2023, 1, 1, 0, 0, 0) val duration = Duration.between(from, to)
val days = duration.toDays
val hours = duration.toHours
val minutes = duration.toMinutes
val seconds = duration.getSeconds
val milliSeconds = duration.toMillis
val nanoSeconds = duration.toNanos
def timeDuration(): Unit = { val from = LocalDateTime.of(2022, 1, 1, 0, 0, 0) val to = LocalDateTime.of(2023, 1, 1, 0, 0, 0) val duration = Duration.between(from, to) // 间隔内的 总天数 小时数 分钟数 秒数 毫秒数 纳秒数 val days = duration.toDays val hours = duration.toHours val minutes = duration.toMinutes val seconds = duration.getSeconds val milliSeconds = duration.toMillis val nanoSeconds = duration.toNanos println(days, hours, minutes, seconds, milliSeconds, nanoSeconds) }
直接调用方法获取全部 Duration:
(365,8760,525600,31536000,31536000000,31536000000000000)
• Duration 可以便捷得到两个 LocalDateTime 之间的间隔信息
• LocalDateTime 可以获取年、月、日,下一个年、月、日等
• LocalTime 相比 LocalDateTime 无法获取更细粒度的秒信息
• TemporalAdjusters 内含多个时间函数静态方法,可以按需调用
• ChronoField 包含多类型时间字段,除上面介绍外,还有 AM、PM 类型时间获取
• ChronoUnit 主要为时间单位,例如 YEARS、MONTHS、DAYS 等等
• 与 SimpleDataFormat 相比,DateTimeFormatter 是线程安全的