Java8 日期/时间 工具类



import org.apache.commons.lang3.StringUtils;

import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 日期/时间 工具类
 *
 * @author ab
 * @date 2020/10/8 10:27
 * @Version 1.0
 */
public class DateTimeUtil {

    public static String YMD = "yyyy-MM-dd";

    public static String YMD_SFM = "yyyy-MM-dd HH:mm:ss";

    /**
     * 本周的开始/结束时间
     *
     * @param today
     * @param isFirst true 表示开始时间,false表示结束时间
     * @return
     */
    public static Date getDateStartOrEndDayOfWeek(LocalDate today, Boolean isFirst) {
        if (today == null) {
            today = LocalDate.now();
        }
        if (isFirst) {
            today = today.with(DayOfWeek.MONDAY);
            return localDate2DateStart(today);
        } else {
            today = today.with(DayOfWeek.SUNDAY);
            return localDate2DateEnd(today);
        }

    }


    /**
     * 本月 当前旬 的开始日期 结束日期
     *
     * @param today
     * @param isFirst true 表示开始时间,false表示结束时间
     * @return
     */
    public static Date getXun(LocalDate today, Boolean isFirst) {
        if (today == null) {
            today = LocalDate.now();
        }
        int dayOfMonth = today.getDayOfMonth();
        if (dayOfMonth < 11) {
            //上旬
            if (isFirst) {
                today = LocalDate.of(today.getYear(), today.getMonthValue(), 1);
                return localDate2DateStart(today);
            } else {
                today = LocalDate.of(today.getYear(), today.getMonthValue(), 10);
                return localDate2DateEnd(today);
            }
        } else if (dayOfMonth < 21) {
            //中旬
            if (isFirst) {
                today = LocalDate.of(today.getYear(), today.getMonthValue(), 11);
                return localDate2DateStart(today);
            } else {
                today = LocalDate.of(today.getYear(), today.getMonthValue(), 20);
                return localDate2DateEnd(today);
            }
        } else {
            //下旬
            if (isFirst) {
                today = LocalDate.of(today.getYear(), today.getMonthValue(), 21);
                return localDate2DateStart(today);
            } else {
                today = today.with(TemporalAdjusters.lastDayOfMonth());
                return localDate2DateEnd(today);
            }
        }
    }

    /**
     * 本月的开始/结束时间
     *
     * @param today
     * @param isFirst true 表示开始时间,false表示结束时间
     * @return
     */
    public static Date getDateStartOrEndDayOfMonth(LocalDate today, Boolean isFirst) {
        if (today == null) {
            today = LocalDate.now();
        }
        if (isFirst) {
            today = today.with(TemporalAdjusters.firstDayOfMonth());
            return localDate2DateStart(today);
        } else {
            today = today.with(TemporalAdjusters.lastDayOfMonth());
            return localDate2DateEnd(today);
        }

    }

    /**
     * 本月 所在季度的开始/结束时间
     *
     * @param today
     * @param isFirst true 表示开始时间,false表示结束时间
     * @return
     */
    public static Date getJiDu(LocalDate today, Boolean isFirst) {
        if (today == null) {
            today = LocalDate.now();
        }
        int monthValue = today.getMonthValue();
        if (monthValue < 4) {
            if (isFirst) {
                today = LocalDate.of(today.getYear(), 1, 1);
                return localDate2DateStart(today);
            } else {
                today = LocalDate.of(today.getYear(), 3, 31);
                return localDate2DateEnd(today);
            }
        } else if (monthValue < 7) {
            if (isFirst) {
                today = LocalDate.of(today.getYear(), 4, 1);
                return localDate2DateStart(today);
            } else {
                today = LocalDate.of(today.getYear(), 6, 30);
                return localDate2DateEnd(today);
            }
        } else if (monthValue < 10) {
            if (isFirst) {
                today = LocalDate.of(today.getYear(), 7, 1);
                return localDate2DateStart(today);
            } else {
                today = LocalDate.of(today.getYear(), 9, 30);
                return localDate2DateEnd(today);
            }
        } else {
            if (isFirst) {
                today = LocalDate.of(today.getYear(), 10, 1);
                return localDate2DateStart(today);
            } else {
                today = LocalDate.of(today.getYear(), 12, 31);
                return localDate2DateEnd(today);
            }
        }

    }

    /**
     * 本半年 的开始/结束时间
     *
     * @param today
     * @param isFirst true 表示开始时间,false表示结束时间
     * @return
     */
    public static Date getHalfYear(LocalDate today, Boolean isFirst) {
        if (today == null) {
            today = LocalDate.now();
        }
        int monthValue = today.getMonthValue();
        if (monthValue < 7) {
            if (isFirst) {
                today = LocalDate.of(today.getYear(), 1, 1);
                return localDate2DateStart(today);
            } else {
                today = LocalDate.of(today.getYear(), 6, 30);
                return localDate2DateEnd(today);
            }
        } else {
            if (isFirst) {
                today = LocalDate.of(today.getYear(), 7, 1);
                return localDate2DateStart(today);
            } else {
                today = LocalDate.of(today.getYear(), 12, 31);
                return localDate2DateEnd(today);
            }
        }

    }


