TimeZoneUtil.java 3.98 KB
package vion.utils;

import org.dromara.hutool.core.text.StrUtil;

import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 时区工具类
 */
public class TimeZoneUtil {

    /**
     * 获取默认时区和给定时区的时间差
     *
     * @param zoneId 时区id
     * @return int  小时
     */
    public static int getOffsetMinute(String zoneId) {
        if (StrUtil.isBlank(zoneId)) {
            return 0;
        }
        try {
            // 获取当前时区
            ZoneId currentZone = ZoneId.systemDefault();
            // 指定目标时区
            ZoneId targetZone = ZoneId.of(zoneId);
            // 获取当前时间
            ZonedDateTime currentTime = ZonedDateTime.now(currentZone);
            // 在目标时区计算时间
            ZonedDateTime targetTime = currentTime.withZoneSameInstant(targetZone);
            // 计算时差
            ZoneOffset currentOffset = currentTime.getOffset();
            ZoneOffset targetOffset = targetTime.getOffset();
            return (currentOffset.getTotalSeconds() - targetOffset.getTotalSeconds()) / 60;
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 转换Cron表达式
     *
     * @param originalCron  原始Cron表达式
     * @param offsetMinutes 偏移分钟
     * @return 转换后的Cron表达式
     */
    public static String convertCronExpression(String originalCron, int offsetMinutes) {
        // 分割Cron表达式
        String[] parts = originalCron.split(" ");

        // 转换每个部分
        String convertedMinute = convertField(parts[1], offsetMinutes, 0, 59);
        String convertedHour = convertField(parts[2], offsetMinutes / 60, 0, 23);

        // 重新组装Cron表达式
        parts[1] = convertedMinute;
        parts[2] = convertedHour;

        return String.join(" ", parts);
    }

    /**
     * 转换Cron表达式的单个字段
     *
     * @param field  原始字段
     * @param offset 偏移量
     * @param min    最小值
     * @param max    最大值
     * @return 转换后的字段
     */
    private static String convertField(String field, long offset, int min, int max) {
        // 处理通配符
        if ("*".equals(field)) {
            return "*";
        }

        // 处理步进模式 如: */5
        if (field.startsWith("*/") || field.startsWith("0/")) {
            return field;
        }

        // 处理范围模式 如: 1-5
        if (field.contains("-")) {
            String[] range = field.split("-");
            int start = Integer.parseInt(range[0]);
            int end = Integer.parseInt(range[1]);

            start = normalize(start + (int) offset, min, max);
            end = normalize(end + (int) offset, min, max);
            if (start > end) {
                return start + "-" + max + "," + min + "-" + end;
            }

            return start + "-" + end;
        }

        // 处理多个具体时间点 如: 1,3,5
        if (field.contains(",")) {
            List<String> convertedPoints = new ArrayList<>();
            for (String point : field.split(",")) {
                int convertedPoint = normalize(Integer.parseInt(point) + (int) offset, min, max);
                convertedPoints.add(String.valueOf(convertedPoint));
            }
            return String.join(",", convertedPoints);
        }

        // 处理单个时间点
        int convertedValue = normalize(Integer.parseInt(field) + (int) offset, min, max);
        return String.valueOf(convertedValue);
    }

    /**
     * 规范化值,确保在指定范围内
     *
     * @param value 原始值
     * @param min   最小值
     * @param max   最大值
     * @return 规范化后的值
     */
    private static int normalize(int value, int min, int max) {
        while (value < min) {
            value += (max - min + 1);
        }
        while (value > max) {
            value -= (max - min + 1);
        }
        return value;
    }
}