All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.micro.core.util.DateUtil Maven / Gradle / Ivy

package cn.micro.core.util;

import org.springframework.lang.Nullable;

import java.time.*;
import java.time.chrono.ChronoLocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.*;
import java.util.*;

import static java.time.temporal.ChronoField.*;

/**
 * 日期工具类
 */
public class DateUtil {

    /**
     * 添加年
     *
     * @param date       时间
     * @param yearsToAdd 添加的年数
     * @return 设置后的时间
     */
    public static Date plusYears(Date date, int yearsToAdd) {
        return DateUtil.plusAtUtc(date, Period.ofYears(yearsToAdd));
    }

    /**
     * 添加月
     *
     * @param date        时间
     * @param monthsToAdd 添加的月数
     * @return 设置后的时间
     */
    public static Date plusMonths(Date date, int monthsToAdd) {
        return DateUtil.plusAtUtc(date, Period.ofMonths(monthsToAdd));
    }

    /**
     * 添加周
     *
     * @param date       时间
     * @param weeksToAdd 添加的周数
     * @return 设置后的时间
     */
    public static Date plusWeeks(Date date, int weeksToAdd) {
        return DateUtil.plus(date, Period.ofWeeks(weeksToAdd));
    }

    /**
     * 添加天
     *
     * @param date      时间
     * @param daysToAdd 添加的天数
     * @return 设置后的时间
     */
    public static Date plusDays(Date date, long daysToAdd) {
        return DateUtil.plus(date, Duration.ofDays(daysToAdd));
    }

    /**
     * 添加小时
     *
     * @param date       时间
     * @param hoursToAdd 添加的小时数
     * @return 设置后的时间
     */
    public static Date plusHours(Date date, long hoursToAdd) {
        return DateUtil.plus(date, Duration.ofHours(hoursToAdd));
    }

    /**
     * 添加分钟
     *
     * @param date         时间
     * @param minutesToAdd 添加的分钟数
     * @return 设置后的时间
     */
    public static Date plusMinutes(Date date, long minutesToAdd) {
        return DateUtil.plus(date, Duration.ofMinutes(minutesToAdd));
    }

    /**
     * 添加秒
     *
     * @param date         时间
     * @param secondsToAdd 添加的秒数
     * @return 设置后的时间
     */
    public static Date plusSeconds(Date date, long secondsToAdd) {
        return DateUtil.plus(date, Duration.ofSeconds(secondsToAdd));
    }

    /**
     * 添加毫秒
     *
     * @param date        时间
     * @param millisToAdd 添加的毫秒数
     * @return 设置后的时间
     */
    public static Date plusMillis(Date date, long millisToAdd) {
        return DateUtil.plus(date, Duration.ofMillis(millisToAdd));
    }

    /**
     * 添加纳秒
     *
     * @param date       时间
     * @param nanosToAdd 添加的纳秒数
     * @return 设置后的时间
     */
    public static Date plusNanos(Date date, long nanosToAdd) {
        return DateUtil.plus(date, Duration.ofNanos(nanosToAdd));
    }

    /**
     * 日期添加时间量
     *
     * @param date   时间
     * @param amount 时间量
     * @return 设置后的时间
     */
    public static Date plusAtUtc(Date date, TemporalAmount amount) {
        Objects.requireNonNull(date, "The date must not be null");
        Instant instant = date.toInstant()
                .atZone(ZoneOffset.UTC)
                .plus(amount)
                .toInstant();
        return Date.from(instant);
    }

    /**
     * 日期添加时间量
     *
     * @param date   时间
     * @param amount 时间量
     * @return 设置后的时间
     */
    public static Date plus(Date date, TemporalAmount amount) {
        Objects.requireNonNull(date, "The date must not be null");
        Instant instant = date.toInstant()
                .plus(amount);
        return Date.from(instant);
    }