    /**
     * 本年度的开始/结束时间
     *
     * @param today
     * @param isFirst true 表示开始时间,false表示结束时间
     * @return
     */
    public static Date getDateStartOrEndDayOfYear(LocalDate today, Boolean isFirst) {
        if (today == null) {
            today = LocalDate.now();
        }
        if (isFirst) {
            today = today.with(TemporalAdjusters.firstDayOfYear());
            return localDate2DateStart(today);
        } else {
            today = today.with(TemporalAdjusters.lastDayOfYear());
            return localDate2DateEnd(today);
        }

    }

    /**
     * 间隔N天后的日期 结束时间
     *
     * @param today
     * @param days  间隔几天
     * @return
     */
    public static Date getDateIntervalDateEnd(LocalDate today, long days) {
        if (today == null) {
            today = LocalDate.now();
        }
        today = today.plusDays(days);
        return localDate2DateEnd(today);
    }

    /**
     * 获取两个日期之间相差的分钟数
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return long
     */
    public static long getDateSubMinutes(Date start, Date end) {
        LocalDateTime firstDateTime = null;
        LocalDateTime secondDateTime = date2LocalDateTime(end);
        if (null == start) {
            firstDateTime = secondDateTime.toLocalDate().atStartOfDay();
        } else {
            firstDateTime = date2LocalDateTime(start);
        }
        return Duration.between(firstDateTime, secondDateTime).toMinutes();
    }

    /**
     * 获取两个日期之间相差的小时数
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return long
     */
    public static long getDateSubHours(Date start, Date end) {
        LocalDateTime firstDateTime = null;
        LocalDateTime secondDateTime = date2LocalDateTime(end);
        if (null == start) {
            firstDateTime = secondDateTime.toLocalDate().atStartOfDay();
        } else {
            firstDateTime = date2LocalDateTime(start);
        }
        return Duration.between(firstDateTime, secondDateTime).toHours();
    }

    /**
     * 获取两个日期之间相差的天数
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return long
     */
    public static long getDateSubDays(Date start, Date end) {
        LocalDate firstDate = date2LocalDate(start);
        LocalDate secondDate = date2LocalDate(end);
        return ChronoUnit.DAYS.between(firstDate, secondDate);
    }

    /**
     * 将指定 年 月 转成date
     *
     * @param year  年份
     * @param month 月份
     * @return Date
     */
    public static Date getDateByYM(String year, String month) {
        int month1 = Integer.parseInt(month);
        if (month1 < 10) {
            month = "0" + month;
        }
        String date = year + "-" + month + "-01";
        return string2Date(date, YMD, true);
    }

    /**
     * 收集起始时间到结束时间之间所有的时间并以字符串集合方式返回
     *
     * @param type      1 获取年月日  2 获取月日  3 年月
     * @param timeStart 年月日 yyyy-MM-dd
     * @param timeEnd   年月日 yyyy-MM-dd
     * @return
     */
    public static List<String> collectLocalDates(String timeStart, String timeEnd, String type) {
        return collectLocalDates(LocalDate.parse(timeStart), LocalDate.parse(timeEnd), type);
    }

    /**
     * 收集起始时间到结束时间之间所有的时间并以字符串集合方式返回
     *
     * @param type  1 获取年月日  2 获取月日  3 年月
     * @param start 开始
     * @param end   结束
     * @return
     */
    public static List<String> collectLocalDates(LocalDate start, LocalDate end, String type) {
        if ("2".equals(type)) {
            // 用起始时间作为流的源头,按照每次加一天的方式创建一个无限流
            return Stream.iterate(start, localDate -> localDate.plusDays(1))
                    // 截断无限流,长度为起始时间和结束时间的差+1个
                    .limit(ChronoUnit.DAYS.between(start, end) + 1)
                    // 由于最后要的是字符串,所以map转换一下
                    .map(DateTimeUtil::getMonthAndDay)
                    // 把流收集为List
                    .collect(Collectors.toList());
        } else if ("1".equals(type)) {
            // 用起始时间作为流的源头,按照每次加一天的方式创建一个无限流
            return Stream.iterate(start, localDate -> localDate.plusDays(1))
                    // 截断无限流,长度为起始时间和结束时间的差+1个
                    .limit(ChronoUnit.DAYS.between(start, end) + 1)
                    // 由于最后要的是字符串,所以map转换一下
                    .map(LocalDate::toString)
                    // 把流收集为List
                    .collect(Collectors.toList());
        } else {
            // 用起始时间作为流的源头,按照每次加一月的方式创建一个无限流
            return Stream.iterate(start, localDate -> localDate.plusMonths(1))
                    // 截断无限流,长度为起始时间和结束时间的差+1个
                    .limit(ChronoUnit.MONTHS.between(start, end) + 1)
                    // 由于最后要的是字符串,所以map转换一下
                    .map(DateTimeUtil::getYearAndMonth)
                    // 把流收集为List
                    .collect(Collectors.toList());
        }
    }

