Java Cron 到人类可读的字符串

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1235532/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 01:13:13  来源:igfitidea点击:

Cron to human readable string

javacronquartz-scheduler

提问by Savvas Dalkitsis

I am using Quartz with Java to schedule jobs. One thing is that i store cron expressions on a database and i would like to present them to a user but in a more readable form. So i was wondering if there is a utility that could convert a cron expression into a human readable string. Something like :

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

""0 30 10-13 ? * WED,FRI" will become "Fires at 10:30, 11:30, 12:30, and 13:30, on every Wednesday and Friday."

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

采纳答案by jazzhammer

A Java library that converts cron expressions into human readable strings: https://github.com/RedHogs/cron-parser

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

回答by Niels Peter Strandberg

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

CronTrigger 从 cron 表达式字符串创建一个 CronExpression 对象。但是您无法访问它。但是通过使用反射,您可以:

Class c = cronTrigger.getClass();
Field f = c.getDeclaredField("cronEx");
f.setAccessible(true);
CronExpression cronEx = (CronExpression) f.get(cronTrigger);

回答by Niels Peter Strandberg

Well yes I did understand your question. But I should have explained my answer a little better.

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

No I don't know any tool that will help you get a cron expression in “human” readable form. But by getting access to the CronExpression you can create you own.

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

Try calling

试试打电话

cronTrigger.getExpressionSummary() 

on the cron expression:

在 cron 表达式上:

"0/2 * * 4 * ?"

it returns the following String:

它返回以下字符串:

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: *

By having access to the CronExpression object, you can create your own "human" explenation.

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

回答by jazzhammer

here's one i started. it uses the language that my users will ( probably ) understand.

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

it won't do that well with mixtures of tokens like '1,13,16-23,L' for the dayofmonth token, but hopefully, i'll have some time to spend on it before my users become that sophisticated:

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

package com.tacteonltd.control.cron;

import java.util.StringTokenizer;

import com.tacteonltd.control.string.STRING;
import com.tacteonltd.control.time.TIME;

