java 时间工具类


import com.sun.istack.internal.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.WordUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.ResolverStyle;
import java.time.temporal.*;
import java.util.*;
import java.util.stream.Stream;

/**
 * 时间工具类
 *
 * @author duanluan
 */
@Slf4j
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {

  private DateUtils() {
  }

  // region java.time 下的类相关使用
  public static final String PATTERN_UUUU_MM_DD_HH_MM_SS = "uuuu-MM-dd HH:mm:ss";
  public static final String PATTERN_UUUUMMDDHHMMSS = "uuuuMMddHHmmss";
  public static final String PATTERN_UUUU_MM_DD_HH_MM = "uuuu-MM-dd HH:mm";
  public static final String PATTERN_UUUU_MM_DD = "uuuu-MM-dd";
  public static final String PATTERN_UUUU_MM = "uuuu-MM";
  // endregion

  // region java.util.Date 相关使用
  public static final String PATTERN_YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
  public static final String PATTERN_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
  public static final String PATTERN_YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
  public static final String PATTERN_YYYY_MM_DD = "yyyy-MM-dd";
  public static final String PATTERN_YYYY_MM = "yyyy-MM";
  // endregion

  public static final String PATTERN_HH_MM_SS = "HH:mm:ss";
  public static final String PATTERN_HH_MM = "HH:mm";

  /**
   * 默认内容类型,比如月份是中文还是英文
   */
  private static final Locale DEFAULT_LOCALE;
  /**
   * 默认日期时间格式器
   */
  private static final DateTimeFormatter DEFAULT_DATE_TIME_FORMATTER;
  /**
   * 系统时区
   */
  public static final ZoneId SYSTEM_ZONE_ID;
  /**
   * 系统时区偏移
   */
  public static final ZoneOffset SYSTEM_ZONE_OFFSET;
  /**
   * 默认解析模式
   */
  public static final ResolverStyle DEFAULT_RESOLVER_STYLE;

  static {
    // 内容类型为英文
    DEFAULT_LOCALE = Locale.ENGLISH;
    // 默认时间格式:uuuu-MM-dd HH:mm:ss
    DEFAULT_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(PATTERN_UUUU_MM_DD_HH_MM_SS, DEFAULT_LOCALE);
    // 系统时区
    SYSTEM_ZONE_ID = ZoneId.systemDefault();
    // 系统时区偏移
    SYSTEM_ZONE_OFFSET = OffsetDateTime.now(SYSTEM_ZONE_ID).getOffset();
    // 解析模式为严格模式(https://rumenz.com/java-topic/java/date-time/resolverstyle-strict-date-parsing/index.html)
    DEFAULT_RESOLVER_STYLE = ResolverStyle.STRICT;
  }

  /**
   * Date 默认格式
   */
  public static String defaultDatePattern = PATTERN_YYYY_MM_DD_HH_MM_SS;
  /**
   * LocalDate 默认格式
   */
  public static String defaultLocalDatePattern = PATTERN_UUUU_MM_DD;
  /**
   * LocalDateTime 默认格式
   */
  public static String defaultLocalDateTimePattern = PATTERN_YYYY_MM_DD_HH_MM_SS;
  /**
   * LocalTime 默认格式
   */
  public static String defaultLocalTimePattern = PATTERN_HH_MM_SS;

  /**
   * 获取时间格式化构造器,并给不同时间级别赋默认值
   *
   * @param pattern       格式
   * @param fieldValueMap 时间类型和值
   * @return 时间格式构造器
   */
  public static DateTimeFormatterBuilder getFormatterBuilder(@NotNull String pattern, Map<TemporalField, Long> fieldValueMap) {
    // 根据格式创建时间格式化构造器
    DateTimeFormatterBuilder formatterBuilder = new DateTimeFormatterBuilder().appendPattern(pattern);

    // 如果格式中存在特定字符,则不赋默认值
    TemporalField maybeExistTemporalField = ChronoField.YEAR;
    if (!pattern.toLowerCase().contains("y") && fieldValueMap.containsKey(maybeExistTemporalField)) {
      formatterBuilder.parseDefaulting(maybeExistTemporalField, fieldValueMap.get(maybeExistTemporalField));
      fieldValueMap.remove(maybeExistTemporalField);
    }
    maybeExistTemporalField = ChronoField.MONTH_OF_YEAR;
    if (!pattern.contains("M") && !pattern.contains("L") && fieldValueMap.containsKey(maybeExistTemporalField)) {
      formatterBuilder.parseDefaulting(maybeExistTemporalField, fieldValueMap.get(maybeExistTemporalField));
      fieldValueMap.remove(maybeExistTemporalField);
    }
    maybeExistTemporalField = ChronoField.DAY_OF_MONTH;
    if (!pattern.toLowerCase().contains("d") && !pattern.contains("F") && fieldValueMap.containsKey(maybeExistTemporalField)) {
      formatterBuilder.parseDefaulting(maybeExistTemporalField, fieldValueMap.get(maybeExistTemporalField));
      fieldValueMap.remove(maybeExistTemporalField);
    }

    // 循环给不同时间级别赋默认值
    for (TemporalField temporalField : fieldValueMap.keySet()) {
      formatterBuilder.parseDefaulting(temporalField, fieldValueMap.get(temporalField));
    }
    return formatterBuilder;
  }

  /**
   * 获取默认的时间格式器,对应时间级别没有就赋默认值:1970-01-01 00:00:00.0
   *
   * @param pattern 格式
   * @param locale  区域
   * @param zoneId  时区
   * @return 时间格式器
   */
  public static DateTimeFormatter getDefaultFormatter(@NotNull String pattern, Locale locale, ZoneId zoneId) {
    Map<TemporalField, Long> fieldValueMap = new HashMap<>();
    fieldValueMap.put(ChronoField.YEAR, 1970L);
    fieldValueMap.put(ChronoField.MONTH_OF_YEAR, 1L);
    fieldValueMap.put(ChronoField.DAY_OF_MONTH, 1L);
    fieldValueMap.put(ChronoField.HOUR_OF_DAY, 0L);
    fieldValueMap.put(ChronoField.MINUTE_OF_HOUR, 0L);
    fieldValueMap.put(ChronoField.SECOND_OF_MINUTE, 0L);
    fieldValueMap.put(ChronoField.MILLI_OF_SECOND, 0L);
    DateTimeFormatter dateTimeFormatter;
    DateTimeFormatterBuilder formatterBuilder = getFormatterBuilder(pattern, fieldValueMap);
    if (locale != null) {
      dateTimeFormatter = formatterBuilder.toFormatter(locale);
    } else {
      dateTimeFormatter = formatterBuilder.toFormatter();
    }
    dateTimeFormatter.withResolverStyle(DEFAULT_RESOLVER_STYLE);
    if (zoneId != null) {
      dateTimeFormatter.withZone(zoneId);
    }
    return dateTimeFormatter;
  }

  /**
   * 获取默认的时间格式器,对应时间级别没有就赋默认值:1970-01-01 00:00:00.0
   *
   * @param pattern 格式
   * @param locale  区域
   * @return 时间格式器
   */
  public static DateTimeFormatter getDefaultFormatter(@NotNull String pattern, @NotNull Locale locale) {
    return getDefaultFormatter(pattern, locale, null);
  }

  /**
   * 获取默认的时间格式器,对应时间级别没有就赋默认值:1970-01-01 00:00:00.0
   *
   * @param pattern 格式
   * @param zoneId  时区
   * @return 时间格式器
   */
  public static DateTimeFormatter getDefaultFormatter(@NotNull String pattern, @NotNull ZoneId zoneId) {
    return getDefaultFormatter(pattern, null, zoneId);
  }

  /**
   * 获取默认的时间格式器,对应时间级别没有就赋默认值:1970-01-01 00:00:00.0,内容格式为英文
   *
   * @param pattern 格式
   * @return 时间格式器
   */
  public static DateTimeFormatter getDefaultFormatter(@NotNull String pattern) {
    return getDefaultFormatter(pattern, DEFAULT_LOCALE);
  }

  /**
   * 转换需要格式化的字符串,比如英文月份转换为首字母大写
   *
   * @param source  被转换的字符串
   * @param pattern 转换格式
   * @return 转换后的字符串
   */
  private static String convertByPattern(@NotNull String source, @NotNull String pattern) {
    // 如果格式为英文月份,转换字符串为首字母大写
    int mmmIndex = pattern.indexOf("MMM");
    if (mmmIndex != -1) {
      // 获取 MMM 对应在字符串的位置的内容
      String mmm = source.substring(mmmIndex, mmmIndex + 3);
      // 首字母大写
      source = source.replaceAll(mmm, WordUtils.capitalize(mmm.toLowerCase()));
    }
    return source;
  }

  /**
   * 格式化为指定格式的字符串
   *
   * @param date    时间对象
   * @param pattern 格式
   * @return 格式化后的字符串
   */
  public static String format(@NotNull Date date, @NotNull String pattern) {
    return new SimpleDateFormat(pattern).format(date);
  }

  /**
   * 格式化为 DateUtils#defaultDatePattern
   *
   * @param date
   * @return
   */
  public static String format(@NotNull Date date) {
    return format(date, defaultDatePattern);
  }

  /**
   * 格式化为指定格式的字符串
   *
   * @param temporal 时间对象
   * @param pattern  格式
   * @return 格式化后的字符串
   */
  public static String format(@NotNull Temporal temporal, @NotNull String pattern) {
    return getDefaultFormatter(pattern).format(temporal);
  }

  /**
   * 格式化为 DateUtils#defaultLocalDatePattern/defaultLocalDateTimePattern/defaultLocalTimePattern
   *
   * @param temporal 时间对象
   * @return 格式化后的字符串
   */
  public static String format(@NotNull Temporal temporal) {
    String pattern = null;
    if (temporal instanceof LocalDate) {
      pattern = defaultLocalDatePattern;
    } else if (temporal instanceof LocalDateTime) {
      pattern = defaultLocalDateTimePattern;
    } else if (temporal instanceof LocalTime) {
      pattern = defaultLocalTimePattern;
    }
    return format(temporal, pattern);
  }

  /**
   * 时间戳解析为 Date
   *
   * @param timeStamp 被解析的时间戳
   * @return Date 对象
   */
  public static Date parseDate(@NotNull long timeStamp) {
    return new Date(timeStamp);
  }

  /**
   * String 解析为 Date,根据被解析字符串的长度判断格式
   * <p>
   * 19:DateUtils#PATTERN_UUUU_MM_DD_HH_MM_SS<br>
   * 16:DateUtils#PATTERN_UUUU_MM_DD_HH_MM<br>
   * 10:DateUtils#PATTERN_UUUU_MM_DD<br>
   * 7:DateUtils#PATTERN_UUUU_MM<br>
   * 8:DateUtils#PATTERN_HH_MM_SS<br>
   * 5:DateUtils#PATTERN_HH_MM
   *
   * @param source 被解析的字符串
   * @return Date 对象
   */
  public static Date parseDate(@NotNull String source) {
    try {
      // 如果需要解析的字符串中含 - 或 :
      if (source.contains("-") || source.contains(":")) {
        String pattern = null;
        switch (source.length()) {
          case 19:
            pattern = PATTERN_UUUU_MM_DD_HH_MM_SS;
            break;
          case 16:
            pattern = PATTERN_UUUU_MM_DD_HH_MM;
            break;
          case 10:
            pattern = PATTERN_UUUU_MM_DD;
            break;
          case 7:
            pattern = PATTERN_UUUU_MM;
            break;
          case 8:
            pattern = PATTERN_HH_MM_SS;
            break;
          case 5:
            pattern = PATTERN_HH_MM;
            break;
          default:
        }
        if (pattern != null) {
          return new SimpleDateFormat(pattern).parse(source);
        }
      }
    } catch (ParseException e) {
      log.error(e.getMessage(), e);
      return null;
    }
    return null;
  }

  /**
   * 时间戳解析为 LocalDate
   *
   * @param timeStamp 被解析的时间戳
   * @param zoneId    时区
   * @return LocalDate 对象
   */
  public static LocalDate parseLocalDate(@NotNull long timeStamp, @NotNull ZoneId zoneId) {
    return Instant.ofEpochMilli(timeStamp).atZone(zoneId).toLocalDate();
  }

  /**
   * 时间戳解析为 LocalDate
   *
   * @param timeStamp 被解析的时间戳
   * @return LocalDate 对象
   */
  public static LocalDate parseLocalDate(@NotNull long timeStamp) {
    return parseLocalDate(timeStamp, SYSTEM_ZONE_ID);
  }

  /**
   * String 解析为 LocalDate
   *
   * @param source  被解析的字符串
   * @param pattern 格式
   * @param zoneId  时区
   * @return LocalDate 对象
   */
  public static LocalDate parseLocalDate(@NotNull String source, @NotNull String pattern, @NotNull ZoneId zoneId) {
    source = convertByPattern(source, pattern);
    return LocalDate.parse(source, getDefaultFormatter(pattern, zoneId));
  }

  /**
   * String 解析为 LocalDate
   *
   * @param source  被解析的字符串
   * @param pattern 格式
   * @return LocalDate 对象
   */
  public static LocalDate parseLocalDate(@NotNull String source, @NotNull String pattern) {
    return parseLocalDate(source, pattern, SYSTEM_ZONE_ID);
  }


  /**
   * String 解析为 LocalDate
   *
   * @param source   被解析的字符串
   * @param zoneId   时区
   * @param patterns 多钟格式
   * @return LocalDate 对象
   */
  public static LocalDate parseLocalDate(@NotNull String source, @NotNull ZoneId zoneId, @NotNull String... patterns) {
    LocalDate result = null;
    for (String pattern : patterns) {
      try {
        result = parseLocalDate(source, pattern, zoneId);
      } catch (Exception ignore) {
      }
    }
    return result;
  }

  /**
   * String 解析为 LocalDate
   *
   * @param source   被解析的字符串
   * @param patterns 多钟格式
   * @return LocalDate 对象
   */
  public static LocalDate parseLocalDate(@NotNull String source, @NotNull String... patterns) {
    LocalDate result = null;
    for (String pattern : patterns) {
      try {
        result = parseLocalDate(source, pattern);
      } catch (Exception ignore) {
      }
    }
    return result;
  }

  /**
   * String 解析为 LocalDate,根据被解析字符串的长度判断格式
   * <p>
   * 10:DateUtils#PATTERN_UUUU_MM_DD<br>
   * 7:DateUtils#PATTERN_UUUU_MM
   *
   * @param source 被解析的字符串
   * @return LocalDate 对象
   */
  public static LocalDate parseLocalDate(@NotNull String source) {
    int length = source.length();

    String pattern = null;
    if (source.contains("-") || source.contains(":")) {
      switch (length) {
        case 10:
          pattern = PATTERN_UUUU_MM_DD;
          break;
        case 7:
          pattern = PATTERN_UUUU_MM;
          break;
      }
      if (pattern != null) {
        return parseLocalDate(source, pattern);
      }
    }
    return null;
  }

  /**
   * 时间戳解析为 LocalDateTime
   *
   * @param timeStamp 被解析的时间戳
   * @param zoneId    时区
   * @return LocalDateTime 对象
   */
  public static LocalDateTime parseLocalDateTime(@NotNull long timeStamp, @NotNull ZoneId zoneId) {
    return Instant.ofEpochMilli(timeStamp).atZone(zoneId).toLocalDateTime();
  }

  /**
   * 时间戳解析为 LocalDateTime
   *
   * @param timeStamp 被解析的时间戳
   * @return LocalDateTime 对象
   */
  public static LocalDateTime parseLocalDateTime(@NotNull long timeStamp) {
    return parseLocalDateTime(timeStamp, SYSTEM_ZONE_ID);
  }

  /**
   * String 解析为 LocalDateTime
   *
   * @param source  被解析的字符串
   * @param pattern 格式
   * @param zoneId  时区
   * @return LocalDateTime 对象
   */
  public static LocalDateTime parseLocalDateTime(@NotNull String source, @NotNull String pattern, @NotNull ZoneId zoneId) {
    if (StringUtils.isBlank(source)) {
      return null;
    }
    source = convertByPattern(source, pattern);
    return LocalDateTime.parse(source, getDefaultFormatter(pattern, zoneId));
  }

  /**
   * String 解析为 LocalDateTime
   *
   * @param source  被解析的字符串
   * @param pattern 格式
   * @return LocalDateTime 对象
   */
  public static LocalDateTime parseLocalDateTime(@NotNull String source, @NotNull String pattern) {
    return parseLocalDateTime(source, pattern, SYSTEM_ZONE_ID);
  }

  /**
   * String 解析为 LocalDateTime
   *
   * @param source   被解析的字符串
   * @param zoneId   时区
   * @param patterns 多种格式
   * @return LocalDateTime 对象
   */
  public static LocalDateTime parseLocalDateTime(@NotNull String source, @NotNull ZoneId zoneId, @NotNull String... patterns) {
    LocalDateTime result = null;
    for (String pattern : patterns) {
      try {
        result = parseLocalDateTime(source, pattern, zoneId);
      } catch (Exception ignore) {
      }
    }
    return result;
  }

  /**
   * String 解析为 LocalDateTime
   *
   * @param source   被解析的字符串
   * @param patterns 多种格式
   * @return LocalDateTime 对象
   */
  public static LocalDateTime parseLocalDateTime(@NotNull String source, @NotNull String... patterns) {
    LocalDateTime result = null;
    for (String pattern : patterns) {
      try {
        result = parseLocalDateTime(source, pattern);
      } catch (Exception ignore) {
      }
    }
    return result;
  }

  /**
   * String 解析为 LocalDateTime,根据被解析字符串的长度判断格式
   * <p>
   * 19:DateUtils#PATTERN_UUUU_MM_DD_HH_MM_SS<br>
   * 16:DateUtils#PATTERN_UUUU_MM_DD_HH_MM<br>
   * 10:DateUtils#PATTERN_UUUU_MM_DD<br>
   * 7:DateUtils#PATTERN_UUUU_MM<br>
   * 8:DateUtils#PATTERN_HH_MM_SS<br>
   * 5:DateUtils#PATTERN_HH_MM
   *
   * @param source 被解析的字符串
   * @return LocalDateTime 对象
   */
  public static LocalDateTime parseLocalDateTime(@NotNull String source) {
    String pattern = null;
    if (source.contains("-") || source.contains(":")) {
      switch (source.length()) {
        case 19:
          pattern = PATTERN_UUUU_MM_DD_HH_MM_SS;
          break;
        case 16:
          pattern = PATTERN_UUUU_MM_DD_HH_MM;
          break;
        case 10:
          pattern = PATTERN_UUUU_MM_DD;
          break;
        case 7:
          pattern = PATTERN_UUUU_MM;
          break;
        case 8:
          pattern = PATTERN_HH_MM_SS;
          break;
        case 5:
          pattern = PATTERN_HH_MM;
          break;
        default:
      }
      if (pattern != null) {
        return parseLocalDateTime(source, pattern);
      }
    }
    return null;
  }

  /**
   * 时间戳解析为 LocalTime
   *
   * @param timeStamp 被解析的时间戳
   * @param zoneId    时区
   * @return LocalTime 对象
   */
  public static LocalTime parseLocalTime(@NotNull long timeStamp, @NotNull ZoneId zoneId) {
    return Instant.ofEpochMilli(timeStamp).atZone(zoneId).toLocalTime();
  }

  /**
   * 时间戳解析为 LocalTime
   *
   * @param timeStamp 被解析的时间戳
   * @return LocalTime 对象
   */
  public static LocalTime parseLocalTime(@NotNull long timeStamp) {
    return parseLocalTime(timeStamp, SYSTEM_ZONE_ID);
  }

  /**
   * String 解析为 LocalTime
   *
   * @param source  被解析的字符串
   * @param pattern 格式
   * @param zoneId  时区
   * @return LocalTime 对象
   */
  public static LocalTime parseLocalTime(@NotNull String source, @NotNull String pattern, @NotNull ZoneId zoneId) {
    if (StringUtils.isBlank(source)) {
      return null;
    }
    source = convertByPattern(source, pattern);
    return LocalTime.parse(source, getDefaultFormatter(pattern, zoneId));
  }

  /**
   * String 解析为 LocalTime
   *
   * @param source  被解析的字符串
   * @param pattern 格式
   * @return LocalTime 对象
   */
  public static LocalTime parseLocalTime(@NotNull String source, @NotNull String pattern) {
    return parseLocalTime(source, pattern, SYSTEM_ZONE_ID);
  }

  /**
   * String 解析为 LocalTime
   *
   * @param source   被解析的字符串
   * @param zoneId   时区
   * @param patterns 多种格式
   * @return LocalTime 对象
   */
  public static LocalTime parseLocalTime(@NotNull String source, @NotNull ZoneId zoneId, @NotNull String... patterns) {
    LocalTime result = null;
    for (String pattern : patterns) {
      try {
        result = parseLocalTime(source, pattern, zoneId);
      } catch (Exception ignore) {
      }
    }
    return result;
  }

  /**
   * String 解析为 LocalTime
   *
   * @param source   被解析的字符串
   * @param patterns 多种格式
   * @return LocalTime 对象
   */
  public static LocalTime parseLocalTime(@NotNull String source, @NotNull String... patterns) {
    LocalTime result = null;
    for (String pattern : patterns) {
      try {
        result = parseLocalTime(source, pattern);
      } catch (Exception ignore) {
      }
    }
    return result;
  }

  /**
   * String 解析为 LocalTime,根据被解析字符串的长度判断格式
   * <p>
   * 8:DateUtils#PATTERN_HH_MM_SS<br>
   * 5:DateUtils#PATTERN_HH_MM
   *
   * @param source 被解析的字符串
   * @return LocalTime 对象
   */
  public static LocalTime parseLocalTime(@NotNull String source) {
    String pattern = null;
    if (source.contains("-") || source.contains(":")) {
      switch (source.length()) {
        case 8:
          pattern = PATTERN_HH_MM_SS;
          break;
        case 5:
          pattern = PATTERN_HH_MM;
          break;
        default:
      }
      if (pattern != null) {
        return parseLocalTime(source, pattern);
      }
    }
    return null;
  }

  /**
   * java.util.time 对象 转 Date
   *
   * @param temporal 时间对象
   * @return Date 对象
   */
  public static Date toDate(@NotNull Temporal temporal) {
    if (temporal instanceof LocalDate) {
      return Date.from(((LocalDate) temporal).atStartOfDay().atZone(SYSTEM_ZONE_ID).toInstant());
    } else if (temporal instanceof LocalDateTime) {
      return Date.from(((LocalDateTime) temporal).atZone(SYSTEM_ZONE_ID).toInstant());
    } else if (temporal instanceof LocalTime) {
      return Date.from(minLocalDateTime(temporal).atZone(SYSTEM_ZONE_ID).toInstant());
    }
    return null;
  }

  /**
   * Date 转 LocalDate
   *
   * @param date Date 对象
   * @return LocalDate 对象
   */
  public static LocalDate toLocalDate(@NotNull Date date) {
    return parseLocalDate(date.getTime());
  }

  /**
   * Date 转 LocalDateTime
   *
   * @param date Date 对象
   * @return LocalDateTime 对象
   */
  public static LocalDateTime toLocalDateTime(@NotNull Date date) {
    return parseLocalDateTime(date.getTime());
  }

  /**
   * Date 转 LocalTime
   *
   * @param date Date 对象
   * @return LocalTime 对象
   */
  public static LocalTime toLocalTime(@NotNull Date date) {
    return parseLocalTime(date.getTime());
  }

  /**
   * 最小时间:1970-01-01 00:00:00.0
   *
   * @return LocalDateTime 对象
   */
  public static LocalDateTime minLocalDateTime(@NotNull Temporal temporal) {
    if (temporal instanceof LocalDateTime) {
      return (LocalDateTime) temporal;
    }
    LocalDateTime localDateTime = LocalDateTime.now();
    if (temporal instanceof LocalDate) {
      localDateTime.with(ChronoField.YEAR, ((LocalDate) temporal).getYear());
      localDateTime.with(ChronoField.MONTH_OF_YEAR, ((LocalDate) temporal).getMonthValue());
      localDateTime.with(ChronoField.DAY_OF_MONTH, ((LocalDate) temporal).getDayOfMonth());
    } else {
      localDateTime.with(ChronoField.YEAR, 1970);
      localDateTime.with(ChronoField.MONTH_OF_YEAR, 1);
      localDateTime.with(ChronoField.DAY_OF_MONTH, 1);
    }
    if (temporal instanceof LocalTime) {
      localDateTime.with(ChronoField.HOUR_OF_DAY, ((LocalTime) temporal).getHour());
      localDateTime.with(ChronoField.MINUTE_OF_HOUR, ((LocalTime) temporal).getMinute());
      localDateTime.with(ChronoField.SECOND_OF_MINUTE, ((LocalTime) temporal).getSecond());
      localDateTime.with(ChronoField.MILLI_OF_SECOND, temporal.getLong(ChronoField.MILLI_OF_SECOND));
    } else {
      localDateTime.with(ChronoField.HOUR_OF_DAY, 0);
      localDateTime.with(ChronoField.MINUTE_OF_HOUR, 0);
      localDateTime.with(ChronoField.SECOND_OF_MINUTE, 0);
      localDateTime.with(ChronoField.MILLI_OF_SECOND, 0);
    }
    return localDateTime;
  }

  /**
   * 最小时间:1970-01-01 00:00:00.0
   *
   * @return LocalDateTime 对象
   */
  public static LocalDateTime minLocalDateTime() {
    LocalDateTime localDateTime = LocalDateTime.now();
    localDateTime.with(ChronoField.YEAR, 1970);
    localDateTime.with(ChronoField.MONTH_OF_YEAR, 1);
    localDateTime.with(ChronoField.DAY_OF_MONTH, 1);
    localDateTime.with(ChronoField.HOUR_OF_DAY, 0);
    localDateTime.with(ChronoField.MINUTE_OF_HOUR, 0);
    localDateTime.with(ChronoField.SECOND_OF_MINUTE, 0);
    localDateTime.with(ChronoField.MILLI_OF_SECOND, 0);
    return localDateTime;
  }

  /**
   * 转换时区
   *
   * @param localDate 被转换时区的 LocalDate 对象
   * @param oldZoneId 旧时区
   * @param newZoneId 新时区
   * @return 转换时区后的 LocalDate 对象
   */
  public static LocalDate withZoneInstant(@NotNull LocalDate localDate, @NotNull ZoneId oldZoneId, @NotNull ZoneId newZoneId) {
    return localDate.atStartOfDay().atZone(oldZoneId).withZoneSameInstant(newZoneId).toLocalDate();
  }

  /**
   * 转换时区
   *
   * @param localDateTime 被转换时区的 LocalDateTime 对象
   * @param oldZoneId     旧时区
   * @param newZoneId     新时区
   * @return 转换时区后的 LocalDateTime 对象
   */
  public static LocalDateTime withZoneInstant(@NotNull LocalDateTime localDateTime, @NotNull ZoneId oldZoneId, @NotNull ZoneId newZoneId) {
    return localDateTime.atZone(oldZoneId).withZoneSameInstant(newZoneId).toLocalDateTime();
  }

  /**
   * 转换时区
   *
   * @param localTime 被转换时区的 LocalTime 对象
   * @param oldZoneId 旧时区
   * @param newZoneId 新时区
   * @return 转换时区后的 LocalTime 对象
   */
  public static LocalTime withZoneInstant(@NotNull LocalTime localTime, @NotNull ZoneId oldZoneId, @NotNull ZoneId newZoneId) {
    return minLocalDateTime(localTime).atZone(oldZoneId).withZoneSameInstant(newZoneId).toLocalTime();
  }

  /**
   * 当前时间字符串
   *
   * @return 当前时间字符串
   */
  public static String now() {
    return format(new Date());
  }

  /**
   * 当前时间字符串
   *
   * @param zoneId 时区
   * @return 当前时间字符串
   */
  public static String now(@NotNull ZoneId zoneId) {
    return format(LocalDateTime.now().atZone(zoneId));
  }

  /**
   * 今天开始时间
   *
   * @return LocalDateTime 对象
   */
  public static LocalDateTime todayMinDateTime() {
    return LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
  }

  /**
   * 今天开始时间
   *
   * @param zoneId 时区
   * @return LocalDateTime 对象
   */
  public static LocalDateTime todayMinDateTime(@NotNull ZoneId zoneId) {
    return todayMinDateTime().atZone(zoneId).toLocalDateTime();
  }

  /**
   * 今天开始时间
   *
   * @return LocalTime 对象
   */
  public static LocalTime todayMinTime() {
    return todayMinDateTime().toLocalTime();
  }

  /**
   * 今天开始时间
   *
   * @param zoneId 时区
   * @return LocalTime 对象
   */
  public static LocalTime todayMinTime(@NotNull ZoneId zoneId) {
    return todayMinDateTime(zoneId).toLocalTime();
  }

  /**
   * 获取今天开始时间
   *
   * @return 今天开始时间字符串
   */
  public static String todayMinStr(@NotNull String pattern) {
    return format(LocalDateTime.of(LocalDate.now(), LocalTime.MIN), pattern);
  }

  /**
   * 获取今天开始时间
   *
   * @return 今天开始时间字符串
   */
  public static String todayMinStr() {
    return format(LocalDateTime.of(LocalDate.now(), LocalTime.MIN), defaultLocalTimePattern);
  }

  /**
   * 今天结束时间
   *
   * @return LocalDateTime 对象
   */
  public static LocalDateTime todayMaxDateTime() {
    return LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
  }

  /**
   * 今天结束时间
   *
   * @param zoneId 时区
   * @return LocalDateTime 对象
   */
  public static LocalDateTime todayMaxDateTime(@NotNull ZoneId zoneId) {
    return todayMaxDateTime().atZone(zoneId).toLocalDateTime();
  }

  /**
   * 今天结束时间
   *
   * @return LocalTime 对象
   */
  public static LocalTime todayMaxTime() {
    return todayMaxDateTime().toLocalTime();
  }

  /**
   * 今天结束时间
   *
   * @param zoneId 时区
   * @return LocalTime 对象
   */
  public static LocalTime todayMaxTime(@NotNull ZoneId zoneId) {
    return todayMaxDateTime(zoneId).toLocalTime();
  }

  /**
   * 获取今天结束时间字符串
   *
   * @return 今天开始时间字符串
   */
  public static String todayMaxStr(@NotNull String pattern) {
    return format(LocalDateTime.of(LocalDate.now(), LocalTime.MAX), pattern);
  }

  /**
   * 获取今天结束时间字符串
   *
   * @return 今天开始时间字符串
   */
  public static String todayMaxStr() {
    return format(LocalDateTime.of(LocalDate.now(), LocalTime.MAX), defaultLocalTimePattern);
  }

  /**
   * 获取减去或加上指定类型数量的时间
   *
   * @param temporal        被加减的时间
   * @param augendOrMinuend 数量
   * @param chronoUnit      时间类型
   * @return 加减后的时间
   */
  public static <T extends Temporal> T plusOrMinus(@NotNull T temporal, @NotNull long augendOrMinuend, ChronoUnit chronoUnit) {
    if (chronoUnit == null) {
      chronoUnit = ChronoUnit.MILLIS;
    }
    if (augendOrMinuend < 0) {
      return (T) temporal.minus(Math.abs(augendOrMinuend), chronoUnit);
    } else if (augendOrMinuend > 0) {
      return (T) temporal.plus(augendOrMinuend, chronoUnit);
    }
    return temporal;
  }

  // region 交集差集并集

  /**
   * 两个时间段是否交集
   *
   * @param x1 时间段 1 开始时间
   * @param y1 时间段 1 结束时间
   * @param x2 时间段 2 开始时间
   * @param y2 时间段 2 结束时间
   * @return 是否交集
   */
  public static boolean isIntersection(@NotNull LocalDateTime x1, @NotNull LocalDateTime y1, @NotNull LocalDateTime x2, @NotNull LocalDateTime y2) {
    return !(y1.isBefore(x2) || y2.isBefore(x1));
  }

  /**
   * 获取两个时间段的交集
   *
   * @param x1 时间段 1 开始时间
   * @param y1 时间段 1 结束时间
   * @param x2 时间段 2 开始时间
   * @param y2 时间段 2 结束时间
   * @return 交集
   */
  public static LocalDateTime[] getIntersection(@NotNull LocalDateTime x1, @NotNull LocalDateTime y1, @NotNull LocalDateTime x2, @NotNull LocalDateTime y2) {
    if (!isIntersection(x1, y1, x2, y2)) {
      return null;
    }

    LocalDateTime[] result = new LocalDateTime[2];
    if (x1.isBefore(x2) || x1.isEqual(x2)) {
      result[0] = x2;
    } else if (x1.isAfter(x2)) {
      result[0] = x1;
    }
    if (y1.isBefore(y2) || y1.isEqual(y2)) {
      result[1] = y1;
    } else if (y1.isAfter(y2)) {
      result[1] = y2;
    }
    return result;
  }

  /**
   * 获取两个时间段交集时差集的时间段
   *
   * @param x1 时间段 1 开始时间
   * @param y1 时间段 1 结束时间
   * @param x2 时间段 2 开始时间
   * @param y2 时间段 2 结束时间
   * @return 差集
   */
  public static List<LocalDateTime[]> getDifferenceSetsByIntersectional(@NotNull LocalDateTime x1, @NotNull LocalDateTime y1, @NotNull LocalDateTime x2, @NotNull LocalDateTime y2) {
    // 交集的部分
    LocalDateTime[] intersections = getIntersection(x1, y1, x2, y2);
    if (intersections == null || intersections.length == 0) {
      return null;
    }

    // 获取差集
    List<LocalDateTime[]> result = new ArrayList<>();
    if (x1.isBefore(x2)) {
      result.add(new LocalDateTime[]{x1, x2});
    } else if (x1.isAfter(x2)) {
      result.add(new LocalDateTime[]{x2, x1});
    }
    if (y1.isBefore(y2)) {
      result.add(new LocalDateTime[]{y1, y2});
    } else if (y1.isAfter(y2)) {
      result.add(new LocalDateTime[]{y2, y1});
    }

    for (Iterator<LocalDateTime[]> iterator = result.iterator(); iterator.hasNext(); ) {
      LocalDateTime[] localDateTimes = iterator.next();

      // 如果差集的开始时间和交集的结束时间相等,开始时间 += 1
      if (localDateTimes[0].equals(intersections[1])) {
        localDateTimes[0] = plusOrMinus(localDateTimes[0], 1, ChronoUnit.DAYS);
      }
      // 如果差集的结束时间和交集的开始时间相等,结束时间 -= 1
      if (localDateTimes[1].equals(intersections[0])) {
        localDateTimes[1] = plusOrMinus(localDateTimes[1], -1, ChronoUnit.DAYS);
      }

      // 如果开始时间小于结束时间,删除这段时间
      if (localDateTimes[1].isBefore(localDateTimes[0])) {
        iterator.remove();
      }
    }
    return result;
  }
  // endregion 交集差集并集


  /**
   * 转换星期字符串为星期数组
   *
   * @param weeks      星期字符串
   * @param splitRegex 星期分隔符
   * @return 星期数组
   */
  public static String[] convertWeeks(@NotNull String weeks, @NotNull String splitRegex) {
    // 去除星期字符串中除了 1-7 和 , 之外的字符
    if (RegExUtils.isMatchedByGroup0("[^,1-7]*", weeks)) {
      weeks = weeks.replaceAll("[^,1-7]*", "");
    }
    if (StringUtils.isBlank(weeks)) {
      return new String[]{};
    }
    return weeks.split(splitRegex);
  }

  /**
   * 转换星期字符串为星期数组
   *
   * @param weeks 星期字符串
   * @return 星期数组
   */
  public static String[] convertWeeks(@NotNull String weeks) {
    String regex = ",";
    if (!weeks.contains(regex)) {
      regex = "";
    }
    return convertWeeks(weeks, regex);
  }

  /**
   * 获取符合周几的时间
   *
   * @param times 时间
   * @param weeks 周几,逗号或者无分隔,1 代表周一
   * @return 符合周几的时间
   */
  public static List<LocalDateTime> getByWeeks(@NotNull String weeks, @NotNull LocalDateTime... times) {
    List<LocalDateTime> timeList = null;
    if (!CollectionUtils.sizeIsEmpty(times)) {
      List<String> weekList = Arrays.asList(convertWeeks(weeks));
      timeList = new ArrayList<>(Arrays.asList(times));
      // 周几中不包含就去除
      timeList.removeIf(time -> !weekList.contains(String.valueOf(time.getDayOfWeek().getValue())));
    }
    return timeList;
  }

  /**
   * 获取日期范围内的所有日期
   *
   * @param startTime 开始时间
   * @param endTime   结束时间
   * @param pattern   结果集元素格式
   * @return 日期范围内的所有日期
   */
  public static List<String> getByRange(@NotNull LocalDateTime startTime, @NotNull LocalDateTime endTime, @NotNull String pattern) {
    List<String> result = new ArrayList<>();
    long distance = ChronoUnit.DAYS.between(startTime, endTime);
    if (distance >= 1) {
      Stream.iterate(startTime, day -> day.plusDays(1)).limit(distance + 1).forEach(f -> result.add(format(f, pattern)));
    }
    return result;
  }

  /**
   * 获取日期范围内的所有指定星期,包含开始日期和结束日期
   *
   * @param weeks   周几,逗号或者无分隔,1 代表周一
   * @param pattern 结果集元素的格式
   * @return 所有指定星期的天集合
   */
  public static List<String> getByRangeAndWeeks(@NotNull LocalDateTime startTime, @NotNull LocalDateTime endTime, @NotNull String weeks, @NotNull String pattern) {
    List<String> result = new ArrayList<>();
    // 设置一周的开始为周一
    TemporalField field = WeekFields.of(DayOfWeek.of(1), 1).dayOfWeek();
    LocalDateTime dayByWeek;
    for (String week : convertWeeks(weeks)) {
      // 根据开始时间找到所在周对应星期的天
      dayByWeek = startTime.with(field, Long.parseLong(week));
      // 如果所在周对应星期的天 < 开始时间
      if (dayByWeek.isBefore(startTime)) {
        // 所在周对应星期的天 += 1 周
        dayByWeek = dayByWeek.plusWeeks(1);
      }
      // 循环:所在周对应星期的天 < 结束时间 或 所在周对应星期的天 == 结束时间
      while (dayByWeek.isBefore(endTime) || dayByWeek.isEqual(endTime)) {
        // 此天添加到结果集合中
        result.add(format(dayByWeek, pattern));
        // 所在周对应星期的天 += 1 周
        dayByWeek = dayByWeek.plusWeeks(1);
      }
    }
    return result;
  }

  /**
   * 获取日期范围内的所有指定星期,包含开始日期和结束日期
   *
   * @param weeks 周几,逗号或者无分隔,1 代表周一
   * @return 所有指定星期的天集合
   */
  public static List<LocalDateTime> getByRangeAndWeeks(@NotNull LocalDateTime startTime, @NotNull LocalDateTime endTime, @NotNull String weeks) {
    List<LocalDateTime> result = new ArrayList<>();
    TemporalField field = WeekFields.of(DayOfWeek.of(1), 1).dayOfWeek();
    LocalDateTime tempDay;
    for (String week : convertWeeks(weeks)) {
      tempDay = startTime.with(field, Long.parseLong(week));
      if (tempDay.isBefore(startTime)) {
        tempDay = tempDay.plusWeeks(1);
      }
      while (tempDay.isBefore(endTime) || tempDay.isEqual(endTime)) {
        result.add(tempDay);
        tempDay = tempDay.plusWeeks(1);
      }
    }
    return result;
  }
}


