详解Javascript判断Crontab表达式是否合法

Javascript判断Crontab表达式是否合法

这段时间在做Quartz任务调度,使用的Crontab表达式实现的。Crontab由前端页面输入,作为参数穿入后台。
虽然Quartz具有校验Crontab表达式的方法,如下:

boolean cronExpressionFlag = CronExpression.isValidExpression(crontab);

但是我一直想在前端直接验证,即不需要通过异步的方式向后台获取验证结果,找了好久,发现没有现成的框架可以使用,于是自己根据网上搜索到的资料,写了这个js脚本。

这个脚本目前对日和星期的判断还有点小问题,不过不影响使用。

以后如果有时间,继续完善这个脚本,废话不多说了,上代码:

 function cronValidate() {
    var cron = $("#cron").val();
    var result = CronExpressionValidator.validateCronExpression(cron);
    if(result == true){
      alert("格式正确");
    }
    else{
      alert("格式错误");
    }
    return CronExpressionValidator.validateCronExpression(cron);
  }
  function CronExpressionValidator() {
  } 

  CronExpressionValidator.validateCronExpression = function(value) {
    var results = true;
    if (value == null || value.length == 0) {
      return false;
    } 

    // split and test length
    var expressionArray = value.split(" ");
    var len = expressionArray.length; 

    if ((len != 6) && (len != 7)) {
      return false;
    } 

    // check only one question mark
    var match = value.match(/\?/g);
    if (match != null && match.length > 1) {
      return false;
    } 

    // check only one question mark
    var dayOfTheMonthWildcard = ""; 

    // if appropriate length test parts
    // [0] Seconds 0-59 , - * /
    if (CronExpressionValidator.isNotWildCard(expressionArray[0], /[\*]/gi)) {
      if (!CronExpressionValidator.segmentValidator("([0-9\\\\,-\\/])", expressionArray[0], [0, 59], "seconds")) {
        return false;
      }
    } 

    // [1] Minutes 0-59 , - * /
    if (CronExpressionValidator.isNotWildCard(expressionArray[1], /[\*]/gi)) {
      if (!CronExpressionValidator.segmentValidator("([0-9\\\\,-\\/])", expressionArray[1], [0, 59], "minutes")) {
        return false;
      }
    } 

    // [2] Hours 0-23 , - * /
    if (CronExpressionValidator.isNotWildCard(expressionArray[2], /[\*]/gi)) {
      if (!CronExpressionValidator.segmentValidator("([0-9\\\\,-\\/])", expressionArray[2], [0, 23], "hours")) {
        return false;
      }
    } 

    // [3] Day of month 1-31 , - * ? / L W C
    if (CronExpressionValidator.isNotWildCard(expressionArray[3], /[\*\?]/gi)) {
      if (!CronExpressionValidator.segmentValidator("([0-9LWC\\\\,-\\/])", expressionArray[3], [1, 31], "days of the month")) {
        return false;
      }
    } else {
      dayOfTheMonthWildcard = expressionArray[3];
    } 

    // [4] Month 1-12 or JAN-DEC , - * /
    if (CronExpressionValidator.isNotWildCard(expressionArray[4], /[\*]/gi)) {
      expressionArray[4] = CronExpressionValidator.convertMonthsToInteger(expressionArray[4]);
      if (!CronExpressionValidator.segmentValidator("([0-9\\\\,-\\/])", expressionArray[4], [1, 12], "months")) {
        return false;
      }
    } 

    // [5] Day of week 1-7 or SUN-SAT , - * ? / L C #
    if (CronExpressionValidator.isNotWildCard(expressionArray[5], /[\*\?]/gi)) {
      expressionArray[5] = CronExpressionValidator.convertDaysToInteger(expressionArray[5]);
      if (!CronExpressionValidator.segmentValidator("([0-9LC#\\\\,-\\/])", expressionArray[5], [1, 7], "days of the week")) {
        return false;
      }
    } else {
      if (dayOfTheMonthWildcard == String(expressionArray[5])) {
        return false;
      }
    } 

    // [6] Year empty or 1970-2099 , - * /
    if (len == 7) {
      if (CronExpressionValidator.isNotWildCard(expressionArray[6], /[\*]/gi)) {
        if (!CronExpressionValidator.segmentValidator("([0-9\\\\,-\\/])", expressionArray[6], [1970, 2099], "years")) {
          return false;
        }
      }
    }
    return true;
  } 

  // ----------------------------------
  // isNotWildcard 静态方法;
  // ----------------------------------
  CronExpressionValidator.isNotWildCard = function(value, expression) {
    var match = value.match(expression);
    return (match == null || match.length == 0) ? true : false;
  } 

  // ----------------------------------
  // convertDaysToInteger 静态方法;
  // ----------------------------------
  CronExpressionValidator.convertDaysToInteger = function(value) {
    var v = value;
    v = v.replace(/SUN/gi, "1");
    v = v.replace(/MON/gi, "2");
    v = v.replace(/TUE/gi, "3");
    v = v.replace(/WED/gi, "4");
    v = v.replace(/THU/gi, "5");
    v = v.replace(/FRI/gi, "6");
    v = v.replace(/SAT/gi, "7");
    return v;
  } 

  // ----------------------------------
  // convertMonthsToInteger 静态方法;
  // ----------------------------------
  CronExpressionValidator.convertMonthsToInteger = function(value) {
    var v = value;
    v = v.replace(/JAN/gi, "1");
    v = v.replace(/FEB/gi, "2");
    v = v.replace(/MAR/gi, "3");
    v = v.replace(/APR/gi, "4");
    v = v.replace(/MAY/gi, "5");
    v = v.replace(/JUN/gi, "6");
    v = v.replace(/JUL/gi, "7");
    v = v.replace(/AUG/gi, "8");
    v = v.replace(/SEP/gi, "9");
    v = v.replace(/OCT/gi, "10");
    v = v.replace(/NOV/gi, "11");
    v = v.replace(/DEC/gi, "12");
    return v;
  } 

  // ----------------------------------
  // segmentValidator 静态方法;
  // ----------------------------------
  CronExpressionValidator.segmentValidator = function(expression, value, range, segmentName) {
    var v = value;
    var numbers = new Array(); 

    // first, check for any improper segments
    var reg = new RegExp(expression, "gi");
    if (!reg.test(v)) {
      return false;
    } 

    // check duplicate types
    // check only one L
    var dupMatch = value.match(/L/gi);
    if (dupMatch != null && dupMatch.length > 1) {
      return false;
    } 

    // look through the segments
    // break up segments on ','
    // check for special cases L,W,C,/,#,-
    var split = v.split(",");
    var i = -1;
    var l = split.length;
    var match; 

    while (++i < l) {
      // set vars
      var checkSegment = split[i];
      var n;
      var pattern = /(\w*)/;
      match = pattern.exec(checkSegment); 

      // if just number
      pattern = /(\w*)\-?\d+(\w*)/;
      match = pattern.exec(checkSegment); 

      if (match
          && match[0] == checkSegment
          && checkSegment.indexOf("L") == -1
          && checkSegment.indexOf("l") == -1
          && checkSegment.indexOf("C") == -1
          && checkSegment.indexOf("c") == -1
          && checkSegment.indexOf("W") == -1
          && checkSegment.indexOf("w") == -1
          && checkSegment.indexOf("/") == -1
          && (checkSegment.indexOf("-") == -1 || checkSegment
              .indexOf("-") == 0) && checkSegment.indexOf("#") == -1) {
        n = match[0]; 

        if (n && !(isNaN(n)))
          numbers.push(n);
        else if (match[0] == "0")
          numbers.push(n);
        continue;
      }
  // includes L, C, or w
      pattern = /(\w*)L|C|W(\w*)/i;
      match = pattern.exec(checkSegment); 

      if (match
          && match[0] != ""
          && (checkSegment.indexOf("L") > -1
              || checkSegment.indexOf("l") > -1
              || checkSegment.indexOf("C") > -1
              || checkSegment.indexOf("c") > -1
              || checkSegment.indexOf("W") > -1 || checkSegment
              .indexOf("w") > -1)) { 

        // check just l or L
        if (checkSegment == "L" || checkSegment == "l")
          continue;
        pattern = /(\w*)\d+(l|c|w)?(\w*)/i;
        match = pattern.exec(checkSegment); 

        // if something before or after
        if (!match || match[0] != checkSegment) {
          continue;
        } 

        // get the number
        var numCheck = match[0];
        numCheck = numCheck.replace(/(l|c|w)/ig, ""); 

        n = Number(numCheck); 

        if (n && !(isNaN(n)))
          numbers.push(n);
        else if (match[0] == "0")
          numbers.push(n);
        continue;
      } 

      var numberSplit; 

      // includes /
      if (checkSegment.indexOf("/") > -1) {
        // take first #
        numberSplit = checkSegment.split("/"); 

        if (numberSplit.length != 2) {
          continue;
        } else {
          n = numberSplit[0]; 

          if (n && !(isNaN(n)))
            numbers.push(n);
          else if (numberSplit[0] == "0")
            numbers.push(n);
          continue;
        }
      } 

      // includes #
      if (checkSegment.indexOf("#") > -1) {
        // take first #
        numberSplit = checkSegment.split("#"); 

        if (numberSplit.length != 2) {
          continue;
        } else {
          n = numberSplit[0]; 

          if (n && !(isNaN(n)))
            numbers.push(n);
          else if (numberSplit[0] == "0")
            numbers.push(n);
          continue;
        }
      } 

  // includes -
      if (checkSegment.indexOf("-") > 0) {
        // take both #
        numberSplit = checkSegment.split("-"); 

        if (numberSplit.length != 2) {
          continue;
        } else if (Number(numberSplit[0]) > Number(numberSplit[1])) {
          continue;
        } else {
          n = numberSplit[0]; 

          if (n && !(isNaN(n)))
            numbers.push(n);
          else if (numberSplit[0] == "0")
            numbers.push(n);
          n = numberSplit[1]; 

          if (n && !(isNaN(n)))
            numbers.push(n);
          else if (numberSplit[1] == "0")
            numbers.push(n);
          continue;
        }
      } 

    }
    // lastly, check that all the found numbers are in range
    i = -1;
    l = numbers.length; 

    if (l == 0)
      return false; 

    while (++i < l) {
      // alert(numbers[i]);
      if (numbers[i] < range[0] || numbers[i] > range[1]) {
        return false;
      }
    }
    return true;
  }

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • 详解Javascript判断Crontab表达式是否合法

    Javascript判断Crontab表达式是否合法 这段时间在做Quartz任务调度,使用的Crontab表达式实现的.Crontab由前端页面输入,作为参数穿入后台. 虽然Quartz具有校验Crontab表达式的方法,如下: boolean cronExpressionFlag = CronExpression.isValidExpression(crontab); 但是我一直想在前端直接验证,即不需要通过异步的方式向后台获取验证结果,找了好久,发现没有现成的框架可以使用,于是自己根据网上

  • 详解JavaScript数据类型和判断方法

    前言 JavaScript 中目前有 7 种基本(原始primitives)数据类型 Undefined, Null,Boolean, Number, String,BigInt,Symbol,以及一种引用类型 Object,Object 中又包括 Function,Date,JSON,RegExp等,除了 7 种原始类型,其他的所有能够用 new 实例化的内置类型都是 Object 构造的. 数据类型 对于数据了类型我们可以通过 typeof 运算符来判断,具体结果看下图. 原始类型中两个比较

  • 详解JavaScript的this指向和绑定

    注意: 本文属于基础篇,请大神绕路.如果你不够了解,或者了解的还不完整,那么可以通过本文来复习一下. this 指向的类型 刚开始学习 JavaScript 的时候,this 总是最能让人迷惑,下面我们一起看一下在 JavaScript 中应该如何确定 this 的指向. this 是在函数被调用时确定的,它的指向完全取决于函数调用的地方,而不是它被声明的地方(除箭头函数外).当一个函数被调用时,会创建一个执行上下文,它包含函数在哪里被调用(调用栈).函数的调用方式.传入的参数等信息,this

  • 详解javascript实现瀑布流绝对式布局

    瀑布流也应该算是流行几年了吧.首先是由Pinterest掀起的浪潮,然后国内设计如雨后春笋般,冒出很多瀑布流的例子,比如,蘑菇街,Mark之(不过最近涉黄,好像被喝茶了),还有淘宝的 "哇哦". 这些都是很棒的例子, 今天我们就聊一聊瀑布流. 一.绝对式布局: JS实现原理 其实瀑布式主要的难点就在于,如果将图片整齐的排列在对应的列下,以及什么时候开始刷新加载图片. 而图片整齐的排列的主要逻辑和算法即,先获取容器内可以放多少列,然后,通过计算,存放第一列的高度,再遍历剩下(除第一列的元

  • 详解JavaScript基本类型和引用类型

    一.值的类型        早在介绍JS的数据类型的时候就提到过基本类型和引用类型,不过在说两种类型之前,我们先来了解一下变量的值的类型.在ECMAScript中,变量可以存在两种类型的值,即原始值和引用值. (1)原始值        存储在栈中的简单数据段,也就是说,它们的值直接存储在变量访问的位置. (2)引用值        存储在堆中的对象,也就是说,存储在变量处的值是一个指针,指向存储对象的内存处.        为变量赋值时,ECMAScript的解释程序必须判断该值是原始类型,还

  • js对象实例详解(JavaScript对象深度剖析,深度理解js对象)

    这算是酝酿很久的一篇文章了. JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕. 平时发的文章基本都是开发中遇到的问题和对最佳解决方案的探讨,终于忍不住要写一篇基础概念类的文章了. 本文探讨以下问题,在座的朋友各取所需,欢迎批评指正: 1.创建对象 2.__proto__与prototype 3.继承与原型链 4.对象的深度克隆 5.一些Object的方法与需要注意的点 6.ES6新增特性 下面反复提到实例对象和原型对象,通过构造函数 new

  • 详解javascript void(0)

    void关键字介绍 首先,void关键字是javascript当中非常重要的关键字,该操作符指定要计算或运行一个表达式,但是不返回值. 语法格式: void func() void(func()) 实例1 当点击超级链接时,什么都不发生 <!-- 1.当用户链接时,void(0)计算为0,用户点击不会发生任何效果 --> <a href="javascript:void(0);" rel="external nofollow" rel="

  • 详解JavaScript 作用域

    作用域是可访问变量的集合. JavaScript 作用域 在 JavaScript 中, 对象和函数同样也是变量. 在 JavaScript 中, 作用域为可访问变量,对象,函数的集合. JavaScript 函数作用域: 作用域在函数内修改. JavaScript 局部作用域 变量在函数内声明,变量为局部作用域. 局部变量:只能在函数内部访问. // 此处不能调用 carName 变量 function myFunction() { var carName = "Volvo"; //

  • 详解JavaScript自定义函数

    一.定义方法:在Javascript中必须用function关键字 function funcName(arg1,arg2...) { statements; return "变量值"; //返回值可以根据函数的需要 } 函数名是函数自身的一个引用.此种方式创立的函数引用是独立存在的,无法删除. 1.调用函数:函数名(参数列表). 传递的参数不必与函数定义的参数个数一致,并且可以设定函数参数的默认值. function example(a,b){ var a = arguments[0

  • 详解JavaScript 的执行机制

    一.关于javascript javascript是一门单线程语言,在最新的HTML5中提出了Web Worker,但javascript是单线程这一核心仍未改变. 为什么js是单线程的语言?因为最初的js是用来在浏览器验证表单操纵DOM元素的.如果js是多线程的话,两个线程同时对一个DOM进行了相互冲突的操作,那么浏览器的解析是无法执行的. Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行.在主线程运行的同

随机推荐