日期时间工具类

示例代码:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import static java.time.temporal.ChronoUnit.WEEKS;

/**
 * 日期时间工具类
 */
public final class DateTimeUtil {

    private DateTimeUtil() {
    }

    private static final Logger logger = LoggerFactory.getLogger(DateTimeUtil.class);

    /**
     * 显示年月日时分秒,例如 2015-08-11 09:51:53.
     */
    public static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

    /**
     * 显示年月日时分秒(无符号),例如 20150811095153.
     */
    public static final String UNSIGNED_DATETIME_PATTERN = "yyyyMMddHHmmss";

    /**
     * 仅显示年月日,例如 2015-08-11.
     */
    public static final String DATE_PATTERN = "yyyy-MM-dd";

    /**
     * 仅显示年月日(无符号),例如 20150811.
     */
    public static final String UNSIGNED_DATE_PATTERN = "yyyyMMdd";

    /**
     * 仅显示年月,例如 2015-08.
     */
    public static final String MONTH_PATTERN = "yyyy-MM";

    /**
     * 仅显示年月(无符号),例如 201508.
     */
    public static final String UNSIGNED_MONTH_PATTERN = "yyyyMM";

    /**
     * 仅显示时分秒,例如 09:51:53.
     */
    public static final String TIME_PATTERN = "HH:mm:ss";

    /**
     * 一天的开始时间, 主要用于拼接日期时间
     */
    public static final String DAY_START_TIME_STR = " 00:00:00";

    /**
     * 一天的结束时间, 主要用于拼接日期时间
     */
    public static final String DAY_END_TIME_STR = " 23:59:59";

    /**
     * 春天;
     */
    public static final Integer SPRING = 1;

    /**
     * 夏天;
     */
    public static final Integer SUMMER = 2;

    /**
     * 秋天;
     */
    public static final Integer AUTUMN = 3;

    /**
     * 冬天;
     */
    public static final Integer WINTER = 4;

    /**
     * 星期日;
     */
    public static final String SUNDAY = "星期日";

    /**
     * 星期一;
     */
    public static final String MONDAY = "星期一";

    /**
     * 星期二;
     */
    public static final String TUESDAY = "星期二";

    /**
     * 星期三;
     */
    public static final String WEDNESDAY = "星期三";

    /**
     * 星期四;
     */
    public static final String THURSDAY = "星期四";

    /**
     * 星期五;
     */
    public static final String FRIDAY = "星期五";

    /**
     * 星期六;
     */
    public static final String SATURDAY = "星期六";

    /**
     * 年
     */
    public static final String YEAR = "year";

    /**
     * 月
     */
    public static final String MONTH = "month";

    /**
     * 周
     */
    public static final String WEEK = "week";

    /**
     * 日
     */
    public static final String DAY = "day";

    /**
     * 时
     */
    public static final String HOUR = "hour";

    /**
     * 分
     */
    public static final String MINUTE = "minute";

    /**
     * 秒
     */
    public static final String SECOND = "second";

    public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(DATETIME_PATTERN);

    public static final DateTimeFormatter UNSIGNED_DATETIME_FORMATTER = DateTimeFormatter.ofPattern(UNSIGNED_DATETIME_PATTERN);

    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(DATE_PATTERN);

    public static final DateTimeFormatter UNSIGNED_DATE_FORMATTER = DateTimeFormatter.ofPattern(UNSIGNED_DATE_PATTERN);

    public static final DateTimeFormatter MONTH_FORMATTER = DateTimeFormatter.ofPattern(MONTH_PATTERN);

    public static final DateTimeFormatter UNSIGNED_MONTH_FORMATTER = DateTimeFormatter.ofPattern(UNSIGNED_MONTH_PATTERN);

    public static final DateTimeFormatter TIME_PATTERN_FORMATTER = DateTimeFormatter.ofPattern(TIME_PATTERN);

    private static Map<String, ThreadLocal<SimpleDateFormat>> localSimpleDateFormatMap = new ConcurrentHashMap<>();

    static {
        localSimpleDateFormatMap.put(DATETIME_PATTERN, ThreadLocal.withInitial(() -> new SimpleDateFormat(DATETIME_PATTERN)));
        localSimpleDateFormatMap.put(UNSIGNED_DATETIME_PATTERN, ThreadLocal.withInitial(() -> new SimpleDateFormat(UNSIGNED_DATETIME_PATTERN)));
        localSimpleDateFormatMap.put(DATE_PATTERN, ThreadLocal.withInitial(() -> new SimpleDateFormat(DATE_PATTERN)));
        localSimpleDateFormatMap.put(UNSIGNED_DATE_PATTERN, ThreadLocal.withInitial(() -> new SimpleDateFormat(UNSIGNED_DATE_PATTERN)));
        localSimpleDateFormatMap.put(MONTH_PATTERN, ThreadLocal.withInitial(() -> new SimpleDateFormat(MONTH_PATTERN)));
        localSimpleDateFormatMap.put(UNSIGNED_MONTH_PATTERN, ThreadLocal.withInitial(() -> new SimpleDateFormat(UNSIGNED_MONTH_PATTERN)));
    }

    /**
     * 获取本地变量ThreadLocal
     *
     * @param pattern 时间格式
     * @return
     */
    public static ThreadLocal<SimpleDateFormat> getLocalSimpleDateFormat(String pattern) {
        return localSimpleDateFormatMap.get(pattern);
    }

