Differences Between * and ? in Cron Expressions – Cron 表达式中 * 和 ? 之间的区别

最后修改: 2023年 11月 18日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

With a cron scheduler, we can automate repetitive tasks we’d otherwise need to handle manually. Additionally, the cron expression allows us to schedule jobs executing at the desired date and time.

有了 cron 调度程序,我们就可以将原本需要手动处理的重复性任务自动化。此外,cron 表达式 允许我们安排在所需日期和时间执行的工作。

For scheduling jobs in Java, we usually use the Quartz library. It’s an open-source solution for job scheduling written entirely in Java. Furthermore, if we’re working with the Spring framework, we can use the @Scheduled annotation to easily schedule tasks.

对于 Java 中的作业调度,我们通常使用 Quartz 库。这是一个完全用 Java 编写的作业调度开源解决方案。此外,如果我们使用Spring框架,则可以使用@Scheduled注解来轻松调度任务。

Although cron expression represents a powerful way to schedule tasks, its syntax can sometimes be confusing and overwhelming.

虽然 cron 表达式是一种功能强大的任务计划方式,但其语法有时会令人困惑和不知所措。

In this tutorial, we’ll examine the differences between the ? and the * symbols in cron expressions.

在本教程中,我们将探讨 cron 表达式中 ? 符号和 * 符号的区别。

2. Fields in Cron Expression

2.Cron 表达式中的字段

Before we dive in, let’s explore the fields that can appear in the cron expressions.

在开始之前,我们先来了解一下 cron 表达式中可能出现的字段。

In Quartz, a cron expression represents a string that involves up to seven fields separated by whitespace, each representing a specific unit of date and time:

在 Quartz 中,一个 cron 表达式代表一个字符串,它最多包含七个字段,每个字段用空格隔开,代表一个特定的日期和时间单位:

Field Required Allowed Values Allowed Special Characters
Seconds Yes 0-59 , – * /
Minutes Yes 0-59 , – * /
Hours Yes 0-23 , – * /
Day of Month Yes 1-31 , – * / ? L W
Month Yes 0-11 (or JAN-DEC) , – * /
Day of Week Yes 1-7 (or SUN-SAT) , – * / ? L C #
Year No 1970-2099 (or empty) , – * /

As we can see in the table above, all fields are mandatory except the field that specifies a year. If we don’t provide a value, the job will be executed every year.

如上表所示,除了指定年份的字段外,其他字段都是必填字段。如果我们不提供数值,任务将每年执行一次。

Additionally, the syntax for the Unix cron expressions is a bit different:

此外,Unix cron 表达式的语法有些不同:

Field Required Allowed Values Allowed Special Characters
Minutes Yes 0-59 , – * /
Hours Yes 0-23 , – * /
Day of Month Yes 1-31 , – * /
Month Yes 1-12 (or JAN-DEC) , – * /
Day of Week Yes 0-6 (or SUN-SAT) , – * /

The Unix cron expression consists of five fields followed by the command we’d like to execute. Unlike Quartz, there aren’t specific fields where we’d specify seconds and years. It focuses on scheduling tasks for the current year.

Unix cron 表达式由五个字段组成,后面是我们要执行的命令。与 Quartz 不同,它没有指定秒和年的特定字段。它的重点是调度当年的任务。

It’s worth noting that the cron expression in Unix doesn’t allow the ? symbol to appear in the expression.

值得注意的是,Unix 中的 cron 表达式不允许在表达式中出现 ? 符号。

In the next sections, we’ll primarily focus on the cron expressions with the Quartz library.

在接下来的章节中,我们将主要关注使用 Quartz 库的 cron 表达式。

3. The ? in Cron Expression

3.Cron 表达式中的 ?

Next, let’s examine the question mark symbol (?) in the cron expression. Simply put, it represents no specific value.

接下来,让我们检查一下 cron 表达式中的问号符号 (?)。简单地说,它不代表任何特定值。

We can use it only within the fields that specify the day of the month and the day of the week.

我们只能在指定月日和星期的字段中使用它。

However, it’s important to note the day of the month and the day of the week fields are mutually exclusive. In other words, we can’t specify values for both fields in the same expression.

不过,需要注意的是,”月日 “和 “星期 “字段是互斥的。换句话说,我们不能在同一个表达式中为这两个字段指定值。

For instance, the following expression results in an error:

例如,以下表达式会导致错误:

0 30 10 1 OCT 2 2023

Additionally, to easily understand the expression, let’s see it in the table:

此外,为了便于理解表达式,我们可以在表格中看到它:

Seconds Minutes Hours Day of Month Month Day of Week Year
0 30 10 1 OCT 2 2023

We set values for both the day of the month and the day of the week parameters, which isn’t supported with Quartz.

