package cn.chnmuseum.party.common.util; import java.time.*; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAdjusters; import java.util.Date; import java.util.Locale; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * 日期工具类 - 基于LocalDateTime */ public class DateUtil { // 格式:年-月-日 小时:分钟:秒 public static final String FORMAT_ONE = "yyyy-MM-dd HH:mm:ss"; public static final String FORMAT_T = "yyyy-MM-dd'T'HH:mm:ss"; // 格式:年-月-日 小时:分钟 public static final String FORMAT_TWO = "yyyy-MM-dd HH:mm"; // 格式:年-月-日 public static final String LONG_DATE_FORMAT = "yyyy-MM-dd"; // 格式:月-日 public static final String SHORT_DATE_FORMAT = "MM-dd"; // 格式:小时:分钟:秒 public static final String LONG_TIME_FORMAT = "HH:mm:ss"; // 格式:小时:分钟:秒 public static final String SHORT_TIME_FORMAT = "HH:mm"; // 格式:年-月 public static final String MONTG_DATE_FORMAT = "yyyy-MM"; // 格式:年-月 public static final String Chinese_DATE_FORMAT = "yyyy年MM月dd日 HH:mm"; private static final ConcurrentMap<String, DateTimeFormatter> FORMATTER_CACHE = new ConcurrentHashMap<>(); private static final int PATTERN_CACHE_SIZE = 500; /** * Date转换为格式化时间 * * @param date date * @param pattern 格式 * @return */ public static String format(Date date, String pattern) { return format(LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()), pattern); } /** * localDateTime转换为格式化时间 * * @param localDateTime localDateTime * @param pattern 格式 * @return */ public static String format(LocalDateTime localDateTime, String pattern) { DateTimeFormatter formatter = createCacheFormatter(pattern); return localDateTime.format(formatter); } /** * localDateTime转换为格式化时间 * * @param localDateTime localDateTime * @return */ public static String format(LocalDateTime localDateTime) { DateTimeFormatter formatter = createCacheFormatter(FORMAT_ONE); return localDateTime.format(formatter); } /** * 格式化字符串转为Date * * @param time 格式化时间 * @param pattern 格式 * @return */ public static Date parseDate(String time, String pattern) { return Date.from(parseLocalDateTime(time, pattern).atZone(ZoneId.systemDefault()).toInstant()); } /** * 格式化字符串转为LocalDateTime * * @param time 格式化时间 * @param pattern 格式 * @return */ public static LocalDateTime parseLocalDateTime(String time, String pattern) { DateTimeFormatter formatter = createCacheFormatter(pattern); return LocalDateTime.parse(time, formatter); } /** * 格式化字符串转为LocalDateTime * * @param time 格式化时间 * @param pattern 格式 * @return localDateTime */ public static LocalDateTime transferLocalDateTime(String time, String pattern) { DateTimeFormatter formatter = createCacheFormatter(pattern); return LocalDate.parse(time, formatter).atStartOfDay(); } /** * java.util.Date --> java.time.LocalDateTime */ public static LocalDateTime UDateToLocalDateTime(Date date) { Instant instant = date.toInstant(); ZoneId zone = ZoneId.systemDefault(); return LocalDateTime.ofInstant(instant, zone); } /** * 将LocalDateTime转为自定义的时间格式的字符串 * * @param localDateTime * @param format * @return */ public static String getDateTimeAsString(LocalDateTime localDateTime, String format) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format); return localDateTime.format(formatter); } /** * 将long类型的timestamp转为LocalDateTime * * @param timestamp * @return */ public static LocalDateTime getDateTimeOfTimestamp(long timestamp) { Instant instant = Instant.ofEpochMilli(timestamp); ZoneId zone = ZoneId.systemDefault(); return LocalDateTime.ofInstant(instant, zone); } /** * 将LocalDateTime转为long类型的timestamp * * @param localDateTime * @return */ public static long getTimestampOfDateTime(LocalDateTime localDateTime) { ZoneId zone = ZoneId.systemDefault(); Instant instant = localDateTime.atZone(zone).toInstant(); return instant.toEpochMilli(); } /** * 将某时间字符串转为自定义时间格式的LocalDateTime * * @param time * @param format * @return */ public static LocalDateTime parseStringToDateTime(String time, String format) { DateTimeFormatter df = DateTimeFormatter.ofPattern(format, Locale.getDefault()); return LocalDateTime.parse(time, df); } /** * 计算两个日期之间相差的时间 * * @param startDate 较小的时间 * @param endDate 较大的时间 * @return 相差结果 X天X小时X分钟X秒 */ public static String differenceTimeStr(Date startDate, Date endDate) { // 计算时间差 long between = endDate.toInstant().toEpochMilli() - startDate.toInstant().toEpochMilli(); if (between < 0) { return "-1"; } long day = between / (1000 * 3600 * 24); // 天 long hour = (between / (60 * 60 * 1000) - day * 24); // 小时 long min = ((between / (60 * 1000)) - day * 24 * 60 - hour * 60); // 分钟 long sec = (between / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60); // 秒 StringBuilder sb = new StringBuilder(); if (0 != day) { sb.append(day); sb.append("天"); } if (0 != hour) { sb.append(hour); sb.append("小时"); } if (0 != min) { sb.append(min); sb.append("分"); } sb.append(sec); sb.append("秒"); return String.valueOf(sb); } /** * 时间戳转时间【毫秒】 * * @param timeStamp 时间戳【毫秒】 * @param pattern 格式化参数 * @return 格式化后的时间 */ public static String msTimeStampConvertTime(long timeStamp, String pattern) { Instant instant = Instant.ofEpochMilli(timeStamp); ZoneId zone = ZoneId.systemDefault(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); return LocalDateTime.ofInstant(instant, zone).format(formatter); } /** * 时间戳转时间【秒】 * * @param timeStamp 时间戳【秒】 * @param pattern 格式化参数 * @return 格式化后的时间 */ public static String secondsTimeStampConvertTime(long timeStamp, String pattern) { Instant instant = Instant.ofEpochSecond(timeStamp); ZoneId zone = ZoneId.systemDefault(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern); return LocalDateTime.ofInstant(instant, zone).format(formatter); } /** * 将某时间字符串转为自定义时间格式的LocalDate * * @param time * @param format * @return */ public static LocalDate parseStringToDate(String time, String format) { DateTimeFormatter df = DateTimeFormatter.ofPattern(format, Locale.getDefault()); return LocalDate.parse(time, df); } /** * 将某时间字符串转为自定义时间格式的LocalDate * * @param time * @param format * @return */ public static LocalTime parseStringToTime(String time, String format) { DateTimeFormatter df = DateTimeFormatter.ofPattern(format, Locale.getDefault()); return LocalTime.parse(time, df); } /** * 在缓存中创建DateTimeFormatter * * @param pattern 格式 * @return */ private static DateTimeFormatter createCacheFormatter(String pattern) { if (pattern == null || pattern.length() == 0) { throw new IllegalArgumentException("Invalid pattern specification"); } DateTimeFormatter formatter = FORMATTER_CACHE.get(pattern); if (formatter == null) { if (FORMATTER_CACHE.size() < PATTERN_CACHE_SIZE) { formatter = DateTimeFormatter.ofPattern(pattern); DateTimeFormatter oldFormatter = FORMATTER_CACHE.putIfAbsent(pattern, formatter); if (oldFormatter != null) { formatter = oldFormatter; } } } return formatter; } /** * 获取某个时间段的开始时间 * * @param offset 0今天,1明天,-1昨天,依次类推 * @return */ public static LocalDateTime minuteStart(int offset) { return LocalDateTime.now().plusMinutes(offset).withSecond(0).withNano(0); } /** * 获取某个时间段的开始时间 * * @param offset 0今天,1明天,-1昨天,依次类推 * @return */ public static LocalDateTime minuteEnd(int offset) { return LocalDateTime.now().plusMinutes(offset).withSecond(59).withNano(999999999); } /** * 获取某个时间段的开始时间 * * @param offset 0今天,1明天,-1昨天,依次类推 * @return */ public static LocalDateTime hourStart(int offset) { return LocalDateTime.now().plusHours(offset).withMinute(0).withSecond(0).withNano(0); } /** * 获取某个时间段的结束时间 * * @param offset 0今天,1明天,-1昨天,依次类推 * @return */ public static LocalDateTime hourEnd(int offset) { return LocalDateTime.now().plusHours(offset).withMinute(59) .withSecond(59) .withNano(999999999); } /** * 获取某天的开始日期 * * @param offset 0今天,1明天,-1昨天,依次类推 * @return */ public static LocalDateTime dayStart(int offset) { return LocalDate.now().plusDays(offset).atStartOfDay(); } /** * 获取日期的结束时间 */ public static LocalDateTime getDayStart(int offset) { return LocalDateTime.now().plusDays(offset).withHour(0) .withMinute(0) .withSecond(0) .withNano(0); } /** * 获取某天的开始日期 * * @param offset 0今天,1明天,-1昨天,依次类推 * @return */ public static LocalDateTime dayEnd(int offset) { return LocalDateTime.of(LocalDate.now().plusDays(offset), LocalTime.MAX);//当天零点 } /** * 获取日期的结束时间 */ public static LocalDateTime getDayEnd(int offset) { return LocalDateTime.now().plusDays(offset).withHour(23) .withMinute(59) .withSecond(59) .withNano(999999999); } /** * 获取此刻与相对当天第day天的起始时间相隔的秒数。day为0表示今天的起始时间;1明天,2后天,-1昨天,-2前天等,依次例推。 * * @param day * @return */ public static int ttl(int day) { LocalDateTime now = LocalDateTime.now(); LocalDateTime time = LocalDate.now().plusDays(day).atStartOfDay(); return (int) Duration.between(now, time).toMillis() / 1000; } /** * 获取某周的开始日期 * * @param offset 0本周,1下周,-1上周,依次类推 * @return */ public static LocalDateTime weekStart(int offset) { return LocalDateTime.now().plusWeeks(offset).with(DayOfWeek.MONDAY); } /** * 获取某周的开始日期 * * @param offset 0本周,1下周,-1上周,依次类推 * @return */ public static LocalDateTime weekEnd(int offset) { return LocalDateTime.now().plusWeeks(offset).with(DayOfWeek.SUNDAY); } /** * 获取某月的开始日期 * * @param offset 0本月,1下个月,-1上个月,依次类推 * @return */ public static LocalDateTime monthStart(int offset) { return LocalDateTime.now().plusMonths(offset).with(TemporalAdjusters.firstDayOfMonth()).withHour(0).withMinute(0).withSecond(0); } /** * 获取某月的结束日期 * * @param offset 0本月,1下个月,-1上个月,依次类推 * @return */ public static LocalDateTime monthEnd(int offset) { return LocalDateTime.now().plusMonths(offset).with(TemporalAdjusters.lastDayOfMonth()).withHour(23).withMinute(59).withSecond(59).withNano(999999999); } /** * 获取某季度的开始日期 * 季度一年四季, 第一季度:2月-4月, 第二季度:5月-7月, 第三季度:8月-10月, 第四季度:11月-1月 * * @param offset 0本季度,1下个季度,-1上个季度,依次类推 * @return */ public static LocalDate quarterStart(int offset) { final LocalDate date = LocalDate.now().plusMonths(offset * 3); int month = date.getMonth().getValue();//当月 int start = 0; if (month >= 2 && month <= 4) {//第一季度 start = 2; } else if (month >= 5 && month <= 7) {//第二季度 start = 5; } else if (month >= 8 && month <= 10) {//第三季度 start = 8; } else if (month >= 11) {//第四季度 start = 11; } else {//第四季度 start = 11; month = 13; } return date.plusMonths(start - month).with(TemporalAdjusters.firstDayOfMonth()); } /** * 获取某年的开始日期 * * @param offset 0今年,1明年,-1去年,依次类推 * @return */ public static LocalDateTime yearStart(int offset) { return LocalDateTime.now().plusYears(offset).with(TemporalAdjusters.firstDayOfYear()); } /** * 获取某年的结束日期 * * @param offset 0今年,1明年,-1去年,依次类推 * @return */ public static LocalDateTime yearEnd(int offset) { return LocalDateTime.now().plusYears(offset).with(TemporalAdjusters.lastDayOfYear()); } /** * 计算两个时间相差天数 * * @param day1 时间1 * @param day2 时间2 * @return 相差天数 */ public static long intervalDay(LocalDateTime day1, LocalDateTime day2) { return Duration.between(day1, day2).toDays(); } /** * 计算两个时间相差天数 * * @param day1 格式化的时间1 * @param day2 格式化的时间2 * @param format 格式化参数 * @return 相差天数 */ public static long intervalDay(String day1, String day2, String format) { return intervalDay(transferLocalDateTime(day1, format), transferLocalDateTime(day2, format)); } /** * 获取当前日期 * * @param format 格式化参数 * @return 格式化后的日期 */ public static String getCurrentDate(String format) { return LocalDateTime.now().format(DateTimeFormatter.ofPattern(format)); } }