package com.usky.rule.util; import com.usky.rule.constant.DateTimeConstants; import com.usky.rule.constant.RegExpConstants; import feign.Util; import java.sql.Timestamp; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.format.DateTimeFormatter; import java.util.Date; public class DateTimeUtil { private DateTimeUtil() { } public static LocalDateTime dateToLocalDateTime(Date date) { return date != null ? LocalDateTime.ofInstant(date.toInstant(), getZoneId()) : null; } public static Date localDateTimeToDate(LocalDateTime dateTime) { return dateTime != null ? Date.from(dateTime.atZone(getZoneId()).toInstant()) : null; } public static LocalDateTime timestampToLocalDateTime(Timestamp timestamp) { return timestamp != null ? LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp.getTime()), getZoneId()) : null; } public static String format(LocalDateTime dateTime) { return dateTime != null ? dateTime.format(DateTimeConstants.DATE_TIME_FORMATTER) : null; } public static String format(LocalDateTime dateTime, DateTimeFormatter formatter) { return dateTime != null ? dateTime.format(formatter) : null; } public static LocalDateTime parse(String dateTime) { return parse(dateTime, DateTimeConstants.DATE_TIME_FORMATTER); } public static LocalDateTime parse(String dateTime, DateTimeFormatter formatter) { return Util.isNotBlank(dateTime) ? LocalDateTime.parse(dateTime, formatter) : null; } /** * 将 Unix 时间戳转为东八区 {@link LocalDateTime}。 * 小于 1e12 的数值按「秒」理解,否则按「毫秒」(兼容 10 位秒级与 13 位毫秒级)。 */ public static LocalDateTime fromEpochMillisOrSeconds(long epoch) { long millis = epoch < 1_000_000_000_000L ? epoch * 1000L : epoch; return LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), getZoneId()); } /** * 解析 MQ/设备上报中的时间字段:支持 Number 或纯数字字符串(秒/毫秒时间戳), * 也兼容原有 {@link DateTimeConstants#SIMPLE_DATE_TIME_FORMATTER}、{@link DateTimeConstants#DATE_TIME_FORMATTER} 字符串。 */ public static LocalDateTime parseMessageTimestamp(Object raw) { if (raw == null) { return null; } if (raw instanceof Number) { return fromEpochMillisOrSeconds(((Number) raw).longValue()); } String s = raw.toString().trim(); if (!Util.isNotBlank(s)) { return null; } if (s.chars().allMatch(Character::isDigit)) { if (s.length() == 14 && RegExpConstants.SIMPLE_DATE_TIME_PATTERN.matcher(s).matches()) { return parse(s, DateTimeConstants.SIMPLE_DATE_TIME_FORMATTER); } return fromEpochMillisOrSeconds(Long.parseLong(s)); } return parse(s, DateTimeConstants.DATE_TIME_FORMATTER); } public static long toEpochMilli(LocalDateTime dateTime) { if (dateTime == null) { throw new IllegalArgumentException("dateTime is null"); } else { return dateTime.atZone(getZoneId()).toInstant().toEpochMilli(); } } public static ZoneId getZoneId() { return ZoneOffset.of("+8"); } public static boolean isValidDateTime(String dateTime) { int dataTimeStringLength = 14; return dateTime.length() != 14 ? false : RegExpConstants.SIMPLE_DATE_TIME_PATTERN.matcher(dateTime).matches(); } public static String secondToTime(Long second) { if (second != null && second != 0L) { long days = second / 86400L; second = second % 86400L; long hours = second / 3600L; second = second % 3600L; long minutes = second / 60L; second = second % 60L; return days > 0L ? String.format("%d天%d小时%d分%d秒", days, hours, minutes, second) : String.format("%d小时%d分%d秒", hours, minutes, second); } else { return ""; } } }