计算SQL中CRON表达式的下一次运行时间

问题描述 投票:0回答:1

我在我的网站上使用 CRON UI 为某些用户任务创建重复发生的计划。 UI 生成 CRON 格式,该格式存储在数据库中,我正在寻找一种方法来获取下一个运行时间,以了解任务是否到期并相应地执行该任务。有没有办法可以转换 CRON 格式以获得 SQL 中的下一次运行时间?

0 9 1-7 * 1 *                       First Monday of each month, at 9 a.m.
0 0 1 * * *                         At midnight, on the first day of each month
* 0-11 * * *                        Each minute before midday

桌子

JobID, CRONSchedule
1  0 9 1-7 * 1 *
2  0 0 1 * * * 
3  * 0-11 * * * 

SQL

Select JobID, CRONSchedule, NextRunTime from TABLE
sql sql-server sql-server-2008 cron
1个回答
0
投票

我使用此查询来确定特定的 cron 是否已准备好运行(返回 t/f)。基于此查询,您可以获得下一次运行日期和时间,更新表中存在的列,并可以执行各种此类作业。但这段代码有局限性,我们只能输入 5 位结构的 cron 数据。

* * * * * command
| | | | |
| | | | +----- Day of the week (0 - 6) (Sunday is both 0 and 7)
| | | +------- Month (1 - 12)
| | +--------- Day of the month (1 - 31)
| +----------- Hour (0 - 23)
+------------- Minute (0 - 59)

这将是我的表格结构

 Column |            Type             | Collation | Nullable |               Default                | Storage  | Compression | Stats target | Description 
--------+-----------------------------+-----------+----------+--------------------------------------+----------+-------------+--------------+-------------
 timeid | integer                     |           | not null | nextval('time_timeid_seq'::regclass) | plain    |             |              | 
 time   | timestamp without time zone |           |          |                                      | plain    |             |              | 
 cron   | character varying           |           |          |                                      | extended |             |              | 