    /**
     * 获取当前日期和时间字符串.
     *
     * @return String 日期时间字符串,例如 2015-08-11 09:51:53
     */
    public static String getLocalDateTimeStr() {
        return format(LocalDateTime.now(), DATETIME_PATTERN);
    }

    /**
     * 获取当前日期字符串.
     *
     * @return String 日期字符串,例如2015-08-11
     */
    public static String getLocalDateStr() {
        return format(LocalDate.now(), DATE_PATTERN);
    }

    /**
     * 获取当前时间字符串.
     *
     * @return String 时间字符串,例如 09:51:53
     */
    public static String getLocalTimeStr() {
        return format(LocalTime.now(), TIME_PATTERN);
    }

    /**
     * 获取当前星期字符串.
     *
     * @return String 当前星期字符串,例如 星期二
     */
    public static String getDayOfWeekStr() {
        return format(LocalDate.now(), "E");
    }

    /**
     * 获取指定日期是星期几
     *
     * @param localDate 日期
     * @return String 星期几
     */
    public static String getDayOfWeekStr(LocalDate localDate) {
        String[] weekOfDays = {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY};
        int dayOfWeek = localDate.getDayOfWeek().getValue() - 1;
        return weekOfDays[dayOfWeek];
    }

    /**
     * 获取日期时间字符串
     *
     * @param temporal 需要转化的日期时间
     * @param pattern  时间格式
     * @return String 日期时间字符串,例如 2015-08-11 09:51:53
     */
    public static String format(TemporalAccessor temporal, String pattern) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
        return dateTimeFormatter.format(temporal);
    }

    /**
     * 获取日期时间字符串
     *
     * @param date    需要转化的日期时间
     * @param pattern 时间格式
     * @return String 日期时间字符串,例如 2015-08-11 09:51:53
     */
    public static String format(Date date, String pattern) {
        ThreadLocal<SimpleDateFormat> formatThreadLocal = getLocalSimpleDateFormat(pattern);
        String dateStr = formatThreadLocal.get().format(date);
        formatThreadLocal.remove();
        return dateStr;
    }

    /**
     * 日期时间字符串转换为日期时间(java.time.LocalDateTime)
     *
     * @param localDateTimeStr 日期时间字符串
     * @param pattern          日期时间格式 例如DATETIME_PATTERN
     * @return LocalDateTime 日期时间
     */
    public static LocalDateTime parseLocalDateTime(String localDateTimeStr, String pattern) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
        return LocalDateTime.parse(localDateTimeStr, dateTimeFormatter);
    }

    /**
     * 日期字符串转换为日期(java.time.LocalDate)
     *
     * @param localDateStr 日期字符串
     * @param pattern      日期格式 例如DATE_PATTERN
     * @return LocalDate 日期
     */
    public static LocalDate parseLocalDate(String localDateStr, String pattern) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
        return LocalDate.parse(localDateStr, dateTimeFormatter);
    }

    /**
     * 日期时间字符串转换为日期时间
     *
     * @param dateTimeStr 日期时间字符串
     * @param pattern     日期时间格式 例如DATETIME_PATTERN
     * @return LocalDateTime 日期时间
     */
    public static Date parseDate(String dateTimeStr, String pattern) {
        ThreadLocal<SimpleDateFormat> formatThreadLocal = getLocalSimpleDateFormat(pattern);
        Date date = null;
        try {
            date = formatThreadLocal.get().parse(dateTimeStr);
        } catch (ParseException e) {
            logger.error("DateTimeUtil.parseDate occur exception:{}", e.getMessage(), e);
        }
        formatThreadLocal.remove();
        return date;
    }

    /**
     * 获取指定日期时间加上指定数量日期时间单位之后的日期时间.
     *
     * @param localDateTime 日期时间
     * @param num           数量
     * @param chronoUnit    日期时间单位
     * @return LocalDateTime 新的日期时间
     */
    public static LocalDateTime plus(LocalDateTime localDateTime, int num, ChronoUnit chronoUnit) {
        return localDateTime.plus(num, chronoUnit);
    }

    /**
     * 获取指定日期时间减去指定数量日期时间单位之后的日期时间.
     *
     * @param localDateTime 日期时间
     * @param num           数量
     * @param chronoUnit    日期时间单位
     * @return LocalDateTime 新的日期时间
     */
    public static LocalDateTime minus(LocalDateTime localDateTime, int num, ChronoUnit chronoUnit) {
        return localDateTime.minus(num, chronoUnit);
    }

    /**
     * 根据ChronoUnit计算两个日期时间之间相隔日期时间
     *
     * @param start      开始日期时间
     * @param end        结束日期时间
     * @param chronoUnit 日期时间单位
     * @return long 相隔日期时间
     */
    public static long getChronoUnitBetween(LocalDateTime start, LocalDateTime end, ChronoUnit chronoUnit) {
        return Math.abs(start.until(end, chronoUnit));
    }

    /**
     * 根据ChronoUnit计算两个日期之间相隔年数或月数或天数
     *
     * @param start      开始日期
     * @param end        结束日期
     * @param chronoUnit 日期时间单位,(ChronoUnit.YEARS,ChronoUnit.MONTHS,ChronoUnit.WEEKS,ChronoUnit.DAYS)
     * @return long 相隔年数或月数或天数
     */
    public static long getChronoUnitBetween(LocalDate start, LocalDate end, ChronoUnit chronoUnit) {
        return Math.abs(start.until(end, chronoUnit));
    }

    /**
     * 获取本年第一天的日期字符串
     *
     * @return String 格式:yyyy-MM-dd 00:00:00
     */
    public static String getFirstDayOfYearStr() {
        return getFirstDayOfYearStr(LocalDateTime.now());
    }

    /**
     * 获取本年最后一天的日期字符串
     *
     * @return String 格式:yyyy-MM-dd 23:59:59
     */
    public static String getLastDayOfYearStr() {
        return getLastDayOfYearStr(LocalDateTime.now());
    }

    /**
     * 获取指定日期当年第一天的日期字符串
     *
     * @param localDateTime 指定日期时间
     * @return String 格式:yyyy-MM-dd 00:00:00
     */
    public static String getFirstDayOfYearStr(LocalDateTime localDateTime) {
        return getFirstDayOfYearStr(localDateTime, DATETIME_PATTERN);
    }

    /**
     * 获取指定日期当年最后一天的日期字符串
     *
     * @param localDateTime 指定日期时间
     * @return String 格式:yyyy-MM-dd 23:59:59
     */
    public static String getLastDayOfYearStr(LocalDateTime localDateTime) {
        return getLastDayOfYearStr(localDateTime, DATETIME_PATTERN);
    }

    /**
     * 获取指定日期当年第一天的日期字符串,带日期格式化参数
     *
     * @param localDateTime 指定日期时间
     * @param pattern       日期时间格式
     * @return String 格式:yyyy-MM-dd 00:00:00
     */
    public static String getFirstDayOfYearStr(LocalDateTime localDateTime, String pattern) {
        return format(localDateTime.withDayOfYear(1).withHour(0).withMinute(0).withSecond(0), pattern);
    }

    /**
     * 获取指定日期当年最后一天的日期字符串,带日期格式化参数
     *
     * @param localDateTime 指定日期时间
     * @param pattern       日期时间格式
     * @return String 格式:yyyy-MM-dd 23:59:59
     */
    public static String getLastDayOfYearStr(LocalDateTime localDateTime, String pattern) {
        return format(localDateTime.with(TemporalAdjusters.lastDayOfYear()).withHour(23).withMinute(59).withSecond(59), pattern);
    }

    /**
     * 获取本月第一天的日期字符串
     *
     * @return String 格式:yyyy-MM-dd 00:00:00
     */
    public static String getFirstDayOfMonthStr() {
        return getFirstDayOfMonthStr(LocalDateTime.now());
    }

    /**
     * 获取本月最后一天的日期字符串
     *
     * @return String 格式:yyyy-MM-dd 23:59:59
     */
    public static String getLastDayOfMonthStr() {
        return getLastDayOfMonthStr(LocalDateTime.now());
    }

    /**
     * 获取指定日期当月第一天的日期字符串
     *
     * @param localDateTime 指定日期时间
     * @return String 格式:yyyy-MM-dd 23:59:59
     */
    public static String getFirstDayOfMonthStr(LocalDateTime localDateTime) {
        return getFirstDayOfMonthStr(localDateTime, DATETIME_PATTERN);
    }

    /**
     * 获取指定日期当月最后一天的日期字符串
     *
     * @param localDateTime 指定日期时间
     * @return String 格式:yyyy-MM-dd 23:59:59
     */
    public static String getLastDayOfMonthStr(LocalDateTime localDateTime) {
        return getLastDayOfMonthStr(localDateTime, DATETIME_PATTERN);
    }

    /**
     * 获取指定日期当月第一天的日期字符串,带日期格式化参数
     *
     * @param localDateTime 指定日期时间
     * @return String 格式:yyyy-MM-dd 00:00:00
     */
    public static String getFirstDayOfMonthStr(LocalDateTime localDateTime, String pattern) {
        return format(localDateTime.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0), pattern);
    }

    /**
     * 获取指定日期当月最后一天的日期字符串,带日期格式化参数
     *
     * @param localDateTime 指定日期时间
     * @param pattern       日期时间格式
     * @return String 格式:yyyy-MM-dd 23:59:59
     */
    public static String getLastDayOfMonthStr(LocalDateTime localDateTime, String pattern) {
        return format(localDateTime.with(TemporalAdjusters.lastDayOfMonth()).withHour(23).withMinute(59).withSecond(59), pattern);
    }

    /**
     * 获取本周第一天的日期字符串
     *
     * @return String 格式:yyyy-MM-dd 00:00:00
     */
    public static String getFirstDayOfWeekStr() {
        return getFirstDayOfWeekStr(LocalDateTime.now());
    }

    /**
     * 获取本周最后一天的日期字符串
     *
     * @return String 格式:yyyy-MM-dd 23:59:59
     */
    public static String getLastDayOfWeekStr() {
        return getLastDayOfWeekStr(LocalDateTime.now());
    }

    /**
     * 获取指定日期当周第一天的日期字符串,这里第一天为周一
     *
     * @param localDateTime 指定日期时间
     * @return String 格式:yyyy-MM-dd 00:00:00
     */
    public static String getFirstDayOfWeekStr(LocalDateTime localDateTime) {
        return getFirstDayOfWeekStr(localDateTime, DATETIME_PATTERN);
    }

    /**
     * 获取指定日期当周最后一天的日期字符串,这里最后一天为周日
     *
     * @param localDateTime 指定日期时间
     * @return String 格式:yyyy-MM-dd 23:59:59
     */
    public static String getLastDayOfWeekStr(LocalDateTime localDateTime) {
        return getLastDayOfWeekStr(localDateTime, DATETIME_PATTERN);
    }

    /**
     * 获取指定日期当周第一天的日期字符串,这里第一天为周一,带日期格式化参数
     *
     * @param localDateTime 指定日期时间
     * @param pattern       日期时间格式
     * @return String 格式:yyyy-MM-dd 00:00:00
     */
    public static String getFirstDayOfWeekStr(LocalDateTime localDateTime, String pattern) {
        return format(localDateTime.with(DayOfWeek.MONDAY).withHour(0).withMinute(0).withSecond(0), pattern);
    }

    /**
     * 获取指定日期当周最后一天的日期字符串,这里最后一天为周日,带日期格式化参数
     *
     * @param localDateTime 指定日期时间
     * @param pattern       日期时间格式
     * @return String 格式:yyyy-MM-dd 23:59:59
     */
    public static String getLastDayOfWeekStr(LocalDateTime localDateTime, String pattern) {
        return format(localDateTime.with(DayOfWeek.SUNDAY).withHour(23).withMinute(59).withSecond(59), pattern);
    }

    /**
     * 获取今天开始时间的日期字符串
     *
     * @return String 格式:yyyy-MM-dd 00:00:00
     */
    public static String getStartTimeOfDayStr() {
        return getStartTimeOfDayStr(LocalDateTime.now());
    }

    /**
     * 获取今天结束时间的日期字符串
     *
     * @return String 格式:yyyy-MM-dd 23:59:59
     */
    public static String getEndTimeOfDayStr() {
        return getEndTimeOfDayStr(LocalDateTime.now());
    }

    /**
     * 获取指定日期开始时间的日期字符串
     *
     * @param localDateTime 指定日期时间
     * @return String 格式:yyyy-MM-dd 00:00:00
     */
    public static String getStartTimeOfDayStr(LocalDateTime localDateTime) {
        return getStartTimeOfDayStr(localDateTime, DATETIME_PATTERN);
    }

    /**
     * 获取指定日期结束时间的日期字符串
     *
     * @param localDateTime 指定日期时间
     * @return String 格式:yyyy-MM-dd 23:59:59
     */
    public static String getEndTimeOfDayStr(LocalDateTime localDateTime) {
        return getEndTimeOfDayStr(localDateTime, DATETIME_PATTERN);
    }

    /**
     * 获取指定日期开始时间的日期字符串,带日期格式化参数
     *
     * @param localDateTime 指定日期时间
     * @param pattern       日期时间格式
     * @return String 格式:yyyy-MM-dd HH:mm:ss
     */
    public static String getStartTimeOfDayStr(LocalDateTime localDateTime, String pattern) {
        return format(localDateTime.withHour(0).withMinute(0).withSecond(0), pattern);
    }

    /**
     * 获取指定日期结束时间的日期字符串,带日期格式化参数
     *
     * @param localDateTime 指定日期时间
     * @param pattern       日期时间格式
     * @return String 格式:yyyy-MM-dd 23:59:59
     */
    public static String getEndTimeOfDayStr(LocalDateTime localDateTime, String pattern) {
        return format(localDateTime.withHour(23).withMinute(59).withSecond(59), pattern);
    }

    /**
     * LocalDate 转 Date
     *
     * @param localDate
     * @return
     */
    public static Date asDate(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * LocalDateTime 转 Date
     *
     * @param localDateTime
     * @return
     */
    public static Date asDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * Date 转 LocalDate
     *
     * @param date
     * @return
     */
    public static LocalDate asLocalDate(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDate();
    }

    /**
     * Date 转LocalDateTime
     *
     * @param date
     * @return
     */
    public static LocalDateTime asLocalDateTime(Date date) {
        return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * Timestamp转LocalDateTime(mysql中datetime数据取出时是timestamp类型)
     *
     * @param timestamp
     * @return
     */
    public static LocalDateTime asLocalDateTime(Timestamp timestamp) {
        return LocalDateTime.ofInstant(timestamp.toInstant(), ZoneId.systemDefault());
    }

    /**
     * LocalDateTime转Timestamp
     *
     * @param localDateTime
     * @return
     */
    public static Timestamp asTimestamp(LocalDateTime localDateTime) {
        return Timestamp.valueOf(localDateTime);
    }

    /**
     * LocalDate转LocalDateTime
     *
     * @param localDate
     * @return
     */
    public static LocalDateTime asLocalDateTime(LocalDate localDate) {
        return localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * LocalDateTime转LocalDate
     *
     * @param localDateTime
     * @return
     */
    public static LocalDate asLocalDate(LocalDateTime localDateTime) {
        return localDateTime.toLocalDate();
    }


    /**
     * 获取最近的几天
     *
     * @param day       yyyy-MM-dd 为空则去当前
     * @param number    数量
     * @param format    格式,默认是yyyy-MM-dd,支持yyyy-MM-dd和yyyyMMdd
     * @param inclusion 是否包含当天
     * @return
     */
    public static List<String> getLastDayMonths(String day, Integer number, String format, boolean inclusion) {
        List<String> dateList = new ArrayList();
        LocalDate endDate = LocalDate.now();
        if (day != null && !"".equals(day)) {
            endDate = LocalDate.parse(day, DATE_FORMATTER);
        }
        if (UNSIGNED_DATE_PATTERN.equals(format)) {
            for (int i = number - 1; i >= 0; i--) {
                dateList.add(UNSIGNED_DATE_FORMATTER.format(endDate.minusDays(i)));
            }
        } else {
            for (int i = number - 1; i >= 0; i--) {
                dateList.add(DATE_FORMATTER.format(endDate.minusDays(i)));
            }
        }
        if (!inclusion) {
            dateList = dateList.subList(0, dateList.size() - 1);
        }
        return dateList;
    }

    /**
     * 获取最近的几个月
     *
     * @param yearMonthStr yyyy-MM 为空则取当前月
     * @param number       数量
     * @param format       格式, 为空则为 yyyy-MM,支持yyyy-MM和yyyyMM
     * @param inclusion    是否包含当月
     * @return yyyyMM
     */
    public static List<String> getLastYearMonths(String yearMonthStr, Integer number, String format, boolean inclusion) {
        List<String> monthList = new ArrayList();
        YearMonth yearMonth = YearMonth.now();
        if (yearMonthStr != null && !"".equals(yearMonthStr)) {
            yearMonth = YearMonth.parse(yearMonthStr, MONTH_FORMATTER);
        }
        if (UNSIGNED_MONTH_PATTERN.equals(format)) {
            for (int i = number - 1; i >= 0; i--) {
                monthList.add(UNSIGNED_MONTH_FORMATTER.format(yearMonth.minusMonths(i)));
            }
        } else {
            for (int i = number - 1; i >= 0; i--) {
                monthList.add(MONTH_FORMATTER.format(yearMonth.minusMonths(i)));
            }
        }
        if (!inclusion) {
            monthList = monthList.subList(0, monthList.size() - 1);
        }
        return monthList;
    }

    /**
     * 获取两个日期之间的所有日期 (yyyy-MM-dd)
     *
     * @param startTime, 如2022-02-26
     * @param endTime,   如2022-03-09
     * @return
     */
    public static List<String> getBetweenDate(String startTime, String endTime) {
        // 声明保存日期集合
        List<String> list = new ArrayList();
        LocalDate start = LocalDate.parse(startTime, DATE_FORMATTER);
        LocalDate end = LocalDate.parse(endTime, DATE_FORMATTER);
        while (start.isBefore(end) || start.isEqual(end)) {
            list.add(start.toString());
            start = start.plusDays(1);
        }
        return list;
    }


    /**
     * 获取两月之间的所有月份(yyyy-MM)
     *
     * @param minDate yyyy-MM-dd
     * @param maxDate yyyy-MM-dd
     * @return
     */
    public static List<String> getMonthBetween(String minDate, String maxDate) {
        ArrayList<String> result = new ArrayList<String>();
        SimpleDateFormat sdf = new SimpleDateFormat(MONTH_PATTERN);//格式化为年月

        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();

        try {
            min.setTime(sdf.parse(minDate));
            min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

            max.setTime(sdf.parse(maxDate));
            max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);
        } catch (Exception e) {
            logger.error("getMonthBetween occur exception:{}", e.getMessage(), e);
        }

        Calendar curr = min;
        while (curr.before(max)) {
            result.add(sdf.format(curr.getTime()));
            curr.add(Calendar.MONTH, 1);
        }
        return result;
    }

    /**
     * 将某个日期的指定时间段按day/1小时/2小时的等划分
     *
     * @param day       yyyy-MM-dd
     * @param startTime 00:00
     * @param endTime   08:00
     * @param type      目前支持one_hour、two_hour, 可以自改造
     * @return key:00:00-08:00 value: 2022-07-22 00:00:00,2022-07-22 01:59:59
     */
    public static Map<String, Object> getTimeIntervalByDay(String day, String startTime, String endTime, String type) {
        String startDateTime = day + " " + startTime + ":00";
        String endDateTime = day + " " + endTime + ":00";
        LocalDateTime start = LocalDateTime.parse(startDateTime, DATETIME_FORMATTER);
        LocalDateTime end = LocalDateTime.parse(endDateTime, DATETIME_FORMATTER);
        Map<String, Object> timeIntervalMap = new LinkedHashMap();
        int plusSecond;
        int checkSecondPoint;
        switch (type) {
            case "one_hour":
                plusSecond = 60 * 60;
                checkSecondPoint = 60 * 60;
                break;
            case "two_hour":
                plusSecond = 2 * 60 * 60;
                checkSecondPoint = 2 * 60 * 60;
                break;
            default:
                plusSecond = 24 * 60 * 60;
                checkSecondPoint = 24 * 60 * 60;
        }
        LocalDateTime tempEndDateTime = null;
        while (start.isBefore(end)) {
            String dateTimeValueStart = DATETIME_FORMATTER.format(start);
            String timeKeyStart = dateTimeValueStart.substring(11, 16);
            //判断是否满足条件
            if (ChronoUnit.SECONDS.between(start, end) <= checkSecondPoint) {
                tempEndDateTime = end;
            } else {
                tempEndDateTime = start.plusSeconds(plusSecond);
            }
            String timeKeyEnd = DATETIME_FORMATTER.format(tempEndDateTime).substring(11, 16);
            if (ChronoUnit.SECONDS.between(tempEndDateTime, end) == 0) { //临界值
                if ("00:00".equals(timeKeyEnd)) {
                    timeKeyEnd = "24:00";
                }
            }
            String dateTimeValueEnd = DATETIME_FORMATTER.format(tempEndDateTime.minusSeconds(1));
            timeIntervalMap.put(timeKeyStart + "-" + timeKeyEnd, dateTimeValueStart + "," + dateTimeValueEnd);
            start = tempEndDateTime;
        }

        return timeIntervalMap;
    }

    /**
     * 获取两个时间段的时间段值
     *
     * @param startTime 开始时间戳
     * @param endTime   结束时间戳
     * @param timeType  时间类型, YEAR、MONTH、DAY
     * @return
     */
    public static List<String> getTimePeriodFromTwoTime(Long startTime, Long endTime, String timeType) {
        LocalDate start = Instant.ofEpochMilli(startTime).atZone(ZoneOffset.ofHours(8)).toLocalDate();
        LocalDate end = Instant.ofEpochMilli(endTime).atZone(ZoneOffset.ofHours(8)).toLocalDate();

        List<String> result = new ArrayList<>();

        // 年
        if ("YEAR".equals(timeType)) {
            Year startYear = Year.from(start);
            Year endYear = Year.from(end);
            // 包含最后一个时间
            for (long i = 0; i <= ChronoUnit.YEARS.between(startYear, endYear); i++) {
                result.add(startYear.plusYears(i).toString());
            }
        }
        // 月
        else if ("MONTH".equals(timeType)) {
            YearMonth from = YearMonth.from(start);
            YearMonth to = YearMonth.from(end);
            for (long i = 0; i <= ChronoUnit.MONTHS.between(from, to); i++) {
                result.add(from.plusMonths(i).toString());
            }
        }
        // 日
        else {
            for (long i = 0; i <= ChronoUnit.DAYS.between(start, end); i++) {
                result.add(start.plus(i, ChronoUnit.DAYS).toString());
            }
        }
        return result;
    }

    /**
     * 两个日期之间的周数
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static List<String> numberOfWeeks(LocalDateTime startDate, LocalDateTime endDate) {
        int addWeek = 0;
        TemporalField tf = WeekFields.SUNDAY_START.weekOfYear();
        if (startDate.get(tf) < endDate.get(tf)) {
            addWeek = 1;
        }

        long weeks = WEEKS.between(startDate, endDate) + addWeek;
        List<String> numberWeeks = new ArrayList<>();
        if (weeks >= 0) {
            int week = 0;
            do {
                //Get the number of week
                LocalDateTime dt = startDate.plusWeeks(week);
                int weekNumber = dt.get(tf);
                numberWeeks.add(String.format("%d-W%d", dt.getYear(), weekNumber)); //2018-W34
                week++;
            } while (week <= weeks);
        }
        return numberWeeks;
    }

    /**
     * 获取昨天日期字符串
     *
     * @param format 不传则是 yyyy-MM-dd
     * @return
     **/
    public static String getYesterdayDateStr(String format) {
        if (format == null || "".equals(format)) {
            format = DATE_PATTERN;
        }
        return format(LocalDate.now().minusDays(1), format);
    }

    /**
     * 获取形如时间轴的格式:xx秒前, xx分钟前, xxx小时前, 1年前
     **/
    public static String getFormatDateLine(Date datetime) {
        String timeText = "";
        YearMonth yearMonth = YearMonth.now();
        LocalDate localDate = asLocalDate(datetime);
        LocalDateTime localDateTime = asLocalDateTime(datetime);
        LocalDateTime currentDateTime = LocalDateTime.now();
        if (localDate.isEqual(LocalDate.now())) {
            //当天
            if (ChronoUnit.SECONDS.between(localDateTime, currentDateTime) < 60) {
                timeText = (ChronoUnit.SECONDS.between(localDateTime, currentDateTime)) + "秒前";
            } else if (ChronoUnit.SECONDS.between(localDateTime, currentDateTime) >= 60
                    && ChronoUnit.MINUTES.between(localDateTime, currentDateTime) < 60) {
                timeText = (ChronoUnit.MINUTES.between(localDateTime, currentDateTime)) + "分钟前";
            } else if (ChronoUnit.MINUTES.between(localDateTime, currentDateTime) >= 60
                    && ChronoUnit.HOURS.between(localDateTime, currentDateTime) < 24) {
                timeText = (ChronoUnit.HOURS.between(localDateTime, currentDateTime)) + "小时前";
            }
        } else if (localDate.getYear() == yearMonth.getYear()
                && localDate.getMonthValue() == yearMonth.getMonthValue()
                && localDate.isBefore(LocalDate.now())) {
            //当月(不包含当天)
            timeText = (LocalDate.now().getDayOfMonth() - localDate.getDayOfMonth()) + "天前";
        } else if (localDate.getYear() == yearMonth.getYear()
                && localDate.getMonthValue() < yearMonth.getMonthValue()) {
            //当年(不包含当月)
            timeText = (yearMonth.getMonthValue() - localDate.getMonthValue()) + "月前";
        } else if (localDate.getYear() < yearMonth.getYear()) {
            //去年和去年以前的
            timeText = (yearMonth.getYear() - localDate.getYear()) + "年前";
        } else {
            //其他
            timeText = localDateTime.format(DATETIME_FORMATTER);
        }
        return timeText;
    }

    /**
     * 是否是闰年
     *
     * @param year
     * @return
     */
    public static boolean isLeapYear(int year) {
        return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
    }

    /**
     * 切割日期。按照周期切割成小段日期段。例如: <br>
     *
     * @param startDate 开始日期(yyyy-MM-dd)
     * @param endDate   结束日期(yyyy-MM-dd)
     * @param period    周期(天,周,月,年)
     * @return 切割之后的日期集合
     * <li>startDate="2019-02-28",endDate="2019-03-05",period="day"</li>
     * <li>结果为:[2019-02-28, 2019-03-01, 2019-03-02, 2019-03-03, 2019-03-04, 2019-03-05]</li><br>
     * <li>startDate="2019-02-28",endDate="2019-03-25",period="week"</li>
     * <li>结果为:[2019-02-28,2019-03-06, 2019-03-07,2019-03-13, 2019-03-14,2019-03-20,
     * 2019-03-21,2019-03-25]</li><br>
     * <li>startDate="2019-02-28",endDate="2019-05-25",period="month"</li>
     * <li>结果为:[2019-02-28,2019-02-28, 2019-03-01,2019-03-31, 2019-04-01,2019-04-30,
     * 2019-05-01,2019-05-25]</li><br>
     * <li>startDate="2019-02-28",endDate="2020-05-25",period="year"</li>
     * <li>结果为:[2019-02-28,2019-12-31, 2020-01-01,2020-05-25]</li><br>
     */
    public static List<String> listDateStrs(String startDate, String endDate, String period) {
        List<String> result = new ArrayList<>();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATE_PATTERN);
        LocalDate end = LocalDate.parse(endDate, dateTimeFormatter);
        LocalDate start = LocalDate.parse(startDate, dateTimeFormatter);
        LocalDate tmp = start;
        switch (period) {
            case DAY:
                while (start.isBefore(end) || start.isEqual(end)) {
                    result.add(start.toString());
                    start = start.plusDays(1);
                }
                break;
            case WEEK:
                while (tmp.isBefore(end) || tmp.isEqual(end)) {
                    if (tmp.plusDays(6).isAfter(end)) {
                        result.add(tmp.toString() + "," + end);
                    } else {
                        result.add(tmp.toString() + "," + tmp.plusDays(6));
                    }
                    tmp = tmp.plusDays(7);
                }
                break;
            case MONTH:
                while (tmp.isBefore(end) || tmp.isEqual(end)) {
                    LocalDate lastDayOfMonth = tmp.with(TemporalAdjusters.lastDayOfMonth());
                    if (lastDayOfMonth.isAfter(end)) {
                        result.add(tmp.toString() + "," + end);
                    } else {
                        result.add(tmp.toString() + "," + lastDayOfMonth);
                    }
                    tmp = lastDayOfMonth.plusDays(1);
                }
                break;
            case YEAR:
                while (tmp.isBefore(end) || tmp.isEqual(end)) {
                    LocalDate lastDayOfYear = tmp.with(TemporalAdjusters.lastDayOfYear());
                    if (lastDayOfYear.isAfter(end)) {
                        result.add(tmp.toString() + "," + end);
                    } else {
                        result.add(tmp.toString() + "," + lastDayOfYear);
                    }
                    tmp = lastDayOfYear.plusDays(1);
                }
                break;
            default:
                break;
        }
        return result;
    }

    public static void main(String[] args) {
        System.out.println(getLocalDateTimeStr());
        System.out.println(getLocalDateStr());
        System.out.println(getLocalTimeStr());
        System.out.println("星期:" + getDayOfWeekStr());
        System.out.println(getDayOfWeekStr(LocalDate.now()));

        System.out.println("========");
        System.out.println(format(LocalDate.now(), UNSIGNED_DATE_PATTERN));

        System.out.println("========");
        System.out.println(parseLocalDateTime("2020-12-13 11:14:12", DATETIME_PATTERN));
        System.out.println(parseLocalDate("2020-12-13", DATE_PATTERN));

        System.out.println("========");
        System.out.println(plus(LocalDateTime.now(), 3, ChronoUnit.HOURS));
        System.out.println(minus(LocalDateTime.now(), 4, ChronoUnit.DAYS));

        System.out.println("========");
        System.out.println(getChronoUnitBetween(LocalDateTime.now(), parseLocalDateTime("2020-12-12 12:03:12", DATETIME_PATTERN), ChronoUnit.MINUTES));
        System.out.println(getChronoUnitBetween(LocalDate.now(), parseLocalDate("2021-12-12", DATE_PATTERN), WEEKS));

        System.out.println("========");
        System.out.println(getFirstDayOfYearStr());
        System.out.println(getFirstDayOfYearStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN)));
        System.out.println(getFirstDayOfYearStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN), UNSIGNED_DATETIME_PATTERN));

        System.out.println(getLastDayOfYearStr());
        System.out.println(getLastDayOfYearStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN)));
        System.out.println(getLastDayOfYearStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN), UNSIGNED_DATETIME_PATTERN));

        System.out.println("========");
        System.out.println(getFirstDayOfMonthStr());
        System.out.println(getFirstDayOfMonthStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN)));
        System.out.println(getFirstDayOfMonthStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN), UNSIGNED_DATETIME_PATTERN));

        System.out.println(getLastDayOfMonthStr());
        System.out.println(getLastDayOfMonthStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN)));
        System.out.println(getLastDayOfMonthStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN), UNSIGNED_DATETIME_PATTERN));

        System.out.println("========");
        System.out.println(getFirstDayOfWeekStr());
        System.out.println(getFirstDayOfWeekStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN)));
        System.out.println(getFirstDayOfWeekStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN), UNSIGNED_DATETIME_PATTERN));

        System.out.println(getLastDayOfWeekStr());
        System.out.println(getLastDayOfWeekStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN)));
        System.out.println(getLastDayOfWeekStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN), UNSIGNED_DATETIME_PATTERN));

        System.out.println("========");
        System.out.println(getStartTimeOfDayStr());
        System.out.println(getStartTimeOfDayStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN)));
        System.out.println(getStartTimeOfDayStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN), UNSIGNED_DATETIME_PATTERN));

        System.out.println(getEndTimeOfDayStr());
        System.out.println(getEndTimeOfDayStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN)));
        System.out.println(getEndTimeOfDayStr(parseLocalDateTime("2021-12-12 12:03:12", DATETIME_PATTERN), UNSIGNED_DATETIME_PATTERN));

        System.out.println("========");
        List<String> dateStrs = listDateStrs("2019-01-30", "2020-12-13", YEAR);
        for (String dateStr : dateStrs) {
            System.out.println(dateStr);
        }

        System.out.println("========");
        List<String> dateStrs1 = listDateStrs("2019-01-30", "2020-12-13", MONTH);
        for (String dateStr : dateStrs1) {
            System.out.println(dateStr);
        }

        System.out.println("========");
        List<String> dateStrs2 = listDateStrs("2020-12-01", "2020-12-13", DAY);
        for (String dateStr : dateStrs2) {
            System.out.println(dateStr);
        }

        System.out.println("========");
        LocalDate start = LocalDate.of(2022, 1, 1);
        LocalDate end = LocalDate.of(2022, 1, 15);
        long timstrap = start.atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli();
        long endtime = end.atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli();
        for (String s : getTimePeriodFromTwoTime(timstrap, endtime, "DAY")) {
            System.out.println(s);
        }
        System.out.println("========");
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss','SSS");
        LocalDateTime startDate = LocalDateTime.parse("2018-08-24T12:18:06,166", format);
        LocalDateTime endDate = LocalDateTime.parse("2018-09-12T12:19:06,188", format);
        List<String> numberOfWeeks = numberOfWeeks(startDate, endDate);
        System.out.println("numberOfWeeks:" + numberOfWeeks);

        System.out.println("========");
        List<String> monthBetween = getMonthBetween("2022-01-01", "2022-06-09");
        System.out.println(monthBetween);

        System.out.println("========");
        String format1 = format(new Date(), "yyyy-MM-dd");
        System.out.println(format1);

        System.out.println("========");
        Date date = parseDate("2021-12-10 12:10:10", "yyyy-MM-dd HH:mm:ss");
        System.out.println(date);
        System.out.println("========");
        Map<String, Object> timeIntervalMap = getTimeIntervalByDay("2022-07-22", "00:00", "24:00", "two_hour");
        System.out.println("timeIntervalMap-keySet" + timeIntervalMap.keySet().toString());
        System.out.println("timeIntervalMap-ValueSet" + timeIntervalMap.values().toString());
        System.out.println("========");
        List<String> dayMonths = getLastDayMonths("2022-07-15", 5, "yyyy-MM-dd", true);
        System.out.println("dayMonths:" + dayMonths);
        System.out.println("========");
        List<String> yearMonths = getLastYearMonths("2022-05", 5, "yyyy-MM", true);
        System.out.println("yearMonths:" + yearMonths);


    }
}

