Scala - 时间工具类 LocalDateTime 常用方法整理
作者:mmseoamin日期:2023-12-14

目录

一.引言

二.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 获取与格式化

首先介绍如何生成 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.指定时间获取 LocalDateTime

LocalDateTime 提供方法可以直接指定年月日、小时分钟秒...

    val localDateTimeByAssign = LocalDateTime.of(2023, 3, 5, 10, 20, 30)

下面指定 2023 年 3 月 5 日 10 点 20 分 30 秒:

2023-03-05T10:20:30

4.根据指定样式数据获取 LocalDateTime

    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

5.LocalDateTime 格式化

格式化多见于日志输出,因为 '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

Scala - 时间工具类 LocalDateTime 常用方法整理,第1张

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 是线程安全的