WITH TABLE_1 AS (
    SELECT
        TIMEID,
        TIME,
        CRON,
        EXTRACT(MINUTE FROM now()) AS TIME_MINUTE,
        EXTRACT(HOUR FROM now()) AS TIME_HOUR,
        EXTRACT(DAY FROM now()) AS TIME_DAY_OF_MONTH,
        EXTRACT(MONTH FROM now()) AS TIME_MONTH,
        EXTRACT(DOW FROM now()) AS TIME_DAY_OF_WEEK,
        (STRING_TO_ARRAY(CRON,' '))[1] AS CRON_MINUTE,
        (STRING_TO_ARRAY(CRON,' '))[2] AS CRON_HOUR,
        (STRING_TO_ARRAY(CRON,' '))[3] AS CRON_DAY_OF_MONTH,
        (STRING_TO_ARRAY(CRON,' '))[4] AS CRON_MONTH,
        (STRING_TO_ARRAY(CRON,' '))[5] AS CRON_DAY_OF_WEEK,
        CASE
            WHEN SPLIT_PART(CRON, ' ', 1) LIKE '*/%' THEN SUBSTRING(SPLIT_PART(CRON, ' ', 1) FROM 3)::INT
            WHEN SPLIT_PART(CRON, ' ', 1) ~ '^[0-9]+$' THEN CAST(SPLIT_PART(CRON, ' ', 1) AS INT)
            WHEN SPLIT_PART(CRON, ' ', 1) = '*' THEN 0
            WHEN SPLIT_PART(CRON, ' ', 1) ~ '^[0-9]+-[0-9]+$' THEN (STRING_TO_ARRAY(SPLIT_PART(CRON, ' ', 1), '-'))[1]::INT * 100 + (STRING_TO_ARRAY(SPLIT_PART(CRON, ' ', 1), '-'))[2]::INT
            ELSE NULL
        END AS EXTRACTED_CRON_MINUTE_VALUE,
        CASE
            WHEN SPLIT_PART(CRON, ' ', 2) LIKE '*/%' THEN SUBSTRING(SPLIT_PART(CRON, ' ', 2) FROM 3)::INT
            WHEN SPLIT_PART(CRON, ' ', 2) ~ '^[0-9]+$' THEN CAST(SPLIT_PART(CRON, ' ', 2) AS INT)
            WHEN SPLIT_PART(CRON, ' ', 2) = '*' THEN 0
            WHEN SPLIT_PART(CRON, ' ', 2) ~ '^[0-9]+-[0-9]+$' THEN (STRING_TO_ARRAY(SPLIT_PART(CRON, ' ', 2), '-'))[1]::INT * 100 + (STRING_TO_ARRAY(SPLIT_PART(CRON, ' ', 2), '-'))[2]::INT
            ELSE NULL
        END AS EXTRACTED_CRON_HOUR_VALUE,
        CASE
            WHEN SPLIT_PART(CRON, ' ', 3) LIKE '*/%' THEN SUBSTRING(SPLIT_PART(CRON, ' ', 3) FROM 3)::INT
            WHEN SPLIT_PART(CRON, ' ', 3) ~ '^[0-9]+$' THEN CAST(SPLIT_PART(CRON, ' ', 3) AS INT)
            WHEN SPLIT_PART(CRON, ' ', 3) = '*' THEN 0
            WHEN SPLIT_PART(CRON, ' ', 3) ~ '^[0-9]+-[0-9]+$' THEN (STRING_TO_ARRAY(SPLIT_PART(CRON, ' ', 3), '-'))[1]::INT * 100 + (STRING_TO_ARRAY(SPLIT_PART(CRON, ' ', 3), '-'))[2]::INT
            ELSE NULL
        END AS EXTRACTED_CRON_DAY_OF_MONTH_VALUE,
        CASE
            WHEN SPLIT_PART(CRON, ' ', 4) LIKE '*/%' THEN SUBSTRING(SPLIT_PART(CRON, ' ', 4) FROM 3)::INT
            WHEN SPLIT_PART(CRON, ' ', 4) ~ '^[0-9]+$' THEN CAST(SPLIT_PART(CRON, ' ', 4) AS INT)
            WHEN SPLIT_PART(CRON, ' ', 4) = '*' THEN 0
            WHEN SPLIT_PART(CRON, ' ', 4) ~ '^[0-9]+-[0-9]+$' THEN (STRING_TO_ARRAY(SPLIT_PART(CRON, ' ', 4), '-'))[1]::INT * 100 + (STRING_TO_ARRAY(SPLIT_PART(CRON, ' ', 4), '-'))[2]::INT
            ELSE NULL
        END AS EXTRACTED_CRON_MONTH_VALUE,
        CASE
            WHEN SPLIT_PART(CRON, ' ', 5) LIKE '*/%' THEN SUBSTRING(SPLIT_PART(CRON, ' ', 5) FROM 3)::INT
            WHEN SPLIT_PART(CRON, ' ', 5) ~ '^[0-9]+$' THEN CAST(SPLIT_PART(CRON, ' ', 5) AS INT)
            WHEN SPLIT_PART(CRON, ' ', 5) = '*' THEN 0
            WHEN SPLIT_PART(CRON, ' ', 5) ~ '^[0-9]+-[0-9]+$' THEN (STRING_TO_ARRAY(SPLIT_PART(CRON, ' ', 5), '-'))[1]::INT * 100 + (STRING_TO_ARRAY(SPLIT_PART(CRON, ' ', 5), '-'))[2]::INT
            ELSE NULL
        END AS EXTRACTED_CRON_DAY_OF_WEEK_VALUE
    FROM
        TIME
), TABLE_2 AS (
    SELECT
        TIMEID,
        TIME,
        CRON,
        TIME_MINUTE,
        TIME_HOUR,
        TIME_DAY_OF_MONTH,
        TIME_MONTH,
        TIME_DAY_OF_WEEK,
        EXTRACTED_CRON_MINUTE_VALUE,
        EXTRACTED_CRON_HOUR_VALUE,
        EXTRACTED_CRON_DAY_OF_MONTH_VALUE,
        EXTRACTED_CRON_MONTH_VALUE,
        EXTRACTED_CRON_DAY_OF_WEEK_VALUE,
        CASE
            WHEN CRON_MINUTE LIKE '*/%' AND TIME_MINUTE % EXTRACTED_CRON_MINUTE_VALUE = 0 THEN TRUE
            WHEN CRON_MINUTE ~ '^[0-9]+$' AND TIME_MINUTE - EXTRACTED_CRON_MINUTE_VALUE = 0 THEN TRUE
            WHEN CRON_MINUTE = '*' THEN TRUE
            WHEN CRON_MINUTE ~ '^[0-9]+-[0-9]+$' AND
                TIME_MINUTE = EXTRACTED_CRON_MINUTE_VALUE / 100 OR TIME_MINUTE = EXTRACTED_CRON_MINUTE_VALUE % 10 OR (TIME_MINUTE BETWEEN EXTRACTED_CRON_MINUTE_VALUE / 100
                AND EXTRACTED_CRON_MINUTE_VALUE % 10) THEN TRUE
            ELSE FALSE
        END AS RESULT_MINUTE,
        CASE
            WHEN CRON_HOUR LIKE '*/%' AND TIME_HOUR % EXTRACTED_CRON_HOUR_VALUE = 0 THEN TRUE
            WHEN CRON_HOUR ~ '^[0-9]+$' AND TIME_HOUR - EXTRACTED_CRON_HOUR_VALUE = 0 THEN TRUE
            WHEN CRON_HOUR = '*' THEN TRUE
            WHEN CRON_HOUR ~ '^[0-9]+-[0-9]+$' AND
                TIME_HOUR = EXTRACTED_CRON_HOUR_VALUE / 100 OR TIME_HOUR = EXTRACTED_CRON_HOUR_VALUE % 10 OR (TIME_HOUR BETWEEN EXTRACTED_CRON_HOUR_VALUE / 100
                AND EXTRACTED_CRON_HOUR_VALUE % 10) THEN TRUE
            ELSE FALSE
        END AS RESULT_HOUR,
        CASE
            WHEN CRON_DAY_OF_MONTH LIKE '*/%' AND TIME_DAY_OF_MONTH % EXTRACTED_CRON_DAY_OF_MONTH_VALUE = 0 THEN TRUE
            WHEN CRON_DAY_OF_MONTH ~ '^[0-9]+$' AND TIME_DAY_OF_MONTH - EXTRACTED_CRON_DAY_OF_MONTH_VALUE = 0 THEN TRUE
            WHEN CRON_DAY_OF_MONTH = '*' THEN TRUE
            WHEN CRON_DAY_OF_MONTH ~ '^[0-9]+-[0-9]+$' AND
                TIME_DAY_OF_MONTH = EXTRACTED_CRON_DAY_OF_MONTH_VALUE / 100 OR TIME_DAY_OF_MONTH = EXTRACTED_CRON_DAY_OF_MONTH_VALUE % 10 OR (TIME_DAY_OF_MONTH BETWEEN EXTRACTED_CRON_DAY_OF_MONTH_VALUE / 100
                AND EXTRACTED_CRON_DAY_OF_MONTH_VALUE % 10) THEN TRUE
            ELSE FALSE
        END AS RESULT_DAY_OF_MONTH,
        CASE
            WHEN CRON_MONTH LIKE '*/%' AND TIME_MONTH % EXTRACTED_CRON_MONTH_VALUE = 0 THEN TRUE
            WHEN CRON_MONTH ~ '^[0-9]+$' AND TIME_MONTH - EXTRACTED_CRON_MONTH_VALUE = 0 THEN TRUE
            WHEN CRON_MONTH = '*' THEN TRUE
            WHEN CRON_MONTH ~ '^[0-9]+-[0-9]+$' AND
                TIME_MONTH = EXTRACTED_CRON_MONTH_VALUE / 100 OR TIME_MONTH = EXTRACTED_CRON_MONTH_VALUE % 10 OR (TIME_MONTH BETWEEN EXTRACTED_CRON_MONTH_VALUE / 100
                AND EXTRACTED_CRON_MONTH_VALUE % 10) THEN TRUE
            ELSE FALSE
        END AS RESULT_MONTH,
        CASE
            WHEN CRON_DAY_OF_WEEK LIKE '*/%' AND TIME_DAY_OF_WEEK % EXTRACTED_CRON_DAY_OF_WEEK_VALUE = 0 THEN TRUE
            WHEN CRON_DAY_OF_WEEK ~ '^[0-9]+$' AND TIME_DAY_OF_WEEK - EXTRACTED_CRON_DAY_OF_WEEK_VALUE = 0 THEN TRUE
            WHEN CRON_DAY_OF_WEEK = '*' THEN TRUE
            WHEN CRON_DAY_OF_WEEK ~ '^[0-9]+-[0-9]+$' AND
                TIME_DAY_OF_WEEK = EXTRACTED_CRON_DAY_OF_WEEK_VALUE / 100 OR TIME_DAY_OF_WEEK = EXTRACTED_CRON_DAY_OF_WEEK_VALUE % 10 OR (TIME_DAY_OF_WEEK BETWEEN EXTRACTED_CRON_DAY_OF_WEEK_VALUE / 100
                AND EXTRACTED_CRON_DAY_OF_WEEK_VALUE % 10) THEN TRUE
            ELSE FALSE
        END AS RESULT_DAY_OF_WEEK
    FROM TABLE_1
)
SELECT
    TIMEID,
    CRON,
    RESULT_MINUTE,
    RESULT_HOUR,
    RESULT_DAY_OF_MONTH,
    RESULT_MONTH,
    RESULT_DAY_OF_WEEK,
    CASE
        WHEN (RESULT_MINUTE) = TRUE AND (RESULT_HOUR) AND (RESULT_DAY_OF_MONTH) = TRUE AND (RESULT_MONTH) = TRUE AND (RESULT_DAY_OF_WEEK) = TRUE THEN TRUE
        ELSE FALSE
    END AS RESULT
FROM TABLE_2;

我希望这段代码有帮助!!

© www.soinside.com 2019 - 2024. All rights reserved.