package com.imyeyu.utils; import com.imyeyu.java.TimiJava; import java.text.SimpleDateFormat; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.temporal.ChronoUnit; import java.util.Date; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 时间转换相关 * * @author 夜雨 * @version 2021-06-10 20:07 */ public class Time { // ---------- 格式化 ---------- /** 格式化 yy */ public static final SimpleDateFormat year = new SimpleDateFormat("yy"); /** 格式化 yyyy */ public static final SimpleDateFormat yearFull = new SimpleDateFormat("yyyy"); /** 格式化 M */ public static final SimpleDateFormat month = new SimpleDateFormat("M"); /** 格式化 MM */ public static final SimpleDateFormat monthFull = new SimpleDateFormat("MM"); /** 格式化 d */ public static final SimpleDateFormat day = new SimpleDateFormat("d"); /** 格式化 dd */ public static final SimpleDateFormat dayFull = new SimpleDateFormat("dd"); /** 格式化 HH */ public static final SimpleDateFormat hour = new SimpleDateFormat("HH"); /** 格式化 mm */ public static final SimpleDateFormat minute = new SimpleDateFormat("mm"); /** 格式化 ss */ public static final SimpleDateFormat second = new SimpleDateFormat("ss"); /** 格式化 hh:mm */ public static final SimpleDateFormat hhmm = new SimpleDateFormat("HH:mm"); /** 格式化 mm:ss */ public static final SimpleDateFormat mmss = new SimpleDateFormat("mm:ss"); /** 格式化 yyyyMMdd */ public static final SimpleDateFormat ymd = new SimpleDateFormat("yyyyMMdd"); /** 格式化 HH:mm:ss.SSS */ public static final SimpleDateFormat log = new SimpleDateFormat("[HH:mm:ss.SSS]"); /** 格式化 HH:mm:ss.SSS */ public static final SimpleDateFormat longLog = new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss.SSS]"); /** 格式化 yyyy-MM-dd */ public static final SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd"); /** 格式化 HH:mm:ss */ public static final SimpleDateFormat time = new SimpleDateFormat("HH:mm:ss"); /** 格式化 yyyy-MM-dd HH:mm:ss */ public static final SimpleDateFormat dateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); /** 格式化 yyyy-MM-dd'T'HH:mm:ss */ public static final SimpleDateFormat dateTimeT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); // ---------- 长整型时间戳 ---------- /** 1 秒时间戳 */ public static final long S = 1000; /** 1 分钟时间戳 */ public static final long M = S * 60; /** 1 小时时间戳 */ public static final long H = M * 60; /** 1 天时间戳 */ public static final long D = H * 24; // ---------- 整型时间戳 ---------- /** 1 秒时间戳(整型) */ public static final int SI = 1000; /** 1 分钟时间戳(整型) */ public static final int MI = SI * 60; /** 1 小时时间戳(整型) */ public static final int HI = MI * 60; /** 1 天时间戳(整型) */ public static final int DI = HI * 24; /** * 计算两个时间戳精确的日期时间差 * * @param begin 开始时间戳 * @param end 结束时间戳 * @return 时差 */ public static Between between(long begin, long end) { if (end < begin) { throw new IllegalArgumentException("end time must greater than begin time:" + end + " < " + begin); } LocalDateTime ldtBegin = toLocalDateTime(begin); LocalDateTime ldtEnd = toLocalDateTime(end); Between between = new Between(); between.year = (int) ChronoUnit.YEARS.between(ldtBegin, ldtEnd); between.month = (int) ChronoUnit.MONTHS.between(ldtBegin, ldtEnd) % 12; between.day = (int) ChronoUnit.DAYS.between(ldtBegin.plusMonths(between.year * 12L + between.month), ldtEnd); between.hour = (int) (ChronoUnit.HOURS.between(ldtBegin, ldtEnd) - ChronoUnit.DAYS.between(ldtBegin, ldtEnd) * 24); between.minute = (int) ChronoUnit.MINUTES.between(ldtBegin, ldtEnd) % 60; between.second = (int) ChronoUnit.SECONDS.between(ldtBegin, ldtEnd) % 60; between.millis = (int) ((end - begin) % 1000); return between; } /** * 获取此刻毫秒 * * @return 毫秒 */ public static long now() { return System.currentTimeMillis(); } /** * 获取当前时间 yyyy-MM-dd HH:mm:ss * * @return 当前时间 */ public static String nowString() { return toDateTime(new Date()); } /** * 获取昨天零时时间戳 * * @return 昨天零时时间戳 */ public static long yesterday() { return today() - D; } /** * 获取今天零时时间戳 * * @return 今天零时时间戳 */ public static long today() { long now = now(); final long H8 = H * 8; return ((now + H8 - (now + H8) % (H * 24)) - H8); } /** * 获取明天零时时间戳 * * @return 明天零时时间戳 */ public static long tomorrow() { return today() + D; } /** * 转义为日期 yyyy-MM-dd * * @param unixTime 时间戳 * @return 日期字符串 */ public static String toDate(long unixTime) { return date.format(unixTime); } /** * 转义为时间 HH:mm:ss * * @param unixTime 时间戳 * @return 时间字符串 */ public static String toTime(long unixTime) { return time.format(unixTime); } /** * 转义为日期时间 yyyy-MM-dd HH:mm:ss * * @param unixTime 时间戳 * @return 日期时间字符串 */ public static String toDateTime(long unixTime) { return dateTime.format(unixTime); } /** * 转义为日期时间 yyyy-MM-dd HH:mm:ss * * @param date 时间对象 * @return 日期时间字符串 */ public static String toDateTime(Date date) { return dateTime.format(date); } /** * 本地时间对象转时间戳(本地时区) * * @param date 本地日期对象 * @return 时间戳 */ public static Long fromLocalDate(LocalDate date) { if (date == null) { return null; } return date.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); } /** * 本地时间对象转时间戳(本地时区) * * @param dateTime 本地日期对象 * @return 时间戳 */ public static Long fromLocalDateTime(LocalDateTime dateTime) { if (dateTime == null) { return null; } return dateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); } /** * 时间戳转本地日期(本地时区) * * @param unixTime 时间戳 * @return 本地日期对象 */ public static LocalDateTime toLocalDateTime(Long unixTime) { if (unixTime == null) { return null; } return Instant.ofEpochMilli(unixTime).atZone(ZoneId.systemDefault()).toLocalDateTime(); } /** * 将时间字符串解析为毫秒值 * *
支持的格式示例: *
* 10 = 10 * 10ms = 10 * 10s = 10,000 * 10m = 600,000 * 10h = 36,000,000 * 10d = 10D = 10 d = 864,000,000 * 10.5d = 907,200,000 ** * @param timeStr 时间字符串 * @return 毫秒 * @throws IllegalArgumentException 输入格式无效 */ public static long parseToMS(String timeStr) { if (TimiJava.isEmpty(timeStr)) { throw new IllegalArgumentException("not found timeStr"); } String normalized = timeStr.replaceAll("\\s+", "").toLowerCase(); Pattern pattern = Pattern.compile("^(\\d+(?:\\.\\d+)?)(ms|[dhms])?$"); Matcher matcher = pattern.matcher(normalized); if (!matcher.matches()) { throw new IllegalArgumentException("invalid format: " + timeStr); } double value = Double.parseDouble(matcher.group(1)); String unit = matcher.group(2); if (TimiJava.isEmpty(unit) || unit.equals("ms")) { return Math.round(value); } double multiplier = switch (unit) { case "s" -> Time.S; case "m" -> Time.M; case "h" -> Time.H; case "d" -> Time.D; default -> throw new IllegalArgumentException("invalid format unit: " + unit); }; return Math.round(value * multiplier); } /** * 媒体时间操作 * * @author 夜雨 * @version 2023-01-24 01:10 */ public static class Media { private static final Pattern PATTERN = Pattern.compile("(\\d*):?([0-5]\\d):([0-5]\\d)\\.?(\\d{1,3})?"); /** * 解析字符串为毫秒,匹配 999:59:59.999 格式,兼容 999:59:59 * * @param time 时间字符串 * @return 毫秒 */ public static long fromString(String time) { if (TimiJava.isEmpty(time)) { return 0; } Matcher matcher = PATTERN.matcher(time); if (matcher.find()) { long h = 0; if (TimiJava.isNotEmpty(matcher.group(1))) { h = Long.parseLong(matcher.group(1)); } long m = Long.parseLong(matcher.group(2)); long s = Long.parseLong(matcher.group(3)); long ms = 0; if (TimiJava.isNotEmpty(matcher.group(4))) { String gms = matcher.group(4); ms = Long.parseLong(gms); if (gms.length() == 2) { ms *= 10; } } return h * Time.H + m * Time.M + s * Time.S + ms; } return 0; } /** * 秒转媒体时间,00:00:00 * * @param second 秒 * @return 时间字符串 */ public static String toString(double second) { return toString((int) second); } /** * 秒转媒体时间,00:00:00 * * @param second 秒 * @return 时间字符串 */ public static String toString(int second) { int h = second / 60 / 60; if (0 < h) { return String.format("%d:%02d:%02d", h, second / 60 - h * 60, second % 60); } else { return String.format("%02d:%02d", second / 60, second % 60); } } /** * 毫秒转媒体时间,音视频播放时间,00:00:00.000 * * @param millis 毫秒 * @return 时间字符串 */ public static String toString(long millis) { long s = millis / 1000; long h = s / 60 / 60; return String.format("%d:%02d:%02d.%03d", h, s / 60 - h * 60, s % 60, millis % 1000); } } /** * 时差 * * @author 夜雨 * @version 2022-10-12 14:46 */ public static class Between { int year; int month; int day; int hour; int minute; int second; int millis; /** * 获取年数 * * @return 年数 */ public int getYear() { return year; } /** * 获取月数 * * @return 月数 */ public int getMonth() { return month; } /** * 获取天数 * * @return 天数 */ public int getDay() { return day; } /** * 获取小时 * * @return 小时 */ public int getHour() { return hour; } /** * 获取分钟 * * @return 分钟 */ public int getMinute() { return minute; } /** * 获取秒 * * @return 秒 */ public int getSecond() { return second; } /** * 获取毫秒 * * @return 毫秒 */ public int getMillis() { return millis; } } }