我们同时为月日和周日参数设置了值,而 Quartz 不支持这种设置。

The cron expression would be invalid even if we use the day of the month that falls on the correct weekday:

即使我们使用了正确的工作日,cron 表达式也是无效的:

0 30 10 30 OCT 2 2023

Here, the 30th of October in 2023 falls on a Monday, but the expression is still not valid.

这里,2023 年的 10 月 30 日正好是星期一,但表达式仍然无效。

Furthermore, since we’re required to set values for both fields, we need to put the ? symbol on one of them to indicate the value is unset. The field where we set ? will be ignored:

此外,由于我们需要为两个字段都设置值,因此我们需要在其中一个字段上添加 ? 符号,以表示值未设置。我们设置 ? 的字段将被忽略:

0 0 0 30 OCT ?

From the example, the job runs at midnight on the 30th of October, every year.

从示例中可以看出,这项工作在每年 10 月 30 日午夜运行。

Additionally, the ? can appear only once in a cron expression. Setting both values with ? would result in an error as well:

此外,? 在 cron 表达式中只能出现一次。使用 ? 设置两个值也会导致错误:

0 30 * ? OCT ?

4. The * in Cron Expression

4.Cron 表达式中的 * 符号

On the other hand, the asterisk (*) in the cron expression means all the values. To put it differently, we’d use it to set all the values defined for a specific field.

另一方面,cron 表达式中的星号 (*) 表示所有值。换句话说,我们可以用它来设置为特定字段定义的所有值。

Furthermore, unlike the ?, we can use * within any field in the cron expression.

此外,与 ? 不同,我们可以在 cron 表达式的任何字段中使用 *

As an example, let’s create a cron expression where we’ll set all the values from the field representing the hours:

例如,让我们创建一个 cron 表达式,在该表达式中,我们将设置代表小时数的字段中的所有值:

0 30 * 1 OCT ?

Next, let’s see in the tabular format:

接下来,让我们用表格的形式来看看:

Seconds Minutes Hours Day of Month Month Day of Week Year
0 30 * 1 OCT ? empty

The job executes on the first of October, at every hour, 30 minutes and 0 seconds.

任务在 10 月 1 日每小时 30 分 0 秒执行一次。

Additionally, we can use the * for multiple fields as well:

此外,我们还可以将 * 用于多个字段:

* * * * OCT ?

This job runs every second, every day in October.

这项工作在十月份每天每秒都在进行。

4.1. Day of Month and Day of Week in Linux Cron

4.1.Linux Cron 中的月日和周日

When it comes to the day of the month and the weekday fields in Linux cron, they behave differently than the ones from Quartz.

Linux cron 中的 “月日 “和 “工作日 “字段与 Quartz 中的不同。

Firstly, they’re not mutually exclusive. We can set both values in the same cron expression.

首先,它们并不相互排斥。我们可以在同一个 cron 表达式中设置这两个值。

Secondly, if both fields contain values other than the asterisks, they form a union:

其次,如果两个字段都包含星号以外的值,则它们构成一个联合字段:

30 10 1 10 5

The job from the example above executes at 10:30 on the first of October and every Friday.

上面示例中的工作在 10 月 1 日 10:30 和每周五执行。

Lastly, if one of the values starts with the asterisk, they form an intersection:

最后,如果其中一个值以星号开头,它们就会形成交集:

30 10 */1 * 1

Here, the job runs at 10:30 on every day of the month only if it falls on Monday.

在这里,只有在星期一的情况下,工作才会在每月的每天 10:30 运行。

5. Comparison Between * and ?

5.*?

To conclude, let’s list the main differences between the * and the ? special characters in the cron expression:

最后,让我们列出 cron 表达式中的 *? 特殊字符之间的主要区别:

The * Symbol The ? Symbol
Stands for all allowed values of a specific field Means no specific value
Can be used in any field Can be used only in fields representing the day of the month and the day of the week
Used to specify all the values from the field Used to set empty value
Can appear multiple times in the same expression Only one can exist per expression

6. Conclusion

6.结论

In this article, we learned the differences between the asterisk and the question mark special characters in cron expressions.

在本文中,我们学习了 cron 表达式中星号和问号特殊字符的区别。

To sum up, we’d use the * in the field of a cron expression to include all allowed values for that specific field. On the contrary, the ? represents no specific value and can be used only within the day of month and day of week fields.

总而言之,我们会在 cron 表达式的字段中使用 * 来包含该特定字段的所有允许值。相反,? 不代表特定值,只能在月日和周日字段中使用

Since Quartz doesn’t support implementation for both of those fields, we need to use ? in one of them to leave the field empty.

由于 Quartz 不支持这两个字段的实现,因此我们需要在其中一个字段中使用 ?