public class CRON {
    public static String humanReadable(String value){
        StringBuffer sb = new StringBuffer();
        try{
            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");
            String dom = tokens.nextToken();
            String month = tokens.nextToken();
            String dow = tokens.nextToken();
            humanizeDOMs(dom, dow, sb);sb.append("\n");
            humanizeMonths(month, sb);sb.append("\n");
            humanizeDOWs(dow, dom, sb);
        }catch(Throwable t){
            t.printStackTrace();
        }
        return sb.toString();
    }
    private static void humanizeDOWs(String value, String dom, StringBuffer sb){
        value=value.trim();
        if(STRING.isNumeric(value)){
            sb.append("and the " + value + postFix(value) + " day-of-the-week("+TIME.getWeekDayName(Integer.parseInt(value))+"). "); 
        }
        else if(value.equals("*"))
        {
            sb.append("and every day-of-the-week. ");
        }
        else if(value.equals("?"))
        {
            sb.append("and whatever day-of-the-week it is for day"+(STRING.isNumeric(dom) ? "":"s")+"-of-the-month :"+(STRING.isNumeric(dom) ? dom:"that match"+(STRING.isNumeric(dom) ? "es":"")+" " + dom + "."));
        }
        else if(value.indexOf("/")>-1){
            String first = value.substring(0, value.indexOf("/"));
            String every = 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") + " following. "); 
        }
        else if(value.indexOf(",")>-1){
            StringTokenizer tokens = new StringTokenizer(value, ",", false);
            sb.append("and the following days of the week: ");
            int added = 0;
            while(tokens.hasMoreTokens()){
                String token = tokens.nextToken();
                sb.append((added==0 ? "":", ") + token);added++;
            }
            sb.append(".");
        }
        else if(value.indexOf("-")>-1){
            StringTokenizer tokens = new StringTokenizer(value, "-", false);
            sb.append("and for every day of the week from " + tokens.nextToken() + " through " + tokens.nextToken() + ". ");
        }
        else {
            sb.append("and the following days of the week: " + value + ".");
        }
    }
    private static void humanizeMonths(String value, StringBuffer sb){
        value=value.trim();
        if(STRING.isNumeric(value)){
            sb.append("the " + value + postFix(value) + " month("+TIME.getMonthName(Integer.parseInt(value))+"), "); 
        }
        else if(value.equals("*"))
        {
            sb.append("every month, ");
        }
        else if(value.indexOf("/")>-1){
            String first = value.substring(0, value.indexOf("/"));
            String every = 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") + " following, "); 
        }
        else if(value.indexOf(",")>-1){
            StringTokenizer tokens = new StringTokenizer(value, ",", false);
            sb.append("the following months: ");
            int added = 0;
            while(tokens.hasMoreTokens()){
                sb.append((added==0 ? "":", ") + tokens.nextToken());added++;
            }
        }
    }
    private static void humanizeDOMs(String value, String dow, StringBuffer sb){
        value=value.trim();
        if(STRING.isNumeric(value)){
            sb.append("the " + value + postFix(value) + " day-of-the-month, "); 
        }
        else if(value.equals("*"))
        {
            sb.append("every day-of-the-month, ");
        }
        else if(value.equals("?"))
        {
            sb.append("whatever day-of-the-month falls upon " + dow + " , ");
        }
        else if(value.indexOf("-")>-1){
            StringTokenizer tokens = new StringTokenizer(value, "-", false);
            String from = tokens.nextToken();
            String through = tokens.nextToken();
            int year = TIME.getYear(System.currentTimeMillis());
            int month = TIME.getMonth(System.currentTimeMillis());
            String last_dom = "" + TIME.getLastDOM(year, month);
            sb.append("for every day of the month from " + from + " through " + (through.equals("L") ? "the last("+year +"." +month + "."+last_dom+")":through) );
        }
        else if(value.indexOf("/")>-1){
            String first = value.substring(0, value.indexOf("/"));
            String every = value.substring(value.indexOf("/") + 1);
            sb.append("the " + first + postFix(first) + " day-of-the-month and every " + every + " day" + (Integer.parseInt(every) == 1 ? "":"s") + " following, "); 
        }
        else if(value.indexOf(",")>-1){
            StringTokenizer tokens = new StringTokenizer(value, ",", false);
            sb.append("the following days of the month: ");
            int added = 0;
            while(tokens.hasMoreTokens()){
                String token = tokens.nextToken();
                if(token.equals("L")){
                    int year = TIME.getYear(System.currentTimeMillis());
                    int month = TIME.getMonth(System.currentTimeMillis());
                    String last_dom = "" + TIME.getLastDOM(year, month);
                    sb.append((added==0 ? "":", ") + "the last("+year +"." +month + "."+last_dom+")");
                }
                else{
                    sb.append((added==0 ? "":", ") + token);added++;
                }
            }
        }
    }
    private static void humanizeSeconds(String value, StringBuffer sb){
        value=value.trim();
        if(STRING.isNumeric(value)){
            sb.append("on the " + value + postFix(value) + " second, "); 
        }
        else if(value.equals("*"))
        {
            sb.append("on every second, ");
        }
        else if(value.indexOf("/")>-1){
            String first = value.substring(0, value.indexOf("/"));
            String every = value.substring(value.indexOf("/") + 1);
            sb.append("on the " + first + postFix(first) + " second and every " + every + " second" + (Integer.parseInt(every) == 1 ? "":"s") + " following, "); 
        }
        else if(value.indexOf("-")>-1){
            StringTokenizer tokens = new StringTokenizer(value, "-", false);
            sb.append("for every second from " + tokens.nextToken() + " through " + tokens.nextToken() + " ");
        }
        else if(value.indexOf(",")>-1){
            StringTokenizer tokens = new StringTokenizer(value, ",", false);
            sb.append("on the following seconds: ");
            int added = 0;
            while(tokens.hasMoreTokens()){
                sb.append((added==0 ? "":", ") + tokens.nextToken());added++;
            }
        }
    }
    private static void humanizeMinutes(String value, StringBuffer sb){
        value=value.trim();
        if(STRING.isNumeric(value)){
            sb.append("the " + value + postFix(value) + " minute, "); 
        }
        else if(value.equals("*"))
        {
            sb.append("every minute, ");
        }
        else if(value.indexOf("/")>-1){
            String first = value.substring(0, value.indexOf("/"));
            String every = value.substring(value.indexOf("/") + 1);
            sb.append("the " + first + postFix(first) + " minute and every " + every + " minute" + (Integer.parseInt(every) == 1 ? "":"s") + " following, "); 
        }
        else if(value.indexOf("-")>-1){
            StringTokenizer tokens = new StringTokenizer(value, "-", false);
            sb.append("for every minute from " + tokens.nextToken() + " through " + tokens.nextToken() + " ");
        }
        else if(value.indexOf(",")>-1){
            StringTokenizer tokens = new StringTokenizer(value, ",", false);
            sb.append("the following minutes: ");
            int added = 0;
            while(tokens.hasMoreTokens()){
                sb.append((added==0 ? "":", ") + tokens.nextToken());added++;
            }
        }
    }
    private static void humanizeHours(String value, StringBuffer sb){
        value=value.trim();
        if(STRING.isNumeric(value)){
            sb.append("the " + value + postFix(value) + " hour, "); 
        }
        else if(value.equals("*"))
        {
            sb.append("every hour, ");
        }
        else if(value.indexOf("/")>-1){
            String first = value.substring(0, value.indexOf("/"));
            String every = value.substring(value.indexOf("/") + 1);
            sb.append("the " + first + postFix(first) + " hour and every " + every + " hour" + (Integer.parseInt(every) == 1 ? "":"s") + " following, "); 
        }
        else if(value.indexOf("-")>-1){
            StringTokenizer tokens = new StringTokenizer(value, "-", false);
            sb.append("for every hour from " + tokens.nextToken() + " through " + tokens.nextToken() + " ");
        }
        else if(value.indexOf(",")>-1){
            StringTokenizer tokens = new StringTokenizer(value, ",", false);
            sb.append("the following hours: ");
            int added = 0;
            while(tokens.hasMoreTokens()){
                sb.append((added==0 ? "":", ") + tokens.nextToken());added++;
            }
        }
    }
    private static String postFix(String value){
        String post = null; 
            if(value.substring(value.length()-1).equals("1"))post = "st";
            else if(value.substring(value.length()-1).equals("2"))post = "nd";
            else if(value.substring(value.length()-1).equals("3"))post = "rd";
            else post="th";
        return post;
    }
}

回答by kekec

cron-utilsmay be useful for this task, since provides human readable descriptions and does not require a fully fledged scheduler to provide them. Is well documented and supports multiple cron formats.

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

Below a code snippet from the docs:

在文档中的代码片段下方:

//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"