package com.taia.yms.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * MyUseUtils
 * 相关处理的工具
 **/
@Slf4j
public class MyUseUtils {

    public static final String CONCAT_SYMBOL = "æ";
    private static final String FORMATER = "yyyy-MM-dd HH:mm:ss";
    private static final String DAY_FORMATER = "yyyy-MM-dd";
    private static final String YEAR_MONTH_OR_WEEK_STR = "%d-%02d";
    private static final int HOUR_FORMAT_END = 23;
    private static final int MINUTES_FORMAT_END = 59;
    private static final int SECONDS_FORMAT_END = 59;
    private static final int NANO_OF_SECOND = 999_000_000;
    private static final LocalTime FORMAT_LOCAL_TIME = LocalTime.of(HOUR_FORMAT_END, MINUTES_FORMAT_END, SECONDS_FORMAT_END).withNano(NANO_OF_SECOND);

    private MyUseUtils() {
        throw new IllegalStateException("MyUseUtils class");
    }

    //---------------------------------------------------------------------
    // String Utils
    //---------------------------------------------------------------------

    public static String concatStr(String... value) {
        String resStr = "";
        if (value.length > 0) {
            StringBuilder sb = new StringBuilder();
            for (String v : value) {
                sb.append(v).append(CONCAT_SYMBOL);
            }
            resStr = sb.toString();
        }
        return resStr;
    }

    /**
     * 开始日期时间 +  指定天数
     * @param startTime
     * @param days
     * @return
     */
    public static long calculateEndTime(Timestamp startTime,int days){
        return calculateEndTimeStamp( startTime, days).getTime();
    }

    public static Timestamp calculateEndTimeStamp(Timestamp startTime,int days){
        if(startTime == null){
            log.error("calculateEndTime error : startTime is null!");
            throw new NullPointerException("startTime is null!");
        }
        return Timestamp.valueOf(startTime.toLocalDateTime().plusDays(days));
    }

    /**
     * 根据开始日期时间往前推 2年
     * @param startTime
     * @return
     */
    public static Timestamp calculateMaxDateTime(Timestamp startTime){
        return calculateMaxDateTime( startTime,2);
    }

    public static Timestamp calculateMaxDateTime(Timestamp startTime,int year){
        if(startTime == null){
            log.error("calculateMaxDateTime error : startTime is null!");
            throw new NullPointerException("startTime is null!");
        }
        return Timestamp.valueOf(startTime.toLocalDateTime().plusYears(year));
    }

    /**
     * 获取时间格式
     * @return "yyyy-MM-dd HH:mm:ss"
     */
    public static String getPastTime(long nowTime) {
        return getPastTime(nowTime,0);
    }

    /**
     * 获取间隔时间(往过去时间)
     *
     * @param nowTime 当前时间
     * @param timeInterval 时间间隔
     * @return 返回格式:"yyyy-MM-dd HH:mm:ss"
     */
    public static String getPastTime(long nowTime, long timeInterval) {
        SimpleDateFormat sdf = new SimpleDateFormat(FORMATER);
        return sdf.format(new Date(nowTime- timeInterval * 1000));
    }

    /**
     * 时间格式
     * @param nowTime 当前时间
     * @return 返回格式:"yyyy-MM-dd HH:mm:ss"
     */
    public static String getDateFormat(long nowTime) {
        SimpleDateFormat sdf = new SimpleDateFormat(FORMATER);
        return sdf.format(new Date(nowTime));
    }

    public static LocalDate getDateFormat(String timeStr) {
        if(StringUtils.isEmpty(timeStr)){
            log.error("getDateFormat error : timeStr is null!");
            throw new NullPointerException("timeStr is null!");
        }
        return  LocalDate.parse(timeStr);
    }

    /**
     * 计算两个日期时间相差天数
     * 最后加1是因为起始时间从 00:00:00开始计算,结束时间从 23:59:59 计算
     * @param startTime
     * @param endTime
     * @return
     */
    public static long calculateDayDiff(Timestamp startTime, Timestamp endTime){
        if(startTime == null || endTime == null){
            log.error("calculateDayDiff error : startTime|endTime is null!");
            throw new NullPointerException("startTime|endTime is null!");
        }
        return (int) startTime.toLocalDateTime()
                .until(endTime.toLocalDateTime(), ChronoUnit.DAYS) + 1;
    }

    public static long calculateWeekDiff(Timestamp startTime, Timestamp endTime){
        if(startTime == null || endTime == null){
            log.error("calculateDayDiff error : startTime|endTime is null!");
            throw new NullPointerException("startTime|endTime is null!");
        }
        return (int) startTime.toLocalDateTime()
                .until(endTime.toLocalDateTime(), ChronoUnit.WEEKS) + 1;
    }