常用的日期和时间类:

  • Clock:用于获取指定时区当前日期时间
  • DayOfWeek:枚举类,定义周一到周日的枚举值
  • Duration:表示持续时间。OfXxx()用于获取时间的小时分钟秒
  • Instant:表示一个具体的时刻,可以精确到纳秒。提供了now()方法获取当前时刻,now(Clock clock)用于获取clock对应时刻,plusXxx()当前时间基础加时间,minusXxx减时间
  • LocalDate:表示不带时区的日期,now(Clock clock)用于获取clock对应日期,plusXxx()当前时间基础加年月日,minusXxx()减年月日
  • LocalTime:表示不带时区的时间,now(Clock clock)用于获取clock对应时间,plusXxx()当前时间基础加上时分秒,minusXxx()减时分秒
  • LocalDateTime:代表不带时区的日期时间,提供了now()方法获取当前日期时间,now(Clock clock)用于获取clock对应日期时间,plusXxx()当前时间基础加几年几月几日几时几分几秒,minusXxx减时间
  • Month:枚举类,定义了一月到十二月的枚举值
  • MonthDay:表示月日,该类提供了静态now()方法获取当前月日now(Clock clock)获取clock对应的月日
  • Year:表示年,now()获取年份
  • YearMonth:表示年月
  • ZoneId:表示一个时区
  • ZoneDateTime:表示一个时区化的日期和时间

 

posted @ 2022-06-09 12:08  残城碎梦  阅读(60)  评论(0编辑  收藏  举报