    /**
     * 减少年
     *
     * @param date  时间
     * @param years 减少的年数
     * @return 设置后的时间
     */
    public static Date minusYears(Date date, int years) {
        return DateUtil.minusAtUtc(date, Period.ofYears(years));
    }

    /**
     * 减少月
     *
     * @param date   时间
     * @param months 减少的月数
     * @return 设置后的时间
     */
    public static Date minusMonths(Date date, int months) {
        return DateUtil.minusAtUtc(date, Period.ofMonths(months));
    }

    /**
     * 减少周
     *
     * @param date  时间
     * @param weeks 减少的周数
     * @return 设置后的时间
     */
    public static Date minusWeeks(Date date, int weeks) {
        return DateUtil.minus(date, Period.ofWeeks(weeks));
    }

    /**
     * 减少天
     *
     * @param date 时间
     * @param days 减少的天数
     * @return 设置后的时间
     */
    public static Date minusDays(Date date, long days) {
        return DateUtil.minus(date, Duration.ofDays(days));
    }

    /**
     * 减少小时
     *
     * @param date  时间
     * @param hours 减少的小时数
     * @return 设置后的时间
     */
    public static Date minusHours(Date date, long hours) {
        return DateUtil.minus(date, Duration.ofHours(hours));
    }

    /**
     * 减少分钟
     *
     * @param date    时间
     * @param minutes 减少的分钟数
     * @return 设置后的时间
     */
    public static Date minusMinutes(Date date, long minutes) {
        return DateUtil.minus(date, Duration.ofMinutes(minutes));
    }

    /**
     * 减少秒
     *
     * @param date    时间
     * @param seconds 减少的秒数
     * @return 设置后的时间
     */
    public static Date minusSeconds(Date date, long seconds) {
        return DateUtil.minus(date, Duration.ofSeconds(seconds));
    }

    /**
     * 减少毫秒
     *
     * @param date   时间
     * @param millis 减少的毫秒数
     * @return 设置后的时间
     */
    public static Date minusMillis(Date date, long millis) {
        return DateUtil.minus(date, Duration.ofMillis(millis));
    }

    /**
     * 减少纳秒
     *
     * @param date  时间
     * @param nanos 减少的纳秒数
     * @return 设置后的时间
     */
    public static Date minusNanos(Date date, long nanos) {
        return DateUtil.minus(date, Duration.ofNanos(nanos));
    }

    /**
     * 日期减少时间量
     *
     * @param date   时间
     * @param amount 时间量
     * @return 设置后的时间
     */
    public static Date minusAtUtc(Date date, TemporalAmount amount) {
        Objects.requireNonNull(date, "The date must not be null");
        Instant instant = date.toInstant()
                .atZone(ZoneOffset.UTC)
                .minus(amount)
                .toInstant();
        return Date.from(instant);
    }

    /**
     * 日期减少时间量
     *
     * @param date   时间
     * @param amount 时间量
     * @return 设置后的时间
     */
    public static Date minus(Date date, TemporalAmount amount) {
        Objects.requireNonNull(date, "The date must not be null");
        Instant instant = date.toInstant()
                .minus(amount);
        return Date.from(instant);
    }

    /**
     * 日期时间格式化
     *
     * @param date 时间
     * @return 格式化后的时间
     */
    @Nullable
    public static String formatDateTime(@Nullable Date date) {
        return format(date, DatePattern.NORM_DATETIME_PATTERN);
    }

    /**
     * 日期格式化
     *
     * @param date 时间
     * @return 格式化后的时间
     */
    @Nullable
    public static String formatDate(@Nullable Date date) {
        return format(date, DatePattern.NORM_DATE_PATTERN);
    }

    /**
     * 时间格式化
     *
     * @param date 时间
     * @return 格式化后的时间
     */
    @Nullable
    public static String formatTime(@Nullable Date date) {
        return format(date, DatePattern.NORM_TIME_PATTERN);
    }

