2009-08-05 29 views
12

Estoy usando Quartz con Java para programar trabajos. Una cosa es que almaceno cron expresiones en una base de datos y me gustaría presentarlas a un usuario pero en una forma más legible. Entonces me preguntaba si existe una utilidad que pueda convertir una expresión cron en una cadena legible para humanos. Algo como:Cron a cadena legible para humanos

"" 0 30 10-13? * Miércoles, viernes" se convertirá en "Fuegos a las 10:30, 11:30, 12:30, 13:30 y, en todos los miércoles y viernes."

+4

¿Alguna vez implementar una buena solución? Necesito hacer exactamente lo mismo, ¿tiene alguna pista/estrategia que facilite mi implementación? –

+0

Me temo que no ... Esto era necesario para la producción y mi empresa no lo veía como una prioridad. En su lugar, optamos por simplemente mostrar la próxima hora de activación para los trabajos cron: S Pero la respuesta que acepté a continuación proporciona un punto de partida para trabajar con cron. No sé lo fácil que sería ... –

Respuesta

19

Una biblioteca de Java que convierte las expresiones cron en cadenas de caracteres legibles: https://github.com/RedHogs/cron-parser

+12

Me encanta que Stackoverflow proporcione la respuesta correcta a una pregunta incluso 5 años después de haber sido solicitada. :) Saludos –

0

El CronTrigger crea un objeto CronExpression de la expresión cron . cadena Pero no se puede tener acceso a ella, pero mediante el uso de la reflexión se puede:.

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

creo que no entendiste mi pregunta –

9

Bueno, sí lo hice entender su pregunta, pero debería haber explicado mi respuesta un poco mejor

no yo.. No conozco ninguna herramienta que te ayude a obtener una expresión cron en forma legible "humana". Pero obteniendo acceso a CronExpression puedes crear tu propio.

intente llamar

cronTrigger.getExpressionSummary() 

en la expresión cron:

"0/2 * * 4 * ?" 

devuelve la cadena siguiente:

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

Al tener acceso al objeto CronExpression, puede crear su propia explementación "humana".

+0

sí, gracias por la respuesta. parece que voy a crear mi versión. –

2

aquí hay uno que comencé. usa el lenguaje que mis usuarios (probablemente) entenderán.

no le irá tan bien con mezclas de tokens como '1,13,16-23, L' para el token de dayofmonth, pero con suerte, tendré algo de tiempo para gastar en ello antes de que mis usuarios se conviertan en eso sofisticado:

 
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; 
    } 
} 
5

Hice una pequeña página para la traducción de cron. http://crontranslator.appspot.com/ Todavía necesita alguna mejora, cualquier sugerencia es bienvenida.

+0

¿Es de código abierto? –

+0

todavía no hay ningún proyecto en google code o github. Pero si quieres echar un vistazo, es solo un archivo JavaScript en la página. –

+0

¡genial! pero puedo usarlo? (por supuesto, dándole el crédito apropiado) ¿puedo ponerlo en alguna parte en github? –

1

cron-utils puede ser útil para esta tarea, ya que proporciona descripciones legibles por humanos y no requiere de un programador de pleno derecho para su prestación. Está bien documentado y es compatible con múltiples formatos cron.

A continuación un fragmento de código a partir de los documentos:

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