目录
一.引言
二.LocalDateTime 获取与格式化
1.获取当前时间 LocalDateTime
2.根据时间戳获取 LocalDateTime
3.指定时间获取 LocalDataTime
4.LocalDataTime 格式化
三.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 获取与格式化
首先介绍如何生成 LocalDateTime 类。
1.获取当前时间 LocalDateTime
该方法开发环境中比较常见,一般是 Object 内加载一次获取当前相关的时间语义状态。
// 获取当前时间
val localDateTime = LocalDateTime.now()
2023-04-11T14:09:17.712
2.根据时间戳获取 LocalDateTime
多见于数据分析,将日志中的时间戳转化并统计相关指标。实际分析时将时间戳换成自己的时间戳即可。
val currentTimeStamp = System.currentTimeMillis() / 1000
val localDateTimeByTs = LocalDateTime.ofEpochSecond(currentTimeStamp, 0, ZoneOffset.ofHours(8))
2023-04-11T14:12:25
3.指定时间获取 LocalDataTime
LocalDateTime 提供方法可以直接指定年月日、小时分钟秒...
val localDateTimeByAssign = LocalDateTime.of(2023, 3, 5, 10, 20, 30)
下面指定 2023 年 3 月 5 日 10 点 20 分 30 秒:
2023-03-05T10:20:30
4.LocalDataTime 格式化
格式化多见于日志输出,因为 '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
三.LocalDateTime 读取时间细节
import java.time.temporal.{ChronoField, ChronoUnit}
// 获取当前时间
val localDateTime = LocalDateTime.now()
1.获取年-Year
val year = localDateTime.getYear
val year2 = localDateTime.get(ChronoField.YEAR)
2.获取月-Month
val month = localDateTime.getMonth
val month2 = localDateTime.get(ChronoField.MONTH_OF_YEAR)
这里推荐大家使用第二种,第一种 getMonth 返回的是 Month 类,打印结果为: "APRIL" 而不是 Int 的月份。
3.获取日-Day
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 即可。
4.获取时-Hour
val hour = localDateTime.get(ChronoField.HOUR_OF_DAY)
5.获取分-Minute
val minute = localDateTime.get(ChronoField.MINUTE_OF_HOUR)
6.获取秒-Second
val second = localDateTime.get(ChronoField.SECOND_OF_MINUTE)
7.获取时间戳-TimeStamp
val localDateTime = LocalDateTime.now()
println(localDateTime.toEpochSecond(ZoneOffset.ofHours(8)))
1681195918
如果需要毫秒形式需要补 000
8.TimeUtil 工具类
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)
四.LocalDateTime 修改
除了获取指定时间 LocaDateTime 外,有时候还需要对时间做适当修改。
1.加一年
val plusYearV1 = localDateTime.plusYears(1)
val plusYearV2 = localDateTime.plus(1, ChronoUnit.YEARS)
2024-04-11T14:59:40.311
2.加一月
// 加一月
val plusMonthV1 = localDateTime.plusMonths(1)
val plusMonthV2 = localDateTime.minus(1, ChronoUnit.MONTHS)
3.加一天
val plusDayV1 = localDateTime.plusDays(1)
val plusDayV2 = localDateTime.plus(1, ChronoUnit.DAYS)
4.通过 `with` 修改
4.1 指定年份
val withYearV1 = localDateTime.withYear(2021)
val withYearV2 = localDateTime.`with`(ChronoField.YEAR, 2020)
4.2 firstDayOfYear 今年第一天
println(localDateTime.`with`(firstDayOfYear))
2023-01-01T15:11:32.817
4.3 dayOfWeekInMonth 本月的第几个周几
返回本月的第一个周五:
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
4.4 firstDayOfMonth 当月第一天
println(localDateTime.`with`(firstDayOfMonth()))
2023-04-01T15:20:29.200
4.5 firstDayOfNextMonth 下月第一天
println(localDateTime.`with`(firstDayOfNextMonth()))
2023-05-01T15:20:51.163
4.6 firstDayOfNextYear 明年第一天
println(localDateTime.`with`(firstDayOfNextYear()))
2024-01-01T15:21:31.954
4.7 firstInMonth 本月第一个周几
本月第一个周五
println(localDateTime.`with`(firstInMonth(DayOfWeek.FRIDAY)))
2023-04-07T15:22:26.534
4.8 lastDayOfYear 本年最后一天
println(localDateTime.`with`(lastDayOfYear))
2023-12-31T15:24:25.833
4.9 lastInMonth 本月最后一个周几
本月最后一个周一
println(localDateTime.`with`(lastInMonth(DayOfWeek.MONDAY)))
2023-04-24T15:25:26.660
4.10 next 下一个周几
下一个周一
println(localDateTime.`with`(next(DayOfWeek.MONDAY)))
2023-04-17T15:26:42.145
4.11 previous 上一个周几
上一个周五
println(localDateTime.`with`(previous(DayOfWeek.FRIDAY)))
2023-04-07T15:27:26.763
4.12 nextOrSame 下一个周几且是否当日
下一个周五,不是当日所以正常返回
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 可以看作是大于等于和大于的区别。
4.13 previousOrSame 上一个周几且是否当日
上一个周五
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 可以看作是小于等于和小于的区别。
五.LocalDateTime 与时间间隔 Duration
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)
1.差几天
val days = duration.toDays
2.差几小时
val hours = duration.toHours
3.差几分钟
val minutes = duration.toMinutes
4.差几秒
val seconds = duration.getSeconds
5.差几毫秒
val milliSeconds = duration.toMillis
6.差几纳秒
val nanoSeconds = duration.toNanos
7.DurationUtil 工具类
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 是线程安全的