19

我正在使用 Quartz 和 Java 来安排作业。一件事是我将 cron 表达式存储在数据库中,并且我想以更易读的形式将它们呈现给用户。所以我想知道是否有一个实用程序可以将 cron 表达式转换为人类可读的字符串。就像是 :

“”0 30 10-13?* WED,FRI”将变为“每周三和周五的 10:30、11:30、12:30 和 13:30 开火”。

4

5 回答 5

33

一个将 cron 表达式转换为人类可读字符串的 Java 库:https ://github.com/RedHogs/cron-parser

于 2014-03-06T21:01:15.230 回答
10

嗯,是的,我确实理解你的问题。但我应该更好地解释我的答案。

不,我不知道有任何工具可以帮助您以“人类”可读形式获得 cron 表达式。但是通过访问 CronExpression,您可以创建自己的。

试着打电话

cronTrigger.getExpressionSummary() 

关于 cron 表达式:

"0/2 * * 4 * ?"

它返回以下字符串:

seconds: 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58
minutes: *
hours: *
daysOfMonth: 4
months: *
daysOfWeek: ?
lastdayOfWeek: false
nearestWeekday: false
NthDayOfWeek: 0
lastdayOfMonth: false
calendardayOfWeek: false
calendardayOfMonth: false
years: *

通过访问 CronExpression 对象,您可以创建自己的“人类”解释。

于 2009-08-06T10:20:25.277 回答
5

cron-utils可能对这项任务有用,因为它提供了人类可读的描述,并且不需要完全成熟的调度程序来提供它们。有据可查并支持多种 cron 格式。

下面是来自文档的代码片段:

//create a descriptor for a specific Locale
CronDescriptor descriptor = CronDescriptor.instance(Locale.UK);

//parse some expression and ask descriptor for description
String description = descriptor.describe(parser.parse("*/45 * * * * *"));
//description will be: "every 45 seconds"
于 2015-10-20T09:49:20.293 回答
2

这是我开始的。它使用我的用户将(可能)理解的语言。

对于 dayofmonth 令牌,它不会像 '1,13,16-23,L' 这样的令牌混合做得很好,但希望在我的用户变得如此复杂之前,我会有一些时间花在它上面:

包 com.tacteonltd.control.cron;

导入 java.util.StringTokenizer;

导入 com.tacteonltd.control.string.STRING;
导入 com.tacteonltd.control.time.TIME;