    public static long calculateMonthDiff(Timestamp startTime, Timestamp endTime){
        return calculateMonthDiff( startTime,  endTime,1);
    }

    public static long calculateMonthDiff(Timestamp startTime, Timestamp endTime,int diffMonth){
        if(startTime == null || endTime == null){
            log.error("calculateDayDiff error : startTime|endTime is null!");
            throw new NullPointerException("startTime|endTime is null!");
        }
        return (int) startTime.toLocalDateTime()
                .until(endTime.toLocalDateTime(), ChronoUnit.MONTHS) + diffMonth;
    }

    //---------------------------------------------------------------------
    // Stream Utils
    //---------------------------------------------------------------------

    /**
     * 多个字段去重过滤
     */
    @SafeVarargs
    public static <T> Predicate<T> distinctByKeys(Function<? super T, ?>... keyExtractors) {
        final Map<List<?>, Boolean> seen = new ConcurrentHashMap<>();
        return t -> {
            final List<?> keys = Arrays.stream(keyExtractors)
                    .map(ke -> ke.apply(t))
                    .collect(Collectors.toList());
            return seen.putIfAbsent(keys, Boolean.TRUE) == null;
        };
    }

    /**
     * 计算出 指定时间在所在年的第几周,输出 年-周
     * @param timestamp
     * @return
     */
    public static String calWhichWeek( Timestamp timestamp,String format){
        if(timestamp == null){
            log.error("calWhichWeek error : timestamp is null!");
            throw new NullPointerException("timestamp is null!");
        }
        // 转换为LocalDate
        LocalDate localDate = timestamp.toLocalDateTime().toLocalDate();
        // 使用ISO周定义(周一为一周的第一天,并且要求一周至少有4天在新的一年中)
        WeekFields weekFields = WeekFields.ISO;
        int year = localDate.get(weekFields.weekBasedYear());
        int weekOfYear = localDate.get(weekFields.weekOfYear());
        // 格式化输出
        return String.format(format, year, weekOfYear);
    }

    /**
     * 计算出 指定时间在所在年的第几月,输出 年-月
     * @param timestamp
     * @return
     */
    public static String calWhichMonth( Timestamp timestamp,String format){
        if(timestamp == null){
            log.error("calWhichMonth error : timestamp is null!");
            throw new NullPointerException("timestamp is null!");
        }
        // 转换为LocalDate
        LocalDate localDate = timestamp.toLocalDateTime().toLocalDate();
        int year = localDate.getYear();
        int monthValue = localDate.getMonthValue();
        // 格式化输出
        return String.format(format, year, monthValue);
    }

    public static String calWhichDay( Timestamp timestamp,String format){
        if(timestamp == null){
            log.error("calWhichDay error : timestamp is null!");
            throw new NullPointerException("timestamp is null!");
        }
        // 创建SimpleDateFormat对象并设置日期格式
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        // 使用SimpleDateFormat的format()方法将Timestamp对象转换为字符串
        return sdf.format(timestamp);
    }

    public static String calWhichDay( Timestamp timestamp){
        return calWhichDay( timestamp,DAY_FORMATER);
    }

    public static String calWhichWeekStr( Timestamp timestamp){
        return calWhichWeek( timestamp,YEAR_MONTH_OR_WEEK_STR);
    }

    public static String calWhichMonthStr( Timestamp timestamp){
        return calWhichMonth( timestamp,YEAR_MONTH_OR_WEEK_STR);
    }

    public static Timestamp calMonthLastDay(LocalDate localDate){
        if(localDate == null){
            log.error("calLastDay error : localDate is null!");
            throw new NullPointerException("localDate is null!");
        }
        // 构造该月份的最后一天的LocalDate
        LocalDate lastDayOfMonth = localDate.withDayOfMonth(localDate.lengthOfMonth());
        // 设置时间为23:59:59
        LocalDateTime lastMomentOfMonth = LocalDateTime.of(lastDayOfMonth,FORMAT_LOCAL_TIME);
        // 如果需要转换回Timestamp
        // 注意:这里我们使用了系统的默认时区,但在实际应用中,你可能需要指定一个特定的时区
        return Timestamp.valueOf(lastMomentOfMonth);
    }

    public static Timestamp calMonthLastDay(String timeStr){
        if(StringUtils.isEmpty(timeStr)){
            log.error("calLastDay error : timeStr is null!");
            throw new NullPointerException("timeStr is null!");
        }
        return calMonthLastDay(getDateFormat(timeStr));
    }