    /**
     * 获取 月日
     *
     * @return
     */
    public static String getMonthAndDay(LocalDate localDate) {
        int monthValue = localDate.getMonthValue();
        String month = monthValue < 10 ? "0" + monthValue : monthValue + "";
        int dayOfMonth = localDate.getDayOfMonth();
        String day = dayOfMonth < 10 ? "0" + dayOfMonth : dayOfMonth + "";
        return month + "-" + day;
    }

    /**
     * 获取 年月
     *
     * @return
     */
    public static String getYearAndMonth(LocalDate localDate) {
        int monthValue = localDate.getMonthValue();
        String month = monthValue < 10 ? "0" + monthValue : monthValue + "";
        return localDate.getYear() + "-" + month;
    }

    /**
     * 获取指定月份的天数
     *
     * @param year  年份
     * @param month 月份
     * @return 天数
     */
    public static int getDayCntOfMonth(int year, int month) {
        if (month > 12 || month < 1) {
            return 0;
        }
        return LocalDate.of(year, month, 1).lengthOfMonth();
    }

    /**
     * 获取指定日期 的 零点时间戳
     *
     * @param date 日期。如  "2020-04-12"
     * @return 时间戳 毫秒
     */
    public static Long getStartOfDay(String date) {
        if (StringUtils.isEmpty(date)) {
            date = date2String(new Date(), YMD);
        }
        DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern(YMD, Locale.CHINA);
        LocalDate parse = LocalDate.parse(date, ofPattern);
        return parse.atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli();
    }

    /**
     * 获取指定日期 的 末尾时间戳
     *
     * @param date 日期。如  "2020-04-12"
     * @return 时间戳 毫秒
     */
    public static Long getEndOfDay(String date) {
        if (StringUtils.isEmpty(date)) {
            date = date2String(new Date(), YMD);
        }
        DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern(YMD, Locale.CHINA);
        LocalDate parse = LocalDate.parse(date, ofPattern);
        return LocalDateTime.of(parse, LocalTime.MAX).toInstant(ZoneOffset.of("+8")).toEpochMilli();
    }

    /**
     * 日期/时间 字符串 转 时间戳
     *
     * @param dateTime 日期或者时间 字符串。如 日期 :"2020-04-12"   时间: "2020-04-12 12:59:59"
     * @param pattern  日期或者时间 格式。  如 日期 :YMD   时间: YMD_SFM
     * @param isDate   是否为日期  @dateTime 为日期则传 true,否则false
     * @return 时间戳 毫秒
     */
    public static Long string2TimeStamp(String dateTime, String pattern, Boolean isDate) {
        DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern(pattern, Locale.CHINA);
        if (isDate) {
            LocalDate parse = LocalDate.parse(dateTime, ofPattern);
            return parse.atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli();
        } else {
            LocalDateTime parse = LocalDateTime.parse(dateTime, ofPattern);
            return parse.toInstant(ZoneOffset.of("+8")).toEpochMilli();
        }
    }

    /**
     * 时间戳  转  日期/时间 字符串
     *
     * @param seconds 时间戳  13位毫秒
     * @param pattern 时间格式  如 yyyy-MM-dd HH:mm:ss
     * @return 格式化的时间
     */
    public static String timeStamp2String(Long seconds, String pattern) {
        if (StringUtils.isEmpty(pattern)) {
            pattern = YMD_SFM;
        }
        String time = null;
        LocalDateTime dateTime = LocalDateTime.ofEpochSecond(seconds / 1000L, 0, ZoneOffset.ofHours(8));
        if (seconds != 0) {
            time = dateTime.format(DateTimeFormatter.ofPattern(pattern));
        }
        return time;
    }

    /**
     * 日期/时间 转 字符串
     *
     * @param date    时间
     * @param pattern 日期或者时间 格式。  如 日期 :yyyy-MM-dd   时间: yyyy-MM-dd HH:mm:ss
     * @return 格式化的时间
     */
    public static String date2String(Date date, String pattern) {
        DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern(pattern, Locale.CHINA);
        LocalDateTime localDateTime = date2LocalDateTime(date);
        return ofPattern.format(localDateTime);
    }