    /**
     * 日期格式化
     *
     * @param date    时间
     * @param pattern 表达式
     * @return 格式化后的时间
     */
    @Nullable
    public static String format(@Nullable Date date, String pattern) {
        return format(date, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 日期格式化
     *
     * @param date      时间
     * @param formatter 格式化
     * @return 格式化后的时间
     */
    @Nullable
    public static String format(@Nullable Date date, DateTimeFormatter formatter) {
        if (date == null) {
            return null;
        }
        return format(date.toInstant(), formatter);
    }

    /**
     * 日期格式化
     *
     * @param instant   时间
     * @param formatter 格式化
     * @return 格式化后的时间
     */
    @Nullable
    public static String format(Instant instant, DateTimeFormatter formatter) {
        ZoneId zone = formatter.getZone();
        if (zone == null) {
            return formatter.withZone(ZoneId.systemDefault()).format(instant);
        }
        return formatter.format(instant);
    }

    /**
     * java8 日期时间格式化
     *
     * @param temporal 时间
     * @return 格式化后的时间
     */
    public static String formatDateTime(TemporalAccessor temporal) {
        return DatePattern.NORM_DATETIME_FORMAT.format(temporal);
    }

    /**
     * java8 日期时间格式化
     *
     * @param temporal 时间
     * @return 格式化后的时间
     */
    public static String formatDate(TemporalAccessor temporal) {
        return DatePattern.NORM_DATE_FORMAT.format(temporal);
    }

    /**
     * java8 时间格式化
     *
     * @param temporal 时间
     * @return 格式化后的时间
     */
    public static String formatTime(TemporalAccessor temporal) {
        return DatePattern.NORM_TIME_FORMAT.format(temporal);
    }

    /**
     * java8 日期格式化
     *
     * @param temporal 时间
     * @param pattern  表达式
     * @return 格式化后的时间
     */
    public static String format(TemporalAccessor temporal, String pattern) {
        return DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault()).format(temporal);
    }

    /**
     * 将字符串转换为时间
     *
     * @param dateStr 时间字符串
     * @param pattern 表达式
     * @return 时间
     */
    public static Date parse(String dateStr, String pattern) {
        return DateUtil.parse(dateStr, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 将字符串转换为时间
     *
     * @param dateStr 时间字符串
     * @param format  DateTimeFormatter
     * @return 时间
     */
    public static Date parse(String dateStr, DateTimeFormatter format) {
        if (format.getZone() == null) {
            format = format.withZone(ZoneId.systemDefault());
        }
        Instant instant = format.parse(dateStr, instantQuery());
        return Date.from(instant);
    }

    /**
     * 将字符串转换为时间
     *
     * @param dateStr 时间字符串
     * @param pattern 表达式
     * @return 时间
     */
    public static  T parse(String dateStr, String pattern, TemporalQuery query) {
        return DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault()).parse(dateStr, query);
    }

    /**
     * LocalDateTime 转 Instant
     *
     * @param dateTime 时间
     * @return Instant
     */
    public static Instant toInstant(LocalDateTime dateTime) {
        return dateTime.atZone(ZoneId.systemDefault()).toInstant();
    }

    /**
     * Instant 转 LocalDateTime
     *
     * @param instant Instant
     * @return Instant
     */
    public static LocalDateTime toDateTime(Instant instant) {
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }

    /**
     * 某天开始时间 yyyy-MM-dd 00:00:00
     *
     * @param localDate LocalDate
     * @return Instant
     */
    public static LocalDateTime toStartOfDay(LocalDate localDate) {
        return localDate.atStartOfDay();
    }

    /**
     * 某天结束时间 yyyy-MM-dd 23:59:59
     *
     * @param localDate LocalDate
     * @return Instant
     */
    public static LocalDateTime toEndOfDay(LocalDate localDate) {
        return LocalDateTime.of(localDate, LocalTime.MAX);
    }

    /**
     * Date 转 LocalDateTime
     *
     * @param date Date
     * @return Instant
     */
    public static LocalDateTime toDateTime(Date date) {
        return DateUtil.toDateTime(date.toInstant());
    }

    /**
     * LocalDateTime 转换成 date
     *
     * @param dateTime LocalDateTime
     * @return Date
     */
    public static Date toDate(LocalDateTime dateTime) {
        return Date.from(DateUtil.toInstant(dateTime));
    }

    /**
     * LocalDate 转换成 date
     *
     * @param localDate LocalDate
     * @return Date
     */
    public static Date toDate(final LocalDate localDate) {
        return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    /**
     * LocalDateTime 转换成 Calendar.
     */
    public static Calendar toCalendar(final LocalDateTime localDateTime) {
        return GregorianCalendar.from(ZonedDateTime.of(localDateTime, ZoneId.systemDefault()));
    }

    /**
     * localDateTime 转换成毫秒数
     *
     * @param localDateTime LocalDateTime
     * @return long
     */
    public static long toMilliseconds(final LocalDateTime localDateTime) {
        return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * localDate 转换成毫秒数
     *
     * @param localDate LocalDate
     * @return long
     */
    public static long toMilliseconds(LocalDate localDate) {
        return toMilliseconds(localDate.atStartOfDay());
    }

    /**
     * 转换成java8 时间
     *
     * @param calendar 日历
     * @return LocalDateTime
     */
    public static LocalDateTime fromCalendar(final Calendar calendar) {
        TimeZone tz = calendar.getTimeZone();
        ZoneId zid = tz == null ? ZoneId.systemDefault() : tz.toZoneId();
        return LocalDateTime.ofInstant(calendar.toInstant(), zid);
    }

    /**
     * 转换成java8 时间
     *
     * @param instant Instant
     * @return LocalDateTime
     */
    public static LocalDateTime fromInstant(final Instant instant) {
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }

    /**
     * 转换成java8 时间
     *
     * @param date Date
     * @return LocalDateTime
     */
    public static LocalDateTime fromDate(final Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    /**
     * 转换成java8 时间
     *
     * @param milliseconds 毫秒数
     * @return LocalDateTime
     */
    public static LocalDateTime fromMilliseconds(final long milliseconds) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(milliseconds), ZoneId.systemDefault());
    }

    /**
     * 判断 A 的时间是否在 B 的时间 "之后"
     *
     * @param self  ChronoLocalDateTime
     * @param other ChronoLocalDateTime
     * @return {boolean}
     */
    public static boolean isAfter(ChronoLocalDateTime self, ChronoLocalDateTime other) {
        return self.isAfter(other);
    }

    /**
     * 判断 A 的时间是否在 B 的时间 "之前"
     *
     * @param self  ChronoLocalDateTime
     * @param other ChronoLocalDateTime
     * @return {boolean}
     */
    public static boolean isBefore(ChronoLocalDateTime self, ChronoLocalDateTime other) {
        return self.isBefore(other);
    }

    /**
     * 判断 A 的时间是否与 B 的时间 "相同"
     *
     * @param self  ChronoLocalDateTime
     * @param other ChronoLocalDateTime
     * @return {boolean}
     */
    public static boolean isEqual(ChronoLocalDateTime self, ChronoLocalDateTime other) {
        return self.isEqual(other);
    }

    /**
     * 比较2个时间差,跨度比较小
     *
     * @param startInclusive 开始时间
     * @param endExclusive   结束时间
     * @return 时间间隔
     */
    public static Duration between(Temporal startInclusive, Temporal endExclusive) {
        return Duration.between(startInclusive, endExclusive);
    }

    /**
     * 比较2个时间差,跨度比较大,年月日为单位
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return 时间间隔
     */
    public static Period between(LocalDate startDate, LocalDate endDate) {
        return Period.between(startDate, endDate);
    }

    /**
     * 比较2个 时间差
     *
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return 时间间隔
     */
    public static Duration between(Date startDate, Date endDate) {
        return Duration.between(startDate.toInstant(), endDate.toInstant());
    }

    /**
     * 将字符串转换为时间
     *
     * @param dateStr 时间字符串
     * @param pattern 表达式
     * @return 时间
     */
    public static LocalDateTime parseDateTime(CharSequence dateStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return DateUtil.parseDateTime(dateStr, formatter);
    }

    /**
     * 将字符串转换为时间
     *
     * @param dateStr   时间字符串
     * @param formatter DateTimeFormatter
     * @return 时间
     */
    public static LocalDateTime parseDateTime(CharSequence dateStr, DateTimeFormatter formatter) {
        return LocalDateTime.parse(dateStr, formatter);
    }

    /**
     * 将字符串转换为时间
     *
     * @param dateStr 时间字符串
     * @return 时间
     */
    public static LocalDateTime parseDateTime(CharSequence dateStr) {
        return DateUtil.parseDateTime(dateStr, DatePattern.NORM_DATETIME_FORMAT);
    }

    /**
     * 将字符串转换为时间
     *
     * @param text          时间字符串
     * @param parsePatterns 时间正则数组
     * @return 时间
     */
    public static LocalDateTime parseDateTime(@Nullable CharSequence text, @Nullable String[] parsePatterns) {
        return parseDateTime(text, null, parsePatterns);
    }

    /**
     * 将字符串转换为时间
     *
     * @param text          时间字符串
     * @param locale        Locale
     * @param parsePatterns 时间正则数组
     * @return 时间
     */
    public static LocalDateTime parseDateTime(@Nullable CharSequence text, @Nullable Locale locale, @Nullable String[] parsePatterns) {
        return parse(text, locale, parsePatterns, LocalDateTime::from);
    }

    /**
     * 将字符串转换为时间
     *
     * @param dateStr 时间字符串
     * @param pattern 表达式
     * @return 时间
     */
    public static LocalDate parseDate(CharSequence dateStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return DateUtil.parseDate(dateStr, formatter);
    }

    /**
     * 将字符串转换为时间
     *
     * @param dateStr   时间字符串
     * @param formatter DateTimeFormatter
     * @return 时间
     */
    public static LocalDate parseDate(CharSequence dateStr, DateTimeFormatter formatter) {
        return LocalDate.parse(dateStr, formatter);
    }

    /**
     * 将字符串转换为日期
     *
     * @param dateStr 时间字符串
     * @return 时间
     */
    public static LocalDate parseDate(CharSequence dateStr) {
        return DateUtil.parseDate(dateStr, DatePattern.NORM_DATE_FORMAT);
    }

    /**
     * 将字符串转换为日期
     *
     * @param text          时间字符串
     * @param parsePatterns 时间正则数组
     * @return 时间
     */
    public static LocalDate parseDate(@Nullable CharSequence text, @Nullable String[] parsePatterns) {
        return parseDate(text, null, parsePatterns);
    }

    /**
     * 将字符串转换为日期
     *
     * @param text          时间字符串
     * @param locale        Locale
     * @param parsePatterns 时间正则数组
     * @return 时间
     */
    public static LocalDate parseDate(@Nullable CharSequence text, @Nullable Locale locale, @Nullable String[] parsePatterns) {
        return parse(text, locale, parsePatterns, LocalDate::from);
    }

    /**
     * 将字符串转换为时间
     *
     * @param dateStr 时间字符串
     * @param pattern 时间正则
     * @return 时间
     */
    public static LocalTime parseTime(CharSequence dateStr, String pattern) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return DateUtil.parseTime(dateStr, formatter);
    }

    /**
     * 将字符串转换为时间
     *
     * @param dateStr   时间字符串
     * @param formatter DateTimeFormatter
     * @return 时间
     */
    public static LocalTime parseTime(CharSequence dateStr, DateTimeFormatter formatter) {
        return LocalTime.parse(dateStr, formatter);
    }

    /**
     * 将字符串转换为时间
     *
     * @param dateStr 时间字符串
     * @return 时间
     */
    public static LocalTime parseTime(CharSequence dateStr) {
        return DateUtil.parseTime(dateStr, DatePattern.NORM_TIME_FORMAT);
    }

    /**
     * 将字符串转换为时间
     *
     * @param text          时间字符串
     * @param parsePatterns 时间正则数组
     * @return 时间
     */
    public static LocalTime parseTime(@Nullable CharSequence text, @Nullable String[] parsePatterns) {
        return parseTime(text, null, parsePatterns);
    }

    /**
     * 将字符串转换为时间
     *
     * @param text          时间字符串
     * @param locale        Locale
     * @param parsePatterns 时间正则数组
     * @return 时间
     */
    public static LocalTime parseTime(@Nullable CharSequence text, @Nullable Locale locale, @Nullable String[] parsePatterns) {
        return parse(text, locale, parsePatterns, LocalTime::from);
    }

    /**
     * 将字符串转换为时间
     *
     * @param text          时间字符串
     * @param locale        Locale
     * @param parsePatterns 时间正则数组
     * @param query         TemporalQuery
     * @param            泛型
     * @return 时间
     */
    public static  T parse(@Nullable CharSequence text, @Nullable Locale locale, @Nullable String[] parsePatterns, TemporalQuery query) {
        if (text == null || parsePatterns == null) {
            throw new IllegalArgumentException("Date and Patterns must not be null");
        }
        final Locale lcl = locale == null ? Locale.getDefault() : locale;
        final ZoneId systemZone = ZoneId.systemDefault();
        DateTimeFormatter formatter = null;
        for (final String parsePattern : parsePatterns) {
            formatter = DateTimeFormatter.ofPattern(parsePattern, lcl).withZone(systemZone);
            try {
                return formatter.parse(text, query);
            } catch (final DateTimeParseException ignore) {
                // leniency is preventing calendar from being set
            }
        }
        throw new DateTimeParseException("Unable to parse the date: " + text, text, -1);
    }

    /**
     * 支持日期、时间、时间日期格式转换成 Instant
     */
    private static final TemporalQuery INSTANT_QUERY = new TemporalQuery() {

        @Nullable
        @Override
        public Instant queryFrom(TemporalAccessor temporal) {
            if (temporal.isSupported(INSTANT_SECONDS) && temporal.isSupported(NANO_OF_SECOND)) {
                long instantSecs = temporal.getLong(INSTANT_SECONDS);
                int nanoOfSecond = temporal.get(NANO_OF_SECOND);
                return Instant.ofEpochSecond(instantSecs, nanoOfSecond);
            }
            // 获取时区
            ZoneId zoneId = temporal.query(TemporalQueries.zoneId());
            Objects.requireNonNull(zoneId, "Unable to obtain Instant from TemporalAccessor: zoneId is null.");
            if (temporal.isSupported(NANO_OF_DAY)) {
                return LocalTime.ofNanoOfDay(temporal.getLong(NANO_OF_DAY))
                        .atDate(DateUtil.EPOCH)
                        .atZone(zoneId)
                        .toInstant();
            } else if (temporal.isSupported(EPOCH_DAY)) {
                return LocalDate.ofEpochDay(temporal.getLong(EPOCH_DAY))
                        .atStartOfDay()
                        .atZone(zoneId)
                        .toInstant();
            }
            return null;
        }

        @Override
        public String toString() {
            return "Instant";
        }
    };

    /**
     * 兼容 java 8
     * 

* The epoch year {@code LocalDate}, '1970-01-01'. */ public static final LocalDate EPOCH = LocalDate.of(1970, 1, 1); public static TemporalQuery instantQuery() { return INSTANT_QUERY; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy