java实现动态日期宏变量

在常用的调度平台,都会提供一个{{ds}}或者${yyyyMMdd}类似的宏变量。

那么这个是怎么实现的呢;

首先定义一个日期加减运算的枚举类,我们可以根据用户提供表达式在当前日期上进行加减运算

复制代码
public enum DateScaleEnum {
    y {
        @Override
        public LocalDateTime calculate(LocalDateTime origin, String op, Integer num) {
            if (op.equals("+")) {
                return origin.plusYears(num);
            } else {
                return origin.minusYears(num);
            }
        }
    },
    M {
        @Override
        public LocalDateTime calculate(LocalDateTime origin, String op, Integer num) {
            if (op.equals("+")) {
                return origin.plusMonths(num);
            } else {
                return origin.minusMonths(num);
            }
        }
    },
    d {
        @Override
        public LocalDateTime calculate(LocalDateTime origin, String op, Integer num) {
            if (op.equals("+")) {
                return origin.plusDays(num);
            } else {
                return origin.minusDays(num);
            }
        }
    };

    public abstract LocalDateTime calculate(LocalDateTime origin, String op, Integer num);
}
复制代码

核心工具类

复制代码
public class DateFormatUtil {
    private static final Pattern dynamicPattern = Pattern.compile("\\$\\{(.*?)\\}");
    private static final Pattern namePattern = Pattern.compile("(?<format>[yMd\\-]+):?(?<op>\\+|\\-)?(?<num>[0-9]+)?(?<scale>[a-zA-Z])?");

    /**
     * 正则查找动态日期字符串'${yyyyMMdd:+7d}',并进行格式化
     * @param sourStr
     * @return
     */
    public static String dynamicFormat(String sourStr) {
        String targetStr = sourStr;

        try {
            Matcher dynamicMatcher = dynamicPattern.matcher(targetStr);
            while (dynamicMatcher.find()) {
                String key = dynamicMatcher.group();
                String keyclone = key.substring(2,key.length()-1);
                String value = getDynamicDate(keyclone);
                if (value != null)
                    targetStr = targetStr.replace(key, value);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return targetStr;
    }

    /**
     * 根据日期格式返回日期字符串
     * @param key 'yyyyMMdd' 或 'yyyy-MM-dd:+1d'
     * @return 2021-11-23
     * 根据格式串分别匹配出日期格式、加or减、加减数量和尺度
     */
    public static String getDynamicDate(String key) {
        Matcher dateMatcher = namePattern.matcher(key);
        LocalDateTime now = LocalDateTime.now();
        String target=null;
        while (dateMatcher.find()) {
            String format= dateMatcher.group("format");
            String op= dateMatcher.group("op");
            String num= dateMatcher.group("num");
            String scale= dateMatcher.group("scale");
            DateFormatEnum dynamicDate = getDateFormat(format);
            if (op == null) {
                return dynamicDate.format(now);
            }

            DateScaleEnum dateScaleEnum = DateScaleEnum.valueOf(scale);
            LocalDateTime calculate = dateScaleEnum.calculate(now, op, Integer.valueOf(num));

            target= dynamicDate.format(calculate);

        }
        return target;
    }

    /**
     * 根据用户提供的format对日期格式化
     * @param format
     * @return
     */
    public static DateFormatEnum getDateFormat(String format) {
        switch (format) {
            case "yyyy":
                return DateFormatEnum.Y;
            case "yyyy-MM":
                return DateFormatEnum.YM;
            case "yyyyMM":
                return DateFormatEnum.YM3;
            case "yyyyMMdd":
                return DateFormatEnum.YMD3;
            case "yyyy-MM-dd":
            default:
                return  DateFormatEnum.YMD;
        }
    }

    public static void main(String[] args) {
        String sql="select a,b,c from table " +
                "where dt>='${yyyy:-1y}' and dt<='${yyyyMM:+10M}' and dt='${yyyyMMdd}'";
        System.out.println(sql);
        String newSql = dynamicFormat(sql);
        System.out.println(newSql);


    }
}
复制代码

 

打印:

select a,b,c from table where dt>='${yyyy:-1y}' and dt<='${yyyyMM:+10M}' and dt='${yyyyMMdd}'
select a,b,c from table where dt>='2020' and dt<='202210' and dt='20211201'

 补充用法:如果想写去年一月这样的日期,怎么办?

其实不需要再把正则表达式进一步优化,现在的方式就可以支持了。

复制代码
 public static void main(String[] args) {
        String sql="select a,b,c from table " +
                "where dt>='${yyyy:-1y}-01' and dt<='${yyyyMM:+10M}' and dt='${yyyy-MM-dd} 00:00:00'";
        System.out.println(sql);
        String newSql = dynamicFormat(sql);
        System.out.println(newSql);
    }

/**
输出:
select a,b,c from table where dt>='${yyyy:-1y}-01' and dt<='${yyyyMM:+10M}' and dt='${yyyy-MM-dd} 00:00:00'
select a,b,c from table where dt>='2020-01' and dt<='202210' and dt='2021-12-01 00:00:00'
*/
复制代码

 

posted @   Mars.wang  阅读(260)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示