公共类 CRON {
    公共静态字符串humanReadable(字符串值){
        StringBuffer sb = new StringBuffer();
        尝试{
            StringTokenizer tokens = new StringTokenizer(value, " ", false);
            humanizeSeconds(tokens.nextToken(), sb);sb.append("\n");
            humanizeMinutes(tokens.nextToken(), sb);sb.append("\n");
            humanizeHours(tokens.nextToken(), sb);sb.append("\n");
            字符串 dom = tokens.nextToken();
            字符串月份 = tokens.nextToken();
            字符串 do = tokens.nextToken();
            humanizeDOMs(dom, dow, sb);sb.append("\n");
            humanizeMonths(月, sb);sb.append("\n");
            humanizeDOWs(dow, dom, sb);
        }catch(可投掷的 t){
            t.printStackTrace();
        }
        返回 sb.toString();
    }
    private static void humanizeDOWs(String value, String dom, StringBuffer sb){
        值=值.trim();
        如果(字符串.isNumeric(值)){
            sb.append("and the " + value + postFix(value) + " day-of-the-week("+TIME.getWeekDayName(Integer.parseInt(value))+"). ");
        }
        否则 if(value.equals("*"))
        {
            sb.append("以及每周的每一天。");
        }
        否则 if(value.equals("?"))
        {
            sb.append("以及星期几"+(STRING.isNumeric(dom) ? "":"s")+"-of-the-month :"+(STRING.isNumeric (dom) ? dom:"那个匹配"+(STRING.isNumeric(dom) ? "es":"")+" " + dom + "."));
        }
        否则 if(value.indexOf("/")>-1){
            String first = value.substring(0, value.indexOf("/"));
            每个字符串 = value.substring(value.indexOf("/") + 1);
            sb.append("and the " + first + postFix(first) + " day-of-the-week and every " + every + " day" + (Integer.parseInt(every) == 1 ? "":"s ") + " 跟随。");
        }
        否则 if(value.indexOf(",")>-1){
            StringTokenizer tokens = new StringTokenizer(value, ",", false);
            sb.append("以及一周中的以下几天:");
            整数添加= 0;
            而(令牌。hasMoreTokens()){
                字符串令牌 = tokens.nextToken();
                sb.append((add==0 ? "":", ") + token); added++;
            }
            sb.append(".");
        }
        否则 if(value.indexOf("-")>-1){
            StringTokenizer tokens = new StringTokenizer(value, "-", false);
            sb.append("一周中的每一天,从 " + tokens.nextToken() + " 到 " + tokens.nextToken() + ". ");
        }
        别的 {
            sb.append("以及一周中接下来的几天:" + value + ".");
        }
    }
    私人静态无效humanizeMonths(字符串值,StringBuffer sb){
        值=值.trim();
        如果(字符串.isNumeric(值)){
            sb.append("" + value + postFix(value) + " month("+TIME.getMonthName(Integer.parseInt(value))+"), ");
        }
        否则 if(value.equals("*"))
        {
            sb.append("每个月,");
        }
        否则 if(value.indexOf("/")>-1){
            String first = value.substring(0, value.indexOf("/"));
            每个字符串 = value.substring(value.indexOf("/") + 1);
            sb.append("the " + first + postFix(first) + " month("+TIME.getMonthName(Integer.parseInt(value))+") and every " + every + "month" + (Integer.parseInt(every ) == 1 ? "":"s") + " 以下, ");
        }
        否则 if(value.indexOf(",")>-1){
            StringTokenizer tokens = new StringTokenizer(value, ",", false);
            sb.append("接下来的月份:");
            整数添加= 0;
            而(令牌。hasMoreTokens()){
                sb.append((add==0 ? "":", ") + tokens.nextToken()); added++;
            }
        }
    }
    private static void humanizeDOMs(String value, String dow, StringBuffer sb){
        值=值.trim();
        如果(字符串.isNumeric(值)){
            sb.append("" + value + postFix(value) + " day-of-the-month, ");
        }
        否则 if(value.equals("*"))
        {
            sb.append("每月的每一天, ");
        }
        否则 if(value.equals("?"))
        {
            sb.append("当月的某一天落在 " + dow + " , ");
        }
        否则 if(value.indexOf("-")>-1){
            StringTokenizer tokens = new StringTokenizer(value, "-", false);
            来自 = tokens.nextToken() 的字符串;
            字符串通过 = tokens.nextToken();
            int 年 = TIME.getYear(System.currentTimeMillis());
            int 月 = TIME.getMonth(System.currentTimeMillis());
            String last_dom = "" + TIME.getLastDOM(year, month);
            sb.append("对于从" + from + "到" + (through.equals("L") ? "the last("+year +"." +month + "."+last_dom+" 的每一天)“:通过) );
        }
        否则 if(value.indexOf("/")>-1){
            String first = value.substring(0, value.indexOf("/"));
            每个字符串 = value.substring(value.indexOf("/") + 1);
            sb.append("the " + first + postFix(first) + " day-of-the-month and every " + every + " day" + (Integer.parseInt(every) == 1 ? "":"s" ) + " 跟随, ");
        }
        否则 if(value.indexOf(",")>-1){
            StringTokenizer tokens = new StringTokenizer(value, ",", false);
            sb.append("一个月的下几天:");
            整数添加= 0;
            而(令牌。hasMoreTokens()){
                字符串令牌 = tokens.nextToken();
                if(token.equals("L")){
                    int 年 = TIME.getYear(System.currentTimeMillis());
                    int 月 = TIME.getMonth(System.currentTimeMillis());
                    String last_dom = "" + TIME.getLastDOM(year, month);
                    sb.append((add==0 ? "":", ") + "the last("+year +"." +month + "."+last_dom+")");
                }
                别的{
                    sb.append((add==0 ? "":", ") + token); added++;
                }
            }
        }
    }
    私人静态无效humanizeSeconds(字符串值,StringBuffer sb){
        值=值.trim();
        如果(字符串.isNumeric(值)){
            sb.append("上" + value + postFix(value) + " second, ");
        }
        否则 if(value.equals("*"))
        {
            sb.append("每隔一秒,");
        }
        否则 if(value.indexOf("/")>-1){
            String first = value.substring(0, value.indexOf("/"));
            每个字符串 = value.substring(value.indexOf("/") + 1);
            sb.append("在 " + first + postFix(first) + " second and every " + every + " second" + (Integer.parseInt(every) == 1 ? "":"s") + " 后面, ");
        }
        否则 if(value.indexOf("-")>-1){
            StringTokenizer tokens = new StringTokenizer(value, "-", false);
            sb.append("从 " + tokens.nextToken() + " 到 " + tokens.nextToken() + " ") 的每一秒;
        }
        否则 if(value.indexOf(",")>-1){
            StringTokenizer tokens = new StringTokenizer(value, ",", false);
            sb.append("在接下来的几秒:");
            整数添加= 0;
            而(令牌。hasMoreTokens()){
                sb.append((add==0 ? "":", ") + tokens.nextToken()); added++;
            }
        }
    }
    私人静态无效humanizeMinutes(字符串值,StringBuffer sb){
        值=值.trim();
        如果(字符串.isNumeric(值)){
            sb.append("" + value + postFix(value) + " minute, ");
        }
        否则 if(value.equals("*"))
        {
            sb.append("每分钟,");
        }
        否则 if(value.indexOf("/")>-1){
            String first = value.substring(0, value.indexOf("/"));
            每个字符串 = value.substring(value.indexOf("/") + 1);
            " );
        }
        否则 if(value.indexOf("-")>-1){
            StringTokenizer tokens = new StringTokenizer(value, "-", false);
            sb.append("从 " + tokens.nextToken() + " 到 " + tokens.nextToken() + " ") 的每一分钟;
        }
        否则 if(value.indexOf(",")>-1){
            StringTokenizer tokens = new StringTokenizer(value, ",", false);
            sb.append("接下来的分钟数:");
            整数添加= 0;
            而(令牌。hasMoreTokens()){
                sb.append((add==0 ? "":", ") + tokens.nextToken()); added++;
            }
        }
    }
    私人静态无效humanizeHours(字符串值,StringBuffer sb){
        值=值.trim();
        如果(字符串.isNumeric(值)){
            sb.append("" + value + postFix(value) + " hour, ");
        }
        否则 if(value.equals("*"))
        {
            sb.append("每小时, ");
        }
        否则 if(value.indexOf("/")>-1){
            String first = value.substring(0, value.indexOf("/"));
            每个字符串 = value.substring(value.indexOf("/") + 1);
            sb.append("" + first + postFix(first) + " hour and every " + every + " hour" + (Integer.parseInt(every) == 1 ? "":"s") + " following, " );
        }
        否则 if(value.indexOf("-")>-1){
            StringTokenizer tokens = new StringTokenizer(value, "-", false);
            sb.append("从 " + tokens.nextToken() + " 到 " + tokens.nextToken() + " ") 的每个小时;
        }
        否则 if(value.indexOf(",")>-1){
            StringTokenizer tokens = new StringTokenizer(value, ",", false);
            sb.append("接下来的时间:");
            整数添加= 0;
            而(令牌。hasMoreTokens()){
                sb.append((add==0 ? "":", ") + tokens.nextToken()); added++;
            }
        }
    }
    私有静态字符串后缀(字符串值){
        字符串帖子=空;
            if(value.substring(value.length()-1).equals("1"))post = "st";
            否则 if(value.substring(value.length()-1).equals("2"))post = "nd";
            否则 if(value.substring(value.length()-1).equals("3"))post = "rd";
            否则 post="th";
        回帖;
    }
}
于 2010-09-19T01:19:59.113 回答
-1

The CronTrigger creates a CronExpression object from the cron expression String. But you cannot get access to it. But by using reflection you can:

Class c = cronTrigger.getClass();
Field f = c.getDeclaredField("cronEx");
f.setAccessible(true);
CronExpression cronEx = (CronExpression) f.get(cronTrigger);
于 2009-08-05T22:25:44.123 回答