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

com.github.dennisit.vplus.data.utils.DateTimeUtils Maven / Gradle / Ivy

There is a newer version: 2.0.8
Show newest version
/*--------------------------------------------------------------------------
 *  Copyright (c) 2010-2020, Elon.su All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the elon developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: Elon.su, you can also mail [email protected]
 *--------------------------------------------------------------------------
 */
package com.github.dennisit.vplus.data.utils;

import com.github.dennisit.vplus.data.utils.date.ChineseDate;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.joda.time.Days;

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

/**
 * Created by Elon.su on 17/9/16.
 */
@Slf4j
public class DateTimeUtils {

    public static final String PATTERN_DATETIME = "yyyy-MM-dd HH:mm:ss";
    public static final String PATTERN_DATE = "yyyy-MM-dd";
    public static final String PATTERN_TIME = "HH:mm:ss";
    /**
     * 老 date 格式化
     */
    public static final ConcurrentDateFormat DATETIME_FORMAT = ConcurrentDateFormat.of(PATTERN_DATETIME);
    public static final ConcurrentDateFormat DATE_FORMAT = ConcurrentDateFormat.of(PATTERN_DATE);
    public static final ConcurrentDateFormat TIME_FORMAT = ConcurrentDateFormat.of(PATTERN_TIME);
    /**
     * java 8 时间格式化
     */
    public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(PATTERN_DATETIME);
    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(PATTERN_DATE);
    public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern(PATTERN_TIME);

    private static final String[] HANZI = {"壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖", "拾"};

    private static final String[] DI_ZHI = {"子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"};

    private static final String[] TIAN_GAN = {"甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"};


    public static final org.joda.time.LocalDate LOCAL_INIT_DATE = new org.joda.time.LocalDate(1970, 1, 1);

    /**
     * 标准日期格式
     */
    public final static String NORM_DATE_PATTERN = "yyyy-MM-dd";
    /**
     * 标准时间格式
     */
    public final static String NORM_TIME_PATTERN = "HH:mm:ss";
    /**
     * 标准日期时间格式
     */
    public final static String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    /**
     * HTTP头中日期时间格式
     */
    public final static String HTTP_DATETIME_PATTERN = "EEE, dd MMM yyyy HH:mm:ss z";

    /**
     * 标准日期(不含时间)格式化器
     */
    public final static SimpleDateFormat NORM_DATE_FORMAT = new SimpleDateFormat(NORM_DATE_PATTERN);
    /**
     * 标准时间格式化器
     */
    public final static SimpleDateFormat NORM_TIME_FORMAT = new SimpleDateFormat(NORM_TIME_PATTERN);
    /**
     * 标准日期时间格式化器
     */
    public final static SimpleDateFormat NORM_DATETIME_FORMAT = new SimpleDateFormat(NORM_DATETIME_PATTERN);
    /**
     * HTTP日期时间格式化器
     */
    public final static SimpleDateFormat HTTP_DATETIME_FORMAT = new SimpleDateFormat(HTTP_DATETIME_PATTERN, Locale.US);



    public static Date now() {
        return new Date();
    }

    public static String lunarYearToGanZhi(int lunarYear) {
        return TIAN_GAN[(lunarYear - 4) % 10] + DI_ZHI[(lunarYear - 4) % 12] + "年";
    }

    public static String lunarMonthToChinese(int month, boolean isleap) {
        String prefix = isleap ? "润" : "";
        if (month <= 10) {
            return prefix + HANZI[month - 1] + "月";
        } else {
            return prefix + HANZI[9] + HANZI[month % 10 - 1] + "月";
        }
    }

    public static String lunarDayToChinese(int day) {
        if (day <= 10) {
            return "初" + HANZI[day - 1];
        } else if (day == 20) {
            return "贰拾";
        } else if (day == 30) {
            return "叁拾";
        } else {
            return HANZI[day / 10 - 1] + HANZI[day % 10 - 1];
        }
    }


    /**
     * 24小时的时间转为对应的农历说法
     *
     * @param hour [0, 23]
     * @return 农历文案
     */
    public static String hourToChinese(int hour) {
        if (hour == 23) {
            return DI_ZHI[0] + "时";
        } else {
            return DI_ZHI[(hour + 1) / 2] + "时";
        }
    }


    /**
     * 阴历转字符串
     *
     * @param lunar 阴历
     * @return 字符串描述
     */
    public static String parseLunar(ChineseDate.Lunar lunar) {
        StringBuilder builder = new StringBuilder();
        builder.append(lunarYearToGanZhi(lunar.getLunarYear()));
        builder.append(lunarMonthToChinese(lunar.getLunarMonth(), lunar.isIsleap()));
        builder.append(lunarDayToChinese(lunar.getLunarDay()));
        return builder.toString();
    }