import org.apache.commons.lang3.time.DateFormatUtils;

import java.lang.management.ManagementFactory;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

/**
 * 时间工具类
 *
 * @author zhupeng
 * @version 1.2
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {


    public static String YYYY = "yyyy";

    public static String YYYY_MM = "yyyy-MM";

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

    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static String YYYYMMDDHHMM = "yyyyMMddHHmm";

    public static String YYYY_P_MMDD_P_HHMM = "yyyy.MMdd.HHmm";

    public static String YYYYMMDD = "yyyyMMdd";

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

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

    public static String YEAR_MONTH_DAY_REGEX = "^([1-9]\\d{3}年)(([0]{0,1}[1-9]月)|([1][0-2]月))(([0]{0,1}[1-9]日)|([1-2][0-9]日)|([3][0-2]日))$";

    public static String YEAR_MONTH_DAY_REGEX_CUSTOM = "^([1-9]\\d{3}/)(([0]{0,1}[1-9]/)|([1][0-2]/))(([0]{0,1}[1-9])|([1-2][0-9])|([3][0-2]))$";

    public static String YYYYMMDDHHMM_REGEX = "^([1-9]\\d{3})(([0]{0,1}[1-9])|([1][0-2]))(([0]{0,1}[1-9])|([1-2][0-9])|([3][0-2]))[0-6][0-9][0-6][0-9]$";

    public static SimpleDateFormat sdfOfYYYY_MM_DD = new SimpleDateFormat("yyyy年MM月dd日");

    public static SimpleDateFormat sdfOfYYYYMMDD = new SimpleDateFormat(YYYYMMDD);

    public static SimpleDateFormat sdfOfYYYYMMDDHHMM = new SimpleDateFormat(YYYYMMDDHHMM);

    public static SimpleDateFormat sdfOfYYYY_MM_DD_HH_MM_SS = new SimpleDateFormat(YYYY_MM_DD_HH_MM_SS);

    //科学计数法正则
    public static String scientific = "^((-?\\d+.?\\d*)[Ee]{1}(-?\\d+))$";

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

    public final static String[] REPLACE_STRING = new String[]{"GMT+0800", "GMT+08:00"};

    public final static String SPLIT_STRING = "(中国标准时间)";

    private static String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", "yyyy-MM-dd HH",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy/MM/dd HH",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM", "yyyy.MM.dd HH",
            "yyyyMMddHHmm", "yyyyMMdd"};



    /**
     * 获取当前Date型日期
     *
     * @return Date() 当前日期
     */
    public static Date getNowDate() {
        return new Date();
    }

    /**
     * 获取当前日期, 默认格式为yyyy-MM-dd
     *
     * @return String
     */
    public static String getYear() {
        return dateTimeNow(YYYY);
    }

    public static String getYearMonth() {
        return dateTimeNow(YYYY_MM);
    }

    public static String getMonth() {
        return dateTimeNow("MM");
    }

    public static String getDate() {
        return dateTimeNow(YYYY_MM_DD);
    }


    public static String getDateYMDHS() {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }

    public static final String getTime() {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }

    public static final String dateTimeNow() {
        return dateTimeNow(YYYYMMDDHHMMSS);
    }

    public static final String dateTimeNow(final String format) {
        return parseDateToStr(format, new Date());
    }

    public static final String dateTime(final Date date) {
        return parseDateToStr(YYYY_MM_DD, date);
    }

    public static final String parseDateToStr(final String format, final Date date) {
        return new SimpleDateFormat(format).format(date);
    }

    public static String currentTimeMillis() {
        return parseDateToStr("yyyy-MM-dd HH:mm:ss:SSS", new Date());
    }

    public static final Date dateTime(final String format, final String ts) {
        try {
            return new SimpleDateFormat(format).parse(ts);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 日期路径 即年/月/日 如20180808
     */
    public static final String dateTime() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }

    /**
     * 日期型字符串转化为日期 格式
     */
    public static Date parseDate(Object str) {
        if (str == null) {
            return null;
        }
        try {
            return parseDate(str.toString(), parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 获取服务器启动时间
     */
    public static Date getServerStartDate() {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * 计算两个date的时间差
     */
    public static Long getDatePoor(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        long sec = diff / ns;
        return sec;
    }

    /**
     * 计算两个date的时间差
     */
    public static Long getStringPoor(String endDate, String nowDate) {
        return getDatePoor(parseDate(endDate), parseDate(nowDate));
    }

    /**
     * 计算两个date的小时差
     */
    public static Integer getHourPoor(String endDate, String nowDate) {
        Long sec = getDatePoor(parseDate(endDate), parseDate(nowDate));
        return Integer.valueOf(String.valueOf(sec / 60 / 60));
    }

    /**
     * 计算两个date的小时差
     */
    public static Integer getDaysPoor(String endDate, String nowDate) {
        Long sec = getDatePoor(parseDate(endDate), parseDate(nowDate));
        return Integer.valueOf(String.valueOf(sec / 60 / 60 / 24));
    }


    /**
     * 获得计算偏移量后的时间
     *
     * @param disposeDate 计算时间
     * @param vsp         变化值(秒)
     * @return 偏移后的时间
     */
    public static Date getDateRangeBySeconds(String disposeDate, Integer vsp) {
        try {
            Date date = parseDate(disposeDate);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.SECOND, vsp);
            return calendar.getTime();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获得计算偏移量后的时间
     *
     * @param disposeDate 计算时间
     * @param vsp         变化值(秒)
     * @return 偏移后的时间
     */
    public static Date getDateRangeByMinutes(String disposeDate, Integer vsp) {
        try {
            Date date = parseDate(disposeDate);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            calendar.add(Calendar.MINUTE, vsp);
            return calendar.getTime();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获得7天前的时间
     *
     * @return String yyyy-MM-dd HH:mm:ss
     */
    public static String getSevenDateAgo() {
        Integer seconds = 7 * 24 * 60 * 60;
        String date = parseDateToStr(YYYY_MM_DD, new Date());
        return parseDateToStr(YYYY_MM_DD_HH_MM_SS, getDateRangeBySeconds(date, 0 - seconds));
    }


    /**
     * 计算两个date的时间差
     */
    public static Long getStringHours(String endDate, String nowDate) {
        return getDateHours(parseDate(endDate), parseDate(nowDate));
    }

    /**
     * 计算两个date的时间差  :  小时
     */
    public static Long getDateHours(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        long ns = 1000;
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        long sec = diff / ns;
        return hour;
    }

    /**
     * 计算两个date的时间差 获得秒数
     */
    public static Long getDifferenceSeconds(String date1, String date2) {
        long ns = 1000;
        long diff = parseDate(date1).getTime() - parseDate(date2).getTime();
        // 获得绝对值
        diff = Math.abs(diff);
        // 计算差多少秒//输出结果
        long sec = diff / ns;
        return sec;
    }

    /**
     * 获取两个时间相差的天数
     *
     * @param date1
     * @param date2
     * @param format
     * @return
     */
    public static long dayDiff(String date1, String date2, String format) {
        SimpleDateFormat formater = new SimpleDateFormat(format);
        long diff = 0L;
        try {
            long d1 = formater.parse(date1).getTime();
            long d2 = formater.parse(date2).getTime();
            //diff=(Math.abs(d1-d2) / (1000 * 60 * 60 * 24));
            diff = (d1 - d2) / (1000 * 60 * 60 * 24);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return diff;
    }

    /**
     * 获取xx天前的日期
     *
     * @return
     */
    public static String getToDay(int num) {
        //获取对日期操作的类对象
        Calendar calendar1 = Calendar.getInstance();
        //在当前时间的基础上获取前三天的日期
        calendar1.add(Calendar.DATE, num);
        Date today = calendar1.getTime();
        return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, today);
    }

    /**
     * date 转 string   yyyy-MM-dd
     *
     * @param date
     * @return
     */
    public static String dateForStr(String date) {
        try {
            SimpleDateFormat inSDF = new SimpleDateFormat("yyyy-MM-dd");
            Date inDate = inSDF.parse(date);
            date = inSDF.format(inDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }

    /**
     * date 转 string   yyyyMMddHHmm
     *
     * @param date
     * @return
     */
    public static String dateToString(String date) {
        try {
            SimpleDateFormat inSDF = new SimpleDateFormat("yyyyMMddHHmm");
            Date inDate = inSDF.parse(date);
            date = inSDF.format(inDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }


    /**
     * date -> string
     *
     * @param time
     * @return
     */
    public static String dateToString(Date time) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");//注意月份是MM
        return simpleDateFormat.format(time);
    }

    /**
     * 日期加一天
     *
     * @param time
     * @return
     */
    public static String dateAddOne(String time) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        try {
            Date dd = df.parse(time);
            calendar.setTime(dd);
            //加一天
            calendar.add(Calendar.DAY_OF_MONTH, 1);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return df.format(calendar.getTime());
    }


    /**
     * 日期加一天
     *
     * @param time
     * @return
     */
    public static String dateAddOneNoHms(String time) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        try {
            Date dd = df.parse(time);
            calendar.setTime(dd);
            //加一天
            calendar.add(Calendar.DAY_OF_MONTH, 1);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return df.format(calendar.getTime());
    }


    /**
     * 小时加8
     *
     * @param time
     * @return
     */
    public static String hourAdd8(String time) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        try {
            Date dd = df.parse(time);
            calendar.setTime(dd);
            //加8小时
            calendar.add(Calendar.HOUR, 8);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return df.format(calendar.getTime());
    }


    /**
     * 日期减一
     *
     * @param time
     * @return
     */
    public static String dateDeleteOne(String time) {
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Date date = new Date();
        try {
            //减一天
            long dif = df.parse(time).getTime() - 86400 * 1000;
            date.setTime(dif);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return df.format(date);
    }

    /**
     * utc(不限格式) -> pek(yyyyMMddHHmm)
     *
     * @param time
     * @return
     */
    public static String utcToPek(String time) {
        try {
            Calendar calendar = Calendar.getInstance();
            Date dd = parseDate(time);
            calendar.setTime(dd);
            //加8小时
            calendar.add(Calendar.HOUR, 8);
            return parseDateToStr(YYYYMMDDHHMM, calendar.getTime());
        } catch (Exception e) {
            return SysConstants.STRING_VACANCY;
        }
    }

    /**
     * pek -> utc
     *
     * @param time
     * @return
     */
    public static String pekToUtc(String time) {
        Calendar calendar = Calendar.getInstance();
        Date dd = parseDate(time);
        calendar.setTime(dd);
        //加8小时
        calendar.add(Calendar.HOUR, -8);
        return parseDateToStr(YYYYMMDDHHMM, calendar.getTime());
    }

    /**
     * 根据传输时间 以及需要增加的时间(小时)返回最终和(yyyyMMddHHmm)
     *
     * @param time
     * @return
     */
    public static String addTime(String time, Integer vsp) {
        Calendar calendar = Calendar.getInstance();
        Date dd = parseDate(time);
        calendar.setTime(dd);
        // 求和
        calendar.add(Calendar.HOUR, vsp);
        return parseDateToStr(YYYYMMDDHHMM, calendar.getTime());
    }


    /**
     * 根据日期加几分钟
     *
     * @param date
     * @param minute
     * @return
     */
    public static Date addMinute(Date date, int minute) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, minute);
        return calendar.getTime();
    }


    /**
     * 功能描述: <br>
     * 〈判断某一个日期是否在俩个日期之间〉
     *
     * @param starDate
     * @param endDate
     * @param compareDate
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static int betweenAndDate(Date starDate, Date endDate, Date compareDate) {
        //传入待比较时间大于开始时间且小于结束时间
        if (starDate.getTime() <= compareDate.getTime() && compareDate.getTime() <= endDate.getTime()) {
            return 1;
        } else {
            return -1;
        }

    }

    // 返回时间格式如:2020-02-17 00:00:00(开始)
    public static String getStartOfDay(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
    }

    // 返回时间格式如:2020-02-19 23:59:59(结束)
    public static String getEndOfDay(Date time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(calendar.getTime());
    }


    /**
     * 判断两段时间是否存在交集
     *
     * @param startDate1 开始1
     * @param endDate1   结束1
     * @param startDate2 开始2
     * @param endDate2   结束2
     * @return boolean true有交集 false无交集
     */
    public static boolean isOverlap(String startDate1, String endDate1, String startDate2, String endDate2) {
        Date leftStartDate = null;
        Date leftEndDate = null;
        Date rightStartDate = null;
        Date rightEndDate = null;
        try {
            leftStartDate = parseDate(startDate1);
            leftEndDate = parseDate(endDate1);
            rightStartDate = parseDate(startDate2);
            rightEndDate = parseDate(endDate2);
        } catch (Exception e) {
            return false;
        }
        return ((leftStartDate.getTime() >= rightStartDate.getTime()) && leftStartDate.getTime() < rightEndDate.getTime())
                || ((leftStartDate.getTime() > rightStartDate.getTime()) && leftStartDate.getTime() <= rightEndDate.getTime())
                || ((rightStartDate.getTime() >= leftStartDate.getTime()) && rightStartDate.getTime() < leftEndDate.getTime())
                || ((rightStartDate.getTime() > leftStartDate.getTime()) && rightStartDate.getTime() <= leftEndDate.getTime());

    }

    /**
     * 连续日期分组(获取时间段内  连续的日期)
     *
     * @param datas
     * @return
     */
    public static List<List<String>> groupConsecutiveDates(List<String> datas) {
        datas.sort(String::compareTo);
        List<List<String>> result = new ArrayList<>();
        List<String> group = null;
        for (String value : datas) {
            if (group == null || !DateUtils.dateAddOneNoHms(group.get(group.size() - 1)).equals(value)) {
                group = new ArrayList<>();
                result.add(group);
            }
            group.add(value);
        }
        return result;
    }


    /**
     * 根据开始时间和结束时间返回时间段内的时间集合
     *
     * @param beginDate
     * @param endDate
     * @return List
     */
    public static List<String> getDatesBetweenTwoDate(Date beginDate, Date endDate) {
        List<String> lDate = new ArrayList<>();
        // 把开始时间加入集合
        lDate.add(parseDateToStr("yyyy-MM-dd", beginDate));
        Calendar cal = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        cal.setTime(beginDate);
        boolean bContinue = true;
        while (bContinue) {
            // 根据日历的规则,为给定的日历字段添加或减去指定的时间量
            cal.add(Calendar.DAY_OF_MONTH, 1);
            // 测试此日期是否在指定日期之后
            if (endDate.after(cal.getTime())) {
                lDate.add(parseDateToStr("yyyy-MM-dd", cal.getTime()));
            } else {
                break;
            }
        }
        // 把结束时间加入集合
        lDate.add(parseDateToStr("yyyy-MM-dd", endDate));
        return lDate;
    }

    /**
     * 将yyyyMMddHHmm字符串转换成时间类型
     *
     * @param dataStr
     * @return
     */
    public static Date longToData(String dataStr) {
        Date d = null;
        try {
            d = sdfOfYYYYMMDDHHMM.parse(dataStr);

        } catch (ParseException e) {
            e.printStackTrace();
        }
        return d;
    }


    /**
     * Tue Aug 21 2018 00:00:00 GMT+0800 (中国标准时间)  时间格式转换
     * @param dateString
     * @return String
     */
    public static Date pekToString(String dateString) {
        try {
            dateString = dateString.split(Pattern.quote(SPLIT_STRING))[0].replace(REPLACE_STRING[0], REPLACE_STRING[1]);
            SimpleDateFormat sf1 = new SimpleDateFormat("E MMM dd yyyy HH:mm:ss z", Locale.US);
//            SimpleDateFormat defaultFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = sf1.parse(dateString);
//            String dateStr = defaultFormat.format(date);
            return date;
        } catch (Exception e) {
            throw new RuntimeException("时间转化格式错误" + "[dateString=" + dateString + "]" + "[FORMAT_STRING=" + FORMAT_STRING + "]");
        }
    }

    /**
     * 判断日期是否在区间内
     * @param nowTime 日期
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @param format 日期格式
     * @return boolean 在返回true
     */
    public static boolean isEffectiveDate(String nowTime, String startTime, String endTime ,String format) {
        Date nowDate = dateTime(format,nowTime);
        Date startDate = dateTime(format,startTime);
        Date stopDate = dateTime(format,endTime);
        if (nowDate.getTime() == startDate.getTime()
                || nowDate.getTime() == stopDate.getTime()) {
            return true;
        }
        Calendar date = Calendar.getInstance();
        date.setTime(nowDate);
        Calendar begin = Calendar.getInstance();
        begin.setTime(startDate);
        Calendar end = Calendar.getInstance();
        end.setTime(stopDate);
        if (date.after(begin) && date.before(end)) {
            return true;
        } else {
            return false;
        }
    }
/***
     * 功能描述:百纳秒的时间加减
     * @Param  date: 百纳秒的时间
     * @Param hours: 
     * @return: long
     * @since: 1.0.0
     */
    public static long addtime(long date,int hours){
        long result = date;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            // 传过来的时间单位是100ns 高精度(要-116445024000000000L(100ns) =》 再转ms(/10/1000))
            String dateStr = sdf.format(new Date((date-116445024000000000L)/10/1000));
            LocalDate localDate = LocalDate.parse(dateStr,format);
            LocalTime localTime = LocalTime.parse(dateStr,format);
            LocalDateTime dateTime = LocalDateTime.of(localDate,localTime);
            // 时间加小时
            LocalDateTime addTime = dateTime.plusHours(hours);
            // 时间减小时
            LocalDateTime reduceTime = dateTime.minusHours(hours);
            result = sdf.parse(addTime.format(format)).getTime()*10*1000 + 116445024000000000L;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return result;
    }


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值