    /**
     * 字符串  转 日期/时间
     *
     * @param date    日期或者时间 字符串。如 日期 :"2020-04-12"   时间: "2020-04-12 12:59:59"
     * @param pattern 日期或者时间 格式。  如 日期 :yyyy-MM-dd   时间: yyyy-MM-dd HH:mm:ss
     * @param isDate  true 为年月日。  false为 年月日 时分秒
     * @return 格式化的时间 Date
     */
    public static Date string2Date(String date, String pattern, Boolean isDate) {
        DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern(pattern, Locale.CHINA);
        if (isDate) {
            LocalDate localDate = LocalDate.parse(date, ofPattern);
            return localDate2Date(localDate);
        } else {
            LocalDateTime localDateTime = LocalDateTime.parse(date, ofPattern);
            return localDateTime2Date(localDateTime);
        }
    }

    /**
     * 判断时间是否为今天
     *
     * @param date 日期
     * @return 格式化的时间 Date
     */
    public static Boolean isToday(Date date) {
        // 当前时间
        Date now = new Date();
        SimpleDateFormat sf = new SimpleDateFormat(YMD);
        //获取今天的日期
        String nowDay = sf.format(now);
        //对比的时间
        String day = sf.format(date);
        return day.equals(nowDay);
    }


    /**
     * 获取今年或去年的年份
     *
     * @param isDate
     * @return
     */
    public static String getYear(Boolean isDate) {
        int year = LocalDate.now().getYear();
        if (isDate) {
            return String.valueOf(year);
        } else {
            return String.valueOf(year - 1);
        }
    }

    /**
     * 根据给定的时间,返回该时间所属的起始时间和下一日的起始时间。
     * 起始时间定义为10:00:00。如果输入时间在当天10点之前,则起始时间为前一天的10点。
     *
     * @param inputTime 给定的LocalDateTime对象
     * @return 包含起始时间和下一日起始时间的数组,格式为[起始时间, 下一日起始时间]
     */
    public static LocalDateTime[] getDayStartAndNextDayStart(LocalDateTime inputTime) {
        if (inputTime.toLocalTime().isBefore(LocalTime.of(10, 0))) {
            // 如果时间在10点之前,则起始时间是前一天的10点
            LocalDateTime todayStart = inputTime.minusDays(1).with(LocalTime.of(10, 0));
            LocalDateTime nextDayStart = todayStart.plusDays(1);
            return new LocalDateTime[]{todayStart, nextDayStart};
        } else {
            // 否则起始时间是当天的10点
            LocalDateTime todayStart = inputTime.with(LocalTime.of(10, 0));
            LocalDateTime nextDayStart = todayStart.plusDays(1);
            return new LocalDateTime[]{todayStart, nextDayStart};
        }
    }

    public static void main(String[] args) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String timeStr = "2024-05-23 02:20:00";
        LocalDateTime inputTime = LocalDateTime.parse(timeStr, formatter);

        LocalDateTime[] result = getDayStartAndNextDayStart(inputTime);
        System.out.println("起始时间: " + result[0].format(formatter));
        System.out.println("下一日起始时间: " + result[1].format(formatter));
    }

    //==============================================================================================================================

    /**
     * 将java.util.Date 转换为java8 的java.time.LocalDateTime,默认时区为东8区
     */
    public static LocalDateTime date2LocalDateTime(Date date) {
        return date.toInstant().atOffset(ZoneOffset.of("+8")).toLocalDateTime();
    }


    /**
     * 将java8 的 java.time.LocalDateTime 转换为 java.util.Date,默认时区为东8区
     */
    public static Date localDateTime2Date(LocalDateTime localDateTime) {
        return Date.from(localDateTime.toInstant(ZoneOffset.of("+8")));
    }

    /**
     * 将java8 的 java.time.LocalDate 转换为 java.util.Date,默认时区为东8区
     */
    public static Date localDate2Date(LocalDate localDate) {
        return Date.from(localDate.atStartOfDay().toInstant(ZoneOffset.of("+8")));
    }

    /**
     * 将java.util.Date 转换为java8 的java.time.LocalDate,默认时区为东8区
     */
    public static LocalDate date2LocalDate(Date date) {
        return date.toInstant().atOffset(ZoneOffset.of("+8")).toLocalDate();
    }

    private static Date localDate2DateStart(LocalDate localDate) {
        return Date.from(LocalDateTime.of(localDate, LocalTime.MIN).withNano(0).toInstant(ZoneOffset.of("+8")));
    }

    private static Date localDate2DateEnd(LocalDate localDate) {
        return  Date.from(LocalDateTime.of(localDate, LocalTime.MAX).withNano(0).toInstant(ZoneOffset.of("+8")));
    }
}

posted @ 2025-01-08 14:55  qwer78  阅读(30)  评论(0)    收藏  举报