    /**
     * 获取当前的阴历日期
     *
     * @param containHour 小时
     * @return 字符串描述
     */
    public static String getNowLunarDate(boolean containHour) {
        Calendar rightNow = Calendar.getInstance();
        int year = rightNow.get(Calendar.YEAR);
        int month = rightNow.get(Calendar.MONTH) + 1; //第一个月从0开始,所以得到月份+1
        int day = rightNow.get(Calendar.DAY_OF_MONTH);
        int hour = rightNow.get(Calendar.HOUR_OF_DAY);

        ChineseDate.Solar solar = new ChineseDate.Solar(year, month, day);
        ChineseDate.Lunar lunar = ChineseDate.solarToLunar(solar);

        if (containHour) {
            return parseLunar(lunar) + " " + hourToChinese(hour);
        } else {
            return parseLunar(lunar);
        }
    }


    public static String getNowLunarDate() {
        return getNowLunarDate(true);
    }


    /**
     * 将 {@link LocalDateTime} 转换成 {@link Date}
     *
     * @param localDateTime {@link LocalDateTime} 待转换的日期
     * @return 转换成Date结果
     */
    @Deprecated
    public static Date from(LocalDateTime localDateTime) {
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(instant);
    }


    /**
     * 将 {@link Date} 转换成 {@link LocalDateTime}
     *
     * @param date {@link Date} 待转换的日期
     * @return 转换成 {@link LocalDateTime} 结果
     */
    @Deprecated
    public static LocalDateTime from(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }


    /**
     * 获取{@link Date}在开始时间和结束时间内的日期时间段{@link Date}集合
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return 时间天数集合
     */
    public static List dateZones(Date start, Date end) {
        return dateZones(from(start), from(end));
    }


    /**
     * 获取 {@link LocalDate} 在开始时间和结束时间内的日期时间段 {@link LocalDate} 集合
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return 时间集合
     */
    public static List dateZones(LocalDate start, LocalDate end) {
        return Stream.iterate(start, x -> x.plusDays(1))
                .limit(ChronoUnit.DAYS.between(start, end) + 1)
                .map(e -> Date.from(e.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()))
                .collect(Collectors.toList());
    }


    /**
     * 获取{@link LocalDateTime} 在开始时间和结束时间内的日期时间段{@link Date}集合
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return 时间天数集合
     */
    public static List dateZones(LocalDateTime start, LocalDateTime end) {
        // 用起始时间作为流的源头,按照每次加一天的方式创建一个无限流
        return Stream.iterate(start.toLocalDate(), x -> x.plusDays(1))
                // 截断无限流,长度为起始时间和结束时间的差+1个
                .limit(ChronoUnit.DAYS.between(start, end) + 1)
                // 由于最后要的是字符串,所以map转换一下
                .map(e -> Date.from(e.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant()))
                // 把流收集为List
                .collect(Collectors.toList());
    }


    /**
     * 获取{@link Date}在开始时间和结束时间内的日期时间段{@link LocalDate}集合
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return 时间集合
     */
    public static List localDateZones(Date start, Date end) {
        return localDateZones(from(start), from(end));
    }


    /**
     * 获取 {@link LocalDate} 在开始时间和结束时间内的日期时间段 {@link LocalDate} 集合
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return 时间集合
     */
    public static List localDateZones(LocalDate start, LocalDate end) {
        return Stream.iterate(start, x -> x.plusDays(1))
                .limit(ChronoUnit.DAYS.between(start, end) + 1)
                .collect(Collectors.toList());
    }

    /**
     * 获取 {@link LocalDateTime} 在开始时间和结束时间内的日期时间段 {@link LocalDate} 集合
     *
     * @param start 开始时间
     * @param end   结束时间
     * @return 时间集合
     */
    public static List localDateZones(LocalDateTime start, LocalDateTime end) {
        // 用起始时间作为流的源头,按照每次加一天的方式创建一个无限流
        return Stream.iterate(start.toLocalDate(), x -> x.plusDays(1))
                // 截断无限流,长度为起始时间和结束时间的差+1个
                .limit(ChronoUnit.DAYS.between(start, end) + 1)
                .map(e -> e.atStartOfDay().toLocalDate())
                // 把流收集为List
                .collect(Collectors.toList());
    }


    /**
     * 日期转换为Unix时间戳
     *
     * @param date 日期
     * @return 秒数
     */
    public static int date2Unixtime(Date date) {
        return (int) (date.getTime() / 1000L);
    }

    /**
     * 获取当前日期距离1970年多少天
     *
     * @param date 日期
     * @return 距离1970年有多少天
     */
    public static long getDaysTotal(Date date) {
        return Days.daysBetween(LOCAL_INIT_DATE, org.joda.time.LocalDate.fromDateFields(date)).getDays();
    }