    public static Timestamp calMonthFirstDay(LocalDate localDate){
        if(localDate == null){
            log.error("calFirstDay error : localDate is null!");
            throw new NullPointerException("localDate is null!");
        }
        // 构造该月份的最后一天的LocalDate
        LocalDate firstDayOfMonth  = localDate.with(TemporalAdjusters.firstDayOfMonth());
        // 设置时间为  00:00:00
        LocalDateTime firstDayOfMonthDateTime = firstDayOfMonth.atStartOfDay();
        // 如果需要转换回Timestamp
        // 注意:这里我们使用了系统的默认时区,但在实际应用中,你可能需要指定一个特定的时区
        return Timestamp.valueOf(firstDayOfMonthDateTime);
    }

    public static Timestamp calMonthFirstDay(String timeStr){
        if(StringUtils.isEmpty(timeStr)){
            log.error("calFirstDay error : timeStr is null!");
            throw new NullPointerException("timeStr is null!");
        }
        return calMonthFirstDay(getDateFormat(timeStr));
    }

    /**
     * 给定 年-周  计算该周的第一天 日期
     * @param year
     * @param weekOfYear
     * @return
     */
    public static Timestamp getFirstDayOfYearWeek(int year, int weekOfYear) {
        // 获取该年份的第一天,并找到第一个周一
        LocalDate firstDayOfYear = LocalDate.of(year, 1, 1);
        LocalDate firstMondayOfYear = firstDayOfYear.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY));
        // 计算给定周数的周一的日期
        LocalDate firstDayOfTargetWeek = firstMondayOfYear.plusWeeks(weekOfYear - 1);
        // 转换为LocalDateTime(假设为当天午夜)
        LocalDateTime firstDayLocalDateTime = LocalDateTime.of(firstDayOfTargetWeek, LocalTime.MIDNIGHT);
        // 转换为ZonedDateTime(如果需要)
        ZonedDateTime firstDayZonedDateTime = firstDayLocalDateTime.atZone(TimeZone.getDefault().toZoneId());
        // 转换为Instant
        Instant firstDayInstant = firstDayZonedDateTime.toInstant();
        // 转换为Timestamp
        return new Timestamp(firstDayInstant.toEpochMilli());
    }

    public static Timestamp getFirstDayOfYearWeek(String timeStr) {
        if(StringUtils.isEmpty(timeStr)){
            log.error("getFirstDayOfYearWeek error : timeStr is null!");
            throw new NullPointerException("timeStr is null!");
        }
        String[] split = timeStr.split("-");
        if(split == null || split.length < 2){
            log.error("getFirstDayOfYearWeek error : split data error!");
            throw new NullPointerException("split data error!");
        }
        return getFirstDayOfYearWeek(Integer.valueOf(split[0]),Integer.valueOf(split[1]));
    }

    /**
     * 给定 年-周  计算该周的最后一天 日期
     * @param year
     * @param weekOfYear
     * @return
     */
    public static Timestamp getLastDayOfYearWeek(int year, int weekOfYear) {
        // 获取该周的第一天(周一)
        Timestamp firstDayTimestamp = getFirstDayOfYearWeek(year, weekOfYear);
        // 转换为LocalDateTime
        LocalDateTime firstDayLocalDateTime = firstDayTimestamp.toLocalDateTime();
        // 加上6天得到最后一天(周日)
        LocalDateTime lastDayLocalDateTime = firstDayLocalDateTime.plusDays(6);
        lastDayLocalDateTime = lastDayLocalDateTime.with(FORMAT_LOCAL_TIME);
        // 转换为ZonedDateTime(如果需要)
        ZonedDateTime lastDayZonedDateTime = lastDayLocalDateTime.atZone(TimeZone.getDefault().toZoneId());
        // 转换为Instant
        Instant lastDayInstant = lastDayZonedDateTime.toInstant();
        // 转换为Timestamp
        return new Timestamp(lastDayInstant.toEpochMilli());
    }

    public static Timestamp getLastDayOfYearWeek(String timeStr) {
        if(StringUtils.isEmpty(timeStr)){
            log.error("getLastDayOfYearWeek error : timeStr is null!");
            throw new NullPointerException("timeStr is null!");
        }
        String[] split = timeStr.split("-");
        if(split == null || split.length < 2){
            log.error("getLastDayOfYearWeek error : split data error!");
            throw new NullPointerException("split data error!");
        }
        return getLastDayOfYearWeek(Integer.valueOf(split[0]),Integer.valueOf(split[1]));
    }

    public static void main(String[] args) {
        int year = 2024;
        int weekOfYear = 23;

        Timestamp firstDayTimestamp = getFirstDayOfYearWeek(year, weekOfYear);
        Timestamp lastDayTimestamp = getLastDayOfYearWeek(year, weekOfYear);

        System.out.println("First day of the week (Monday) as Timestamp: " + firstDayTimestamp);
        System.out.println("Last day of the week (Sunday) as Timestamp: " + lastDayTimestamp);
    }

}

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部