| New file |
| | |
| | | package com.ard.sample.utils; |
| | | |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.time.*; |
| | | import java.time.format.DateTimeFormatter; |
| | | |
| | | /** |
| | | * 时间戳工具类(支持毫秒级/秒级时间戳,基于Java 8+时间API) |
| | | * 功能:加/减时间、转换为LocalDateTime、格式化字符串等 |
| | | */ |
| | | @Component |
| | | public class TimestampUtils { |
| | | |
| | | // 默认时区:北京时间(Asia/Shanghai) |
| | | private static final ZoneId DEFAULT_ZONE = ZoneId.of("Asia/Shanghai"); |
| | | |
| | | // 默认日期时间格式:yyyy-MM-dd HH:mm:ss |
| | | private static final DateTimeFormatter DEFAULT_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
| | | |
| | | // 时间单位常量(毫秒) |
| | | private static final long ONE_SECOND = 1000L; // 1秒 = 1000毫秒 |
| | | private static final long ONE_MINUTE = 60 * ONE_SECOND; // 1分钟 = 60秒 |
| | | private static final long ONE_HOUR = 60 * ONE_MINUTE; // 1小时 = 60分钟 |
| | | private static final long ONE_DAY = 24 * ONE_HOUR; // 1天 = 24小时 |
| | | |
| | | |
| | | // -------------------------- 毫秒级时间戳操作 -------------------------- |
| | | |
| | | /** |
| | | * 毫秒级时间戳 + N天 |
| | | * @param millisTimestamp 原毫秒级时间戳(13位) |
| | | * @param days 天数(正数加,负数减) |
| | | * @return 计算后的毫秒级时间戳 |
| | | */ |
| | | public long plusDaysByMillis(long millisTimestamp, int days) { |
| | | return Instant.ofEpochMilli(millisTimestamp) |
| | | .plusMillis(days * ONE_DAY) |
| | | .toEpochMilli(); |
| | | } |
| | | |
| | | /** |
| | | * 毫秒级时间戳 + N小时 |
| | | * @param millisTimestamp 原毫秒级时间戳(13位) |
| | | * @param hours 小时数(正数加,负数减) |
| | | * @return 计算后的毫秒级时间戳 |
| | | */ |
| | | public long plusHoursByMillis(long millisTimestamp, int hours) { |
| | | return Instant.ofEpochMilli(millisTimestamp) |
| | | .plusMillis(hours * ONE_HOUR) |
| | | .toEpochMilli(); |
| | | } |
| | | |
| | | /** |
| | | * 毫秒级时间戳 + N分钟 |
| | | * @param millisTimestamp 原毫秒级时间戳(13位) |
| | | * @param minutes 分钟数(正数加,负数减) |
| | | * @return 计算后的毫秒级时间戳 |
| | | */ |
| | | public long plusMinutesByMillis(long millisTimestamp, int minutes) { |
| | | return Instant.ofEpochMilli(millisTimestamp) |
| | | .plusMillis(minutes * ONE_MINUTE) |
| | | .toEpochMilli(); |
| | | } |
| | | |
| | | /** |
| | | * 毫秒级时间戳 + N秒 |
| | | * @param millisTimestamp 原毫秒级时间戳(13位) |
| | | * @param seconds 秒数(正数加,负数减) |
| | | * @return 计算后的毫秒级时间戳 |
| | | */ |
| | | public long plusSecondsByMillis(long millisTimestamp, int seconds) { |
| | | return Instant.ofEpochMilli(millisTimestamp) |
| | | .plusMillis(seconds * ONE_SECOND) |
| | | .toEpochMilli(); |
| | | } |
| | | |
| | | |
| | | // -------------------------- 秒级时间戳操作 -------------------------- |
| | | |
| | | /** |
| | | * 秒级时间戳 + N天(自动转换为毫秒级计算,结果转回秒级) |
| | | * @param secondTimestamp 原秒级时间戳(10位) |
| | | * @param days 天数(正数加,负数减) |
| | | * @return 计算后的秒级时间戳 |
| | | */ |
| | | public long plusDaysBySecond(long secondTimestamp, int days) { |
| | | long millis = secondTimestamp * ONE_SECOND; |
| | | long newMillis = plusDaysByMillis(millis, days); |
| | | return newMillis / ONE_SECOND; |
| | | } |
| | | |
| | | /** |
| | | * 秒级时间戳 + N小时 |
| | | * @param secondTimestamp 原秒级时间戳(10位) |
| | | * @param hours 小时数(正数加,负数减) |
| | | * @return 计算后的秒级时间戳 |
| | | */ |
| | | public long plusHoursBySecond(long secondTimestamp, int hours) { |
| | | long millis = secondTimestamp * ONE_SECOND; |
| | | long newMillis = plusHoursByMillis(millis, hours); |
| | | return newMillis / ONE_SECOND; |
| | | } |
| | | |
| | | /** |
| | | * 秒级时间戳 + N分钟 |
| | | * @param secondTimestamp 原秒级时间戳(10位) |
| | | * @param minutes 分钟数(正数加,负数减) |
| | | * @return 计算后的秒级时间戳 |
| | | */ |
| | | public long plusMinutesBySecond(long secondTimestamp, int minutes) { |
| | | long millis = secondTimestamp * ONE_SECOND; |
| | | long newMillis = plusMinutesByMillis(millis, minutes); |
| | | return newMillis / ONE_SECOND; |
| | | } |
| | | |
| | | /** |
| | | * 秒级时间戳 + N秒 |
| | | * @param secondTimestamp 原秒级时间戳(10位) |
| | | * @param seconds 秒数(正数加,负数减) |
| | | * @return 计算后的秒级时间戳 |
| | | */ |
| | | public long plusSecondsBySecond(long secondTimestamp, int seconds) { |
| | | return secondTimestamp + seconds; // 秒级直接加减,无需转毫秒 |
| | | } |
| | | |
| | | |
| | | // -------------------------- 时间戳转换为LocalDateTime -------------------------- |
| | | |
| | | /** |
| | | * 毫秒级时间戳转换为LocalDateTime(默认时区:北京时间) |
| | | * @param millisTimestamp 毫秒级时间戳(13位) |
| | | * @return LocalDateTime对象 |
| | | */ |
| | | public LocalDateTime toLocalDateTimeByMillis(long millisTimestamp) { |
| | | return LocalDateTime.ofInstant( |
| | | Instant.ofEpochMilli(millisTimestamp), |
| | | DEFAULT_ZONE |
| | | ); |
| | | } |
| | | |
| | | /** |
| | | * 秒级时间戳转换为LocalDateTime(默认时区:北京时间) |
| | | * @param secondTimestamp 秒级时间戳(10位) |
| | | * @return LocalDateTime对象 |
| | | */ |
| | | public LocalDateTime toLocalDateTimeBySecond(long secondTimestamp) { |
| | | return LocalDateTime.ofInstant( |
| | | Instant.ofEpochSecond(secondTimestamp), // 直接用ofEpochSecond处理秒级 |
| | | DEFAULT_ZONE |
| | | ); |
| | | } |
| | | |
| | | |
| | | // -------------------------- 时间戳格式化为字符串 -------------------------- |
| | | |
| | | /** |
| | | * 毫秒级时间戳格式化为字符串(默认格式:yyyy-MM-dd HH:mm:ss) |
| | | * @param millisTimestamp 毫秒级时间戳(13位) |
| | | * @return 格式化后的字符串 |
| | | */ |
| | | public String formatByMillis(long millisTimestamp) { |
| | | return formatByMillis(millisTimestamp, DEFAULT_FORMATTER); |
| | | } |
| | | |
| | | /** |
| | | * 毫秒级时间戳格式化为自定义格式字符串 |
| | | * @param millisTimestamp 毫秒级时间戳(13位) |
| | | * @param formatter 自定义格式器(如:DateTimeFormatter.ofPattern("yyyy/MM/dd")) |
| | | * @return 格式化后的字符串 |
| | | */ |
| | | public String formatByMillis(long millisTimestamp, DateTimeFormatter formatter) { |
| | | LocalDateTime dateTime = toLocalDateTimeByMillis(millisTimestamp); |
| | | return dateTime.format(formatter); |
| | | } |
| | | |
| | | /** |
| | | * 秒级时间戳格式化为字符串(默认格式:yyyy-MM-dd HH:mm:ss) |
| | | * @param secondTimestamp 秒级时间戳(10位) |
| | | * @return 格式化后的字符串 |
| | | */ |
| | | public String formatBySecond(long secondTimestamp) { |
| | | return formatBySecond(secondTimestamp, DEFAULT_FORMATTER); |
| | | } |
| | | |
| | | /** |
| | | * 秒级时间戳格式化为自定义格式字符串 |
| | | * @param secondTimestamp 秒级时间戳(10位) |
| | | * @param formatter 自定义格式器 |
| | | * @return 格式化后的字符串 |
| | | */ |
| | | public String formatBySecond(long secondTimestamp, DateTimeFormatter formatter) { |
| | | LocalDateTime dateTime = toLocalDateTimeBySecond(secondTimestamp); |
| | | return dateTime.format(formatter); |
| | | } |
| | | |
| | | /** |
| | | * 取原时间戳的时间部分,与当前日期组合成新时间戳 |
| | | * @param originalTimestamp 原时间戳(毫秒,如System.currentTimeMillis()返回值) |
| | | * @return 组合后的新时间戳(毫秒) |
| | | */ |
| | | public Long combine( Long originalTimestamp) { |
| | | // 1. 校验原时间戳合法性 |
| | | if (originalTimestamp == null || originalTimestamp < 0) { |
| | | throw new IllegalArgumentException("原时间戳无效"); |
| | | } |
| | | |
| | | // 2. 解析原时间戳,提取时间部分(时、分、秒、毫秒) |
| | | // 原时间戳转换为ZonedDateTime(带时区的日期时间) |
| | | ZonedDateTime originalZoned = Instant.ofEpochMilli(originalTimestamp) |
| | | .atZone(DEFAULT_ZONE); |
| | | // 提取时间部分:时、分、秒、纳秒(纳秒需转换为毫秒级精度) |
| | | int hour = originalZoned.getHour(); |
| | | int minute = originalZoned.getMinute(); |
| | | int second = originalZoned.getSecond(); |
| | | int nanoOfSecond = originalZoned.getNano(); // 纳秒(1毫秒=1,000,000纳秒) |
| | | int milliOfSecond = nanoOfSecond / 1_000_000; // 取毫秒部分(0-999) |
| | | |
| | | |
| | | // 3. 获取当前日期(年月日) |
| | | LocalDate currentDate = LocalDate.now(DEFAULT_ZONE); |
| | | |
| | | |
| | | // 4. 组合新的日期时间:当前年月日 + 原时间的时分秒毫秒 |
| | | LocalTime combinedTime = LocalTime.of(hour, minute, second, nanoOfSecond); |
| | | LocalDateTime combinedDateTime = LocalDateTime.of(currentDate, combinedTime); |
| | | |
| | | |
| | | // 5. 转换为新时间戳(毫秒) |
| | | return combinedDateTime.atZone(DEFAULT_ZONE) |
| | | .toInstant() |
| | | .toEpochMilli(); |
| | | } |
| | | |
| | | /** |
| | | * 获取指定时间戳当天0点0分0秒的时间戳(带时区处理) |
| | | * @param timestamp 指定时间戳(毫秒,如System.currentTimeMillis()返回值) |
| | | * @return 当天0点的时间戳(毫秒) |
| | | */ |
| | | public Long getDayStartTimestamp(Long timestamp) { |
| | | // 校验参数合法性 |
| | | if (timestamp == null || timestamp < 0) { |
| | | throw new IllegalArgumentException("时间戳无效(不能为null或负数)"); |
| | | } |
| | | // 1. 将时间戳转换为带时区的日期时间 |
| | | ZonedDateTime zonedDateTime = Instant.ofEpochMilli(timestamp) |
| | | .atZone(DEFAULT_ZONE); |
| | | |
| | | // 2. 获取当天的起始时刻(00:00:00.000) |
| | | // atStartOfDay(zoneId) 会自动处理时区特殊情况(如夏令时切换) |
| | | ZonedDateTime dayStart = zonedDateTime.toLocalDate() |
| | | .atStartOfDay(DEFAULT_ZONE); |
| | | |
| | | // 3. 转换为毫秒级时间戳 |
| | | return dayStart.toInstant().toEpochMilli(); |
| | | } |
| | | } |