    /**
     * 判断是否日期(年月日)有重叠
     *
     * @param zones 开始时间结束时间对
     * @return 是否有天数重叠
     */
    public static boolean isDayOverlap(List> zones) {
        if (CollectionUtils.isEmpty(zones) || zones.size() <= 1) {
            return false;
        }
        validateDateTimes(zones);
        for (int i = 0; i < zones.size() - 1; i++) {
            long starTime = getDaysTotal(zones.get(i).getLeft());
            long endTime = getDaysTotal(zones.get(i).getRight());
            for (int j = i + 1; j < zones.size(); j++) {
                log.info(zones.get(i) + " == " + zones.get(i));
                long jsTime = getDaysTotal(zones.get(j).getLeft());
                long jeTime = getDaysTotal(zones.get(j).getRight());
                if (!(jeTime < starTime || jsTime > endTime)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 判断是否日期时间(年月日时分秒)重叠
     *
     * @param zones 开始时间结束时间对
     * @return 是否日期时间重叠
     */
    public static boolean isDateTimeOverlap(List> zones) {
        if (CollectionUtils.isEmpty(zones) || zones.size() <= 1) {
            return false;
        }
        validateDateTimes(zones);
        for (int i = 0; i < zones.size() - 1; i++) {
            long starTime = zones.get(i).getLeft().getTime();
            long endTime = zones.get(i).getRight().getTime();
            for (int j = i + 1; j < zones.size(); j++) {
                log.info(zones.get(i) + " == " + zones.get(i));
                long jsTime = zones.get(j).getLeft().getTime();
                long jeTime = zones.get(j).getRight().getTime();
                if (!(jeTime < starTime || jsTime > endTime)) {
                    return true;
                }
            }
        }
        return false;
    }


    /**
     * 校验时间段个贵姓
     *
     * @param zones
     */
    private static void validateDateTimes(List> zones) {
        if (CollectionUtils.isEmpty(zones)) {
            return;
        }
        for (Pair timeZone : zones) {
            if (null == timeZone) {
                throw new IllegalArgumentException("时间段为空");
            }
            if (null == timeZone.getLeft() || null == timeZone.getRight()) {
                throw new IllegalArgumentException("时间段为空");
            }
            if (timeZone.getRight().getTime() <= timeZone.getLeft().getTime()) {
                throw new IllegalArgumentException("开始时间大于等于结束时间");
            }
        }
    }

    /**
     * 获取当前年份的所有月份的第一天
     *
     * @return 日期集合
     */
    public static List getNowYearFirstDayOfEachMonth() {
        Calendar cal = Calendar.getInstance();
        List list = Lists.newArrayList();
        for (int i = 0; i < 12; i++) {
            cal.set(Calendar.MONTH, i);
            cal.set(Calendar.DAY_OF_MONTH, 1);
            cal.set(Calendar.HOUR_OF_DAY, 0);
            cal.set(Calendar.MINUTE, 0);
            cal.set(Calendar.SECOND, 0);
            list.add(cal.getTime());
        }
        return list;
    }


    public static Integer getHourMinutePeriod() {
        return Calendar.getInstance().get(Calendar.HOUR_OF_DAY) * 60 + Calendar.getInstance().get(Calendar.MINUTE);
    }

    /*public static final long MILLIS_IN_ONE_MINUTE = 1000 * 60;
    // public static final long MILLIS_IN_ONE_HOUR = MILLIS_IN_ONE_MINUTE * 60;
    public static final long MILLIS_IN_ONE_DAY = MILLIS_IN_ONE_HOUR * 24;
    public static final long MILLIS_IN_ONE_YEAR = MILLIS_IN_ONE_DAY * 365;*/

    /**
     * 原实现做的乘除法过多,影响效率,且几个方法的代码重复
     *
     * @param intervalMillis 据现在的时间间隔
     * @return
     */


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

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

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


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

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

    /**
     * 将字符串转换为时间
     *
     * @param dateStr 时间字符串
     * @return 时间
     */
    public static LocalDateTime parseDateTime(String dateStr) {
        return parseDateTime(dateStr, DATETIME_FORMATTER);
    }

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

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

    /**
     * 将字符串转换为日期
     *
     * @param dateStr 时间字符串
     * @return 时间
     */
    public static LocalDate parseDate(String dateStr) {
        return parseDate(dateStr, DATE_FORMATTER);
    }

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

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

    /**
     * 将字符串转换为时间
     *
     * @param dateStr 时间字符串
     * @return 时间
     */
    public static LocalTime parseTime(String dateStr) {
        return parseTime(dateStr, TIME_FORMATTER);
    }


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy