Class CronExpression
- All Implemented Interfaces:
Serializable, TemporalAdjuster
Parses and evaluates cron expressions with full standard Unix cron semantics, including OR logic for day-of-month/day-of-week, special characters (L, W, #), name aliases (MON-FRI, JAN-DEC), and macro support (@daily, @yearly, etc.).
解析和评估具有完整标准Unix Cron语义的Cron表达式, 包括月中日/星期几的OR逻辑、特殊字符(L、W、#)、 名称别名(MON-FRI、JAN-DEC)和宏支持(@daily、@yearly等)。
Features | 主要功能:
- 5-field and 6-field (with seconds) cron formats - 5字段和6字段(含秒)cron格式
- Standard OR semantics for day-of-month/day-of-week - 标准OR语义
- Special characters: L, L-N, LW, nW, n#m, nL - 特殊字符支持
- Name aliases: MON-FRI, JAN-DEC (case-insensitive) - 名称别名(不区分大小写)
- Macros: @yearly, @monthly, @weekly, @daily, @hourly - 预定义宏
- Range wrap-around: 22-2 for hours means 22,23,0,1,2 - 范围回绕
- Forward scheduling:
nextExecution(ZonedDateTime),nextExecutions(ZonedDateTime, int)- 正向调度 - Reverse scheduling:
previousExecution(ZonedDateTime)- 反向调度 - Lazy streams:
stream(ZonedDateTime),reverseStream(ZonedDateTime)- 惰性流式调度 - Filtered scheduling:
nextExecution(ZonedDateTime, Predicate)- 过滤调度(节假日排除等) - Schedule overlap detection:
nextOverlap(CronExpression, ZonedDateTime),hasOverlapBetween(CronExpression, ZonedDateTime, ZonedDateTime)- 调度重叠检测 TemporalAdjusterintegration:zdt.with(cronExpr)- 时间调节器集成- Human-readable description:
describe()- 人类可读描述 - Serializable with equals/hashCode - 可序列化,支持equals/hashCode
Usage Examples | 使用示例:
// Every day at 10:30 | 每天10:30
CronExpression.parse("30 10 * * *")
// Every weekday at 9:00 | 工作日9:00
CronExpression.parse("0 9 * * MON-FRI")
// 15th of month OR every Monday at noon | 15号或周一中午
CronExpression.parse("0 12 15 * MON")
// Last day of every month at 18:00 | 每月最后一天18:00
CronExpression.parse("0 18 L * *")
// 3rd Friday of every month at 10:00 | 每月第三个周五10:00
CronExpression.parse("0 10 * * FRI#3")
// Next 5 executions | 下5次执行时间
expr.nextExecutions(ZonedDateTime.now(), 5)
// Human-readable | 人类可读描述
expr.describe() // "At 09:00, Monday through Friday"
Performance | 性能特性:
- Parse: O(fields) - one-time cost - 解析: O(字段数) - 一次性开销
- nextExecution: O(1) amortized via field-jumping - 下次执行: 均摊O(1),字段跳跃优化
Security | 安全性:
- Thread-safe: Yes (immutable after construction) - 线程安全: 是(构造后不可变)
- Null-safe: Yes (rejects null inputs) - 空值安全: 是
- Since:
- JDK 25, opencode-base-cron V1.0.0
- Author:
- Leon Soo www.LeonSoo.com
- See Also:
-
Method Summary
Modifier and TypeMethodDescriptionadjustInto(Temporal temporal) Adjusts the temporal to the next execution time of this cron expression 将时间调节为此Cron表达式的下次执行时间longcountExecutionsBetween(ZonedDateTime from, ZonedDateTime to) Counts executions between two times 计算两个时间点之间的执行次数describe()Gets a human-readable description of this expression 获取此表达式的人类可读描述Gets a human-readable description in the specified locale 获取指定语言的人类可读描述booleanexecutionsBetween(ZonedDateTime from, ZonedDateTime to) Lists all executions between two times 列出两个时间点之间的所有执行时间executionsBetween(ZonedDateTime from, ZonedDateTime to, int limit) Lists executions between two times with a limit 列出两个时间点之间的执行时间(带限制)explain(ZonedDateTime from) Gets a comprehensive explanation for debugging 获取用于调试的综合解释信息Gets the original expression string 获取原始表达式字符串inthashCode()booleanhasOverlapBetween(CronExpression other, ZonedDateTime from, ZonedDateTime to) Checks if this and another expression have overlapping executions in a time range 检查此表达式与另一个表达式在时间范围内是否有重叠执行booleanChecks if this expression uses 6-field format (with seconds) 检查此表达式是否使用6字段格式(含秒)booleanisEquivalentTo(CronExpression other) Checks if this expression is structurally equivalent to another 检查此表达式是否与另一个结构等价booleanmatches(ZonedDateTime time) Check if a time matches this cron expression 检查时间是否匹配此Cron表达式nextExecution(ZonedDateTime from) Gets the next execution time after the given time 获取给定时间之后的下次执行时间nextExecution(ZonedDateTime from, int maxYears) Gets the next execution time with configurable search window 获取可配置搜索窗口的下次执行时间nextExecution(ZonedDateTime from, Predicate<ZonedDateTime> filter) Gets the next execution time that satisfies a filter 获取满足过滤条件的下次执行时间nextExecutions(ZonedDateTime from, int count) Gets the next N execution times after the given time 获取给定时间之后的下N次执行时间nextOverlap(CronExpression other, ZonedDateTime from) Finds the next time both this and another expression fire simultaneously 查找此表达式与另一个表达式同时触发的下一个时间static CronExpressionParse a cron expression 解析Cron表达式Gets the previous execution time before the given time 获取给定时间之前的上次执行时间previousExecution(ZonedDateTime from, int maxYears) Gets the previous execution time with configurable search window 获取可配置搜索窗口的上次执行时间previousExecution(ZonedDateTime from, Predicate<ZonedDateTime> filter) Gets the previous execution time that satisfies a filter 获取满足过滤条件的上次执行时间previousExecutions(ZonedDateTime from, int count) Gets the previous N execution times before the given time 获取给定时间之前的前N次执行时间reverseStream(ZonedDateTime from) Returns a lazy, ordered stream of past execution times (newest first) 返回一个惰性的、有序的过去执行时间流(最新在前)stream(ZonedDateTime from) Returns a lazy, ordered stream of future execution times 返回一个惰性的、有序的未来执行时间流Gets the duration since the last execution 获取距上次执行的时间间隔Gets the duration until the next execution 获取距下次执行的时间间隔toString()
-
Method Details
-
parse
Parse a cron expression 解析Cron表达式Supports 5-field, 6-field formats and macros (@yearly, @daily, etc.).
支持5字段、6字段格式和宏(@yearly、@daily 等)。
- Parameters:
expression- the cron expression | Cron表达式- Returns:
- the parsed expression | 解析后的表达式
- Throws:
OpenCronException- if the expression is invalid | 如果表达式无效
-
matches
Check if a time matches this cron expression 检查时间是否匹配此Cron表达式- Parameters:
time- the time to check | 要检查的时间- Returns:
- true if the time matches | 如果匹配返回true
-
nextExecution
Gets the next execution time after the given time 获取给定时间之后的下次执行时间- Parameters:
from- the start time | 开始时间- Returns:
- the next execution time, or null if none within 4 years | 下次执行时间,如果4年内没有则返回null
-
nextExecution
Gets the next execution time with configurable search window 获取可配置搜索窗口的下次执行时间- Parameters:
from- the start time | 开始时间maxYears- the maximum years to search (1-100) | 最大搜索年数(1-100)- Returns:
- the next execution time, or null if none within maxYears | 下次执行时间
- Throws:
IllegalArgumentException- if maxYears is not in range 1-100 | 如果maxYears不在1-100范围内
-
nextExecutions
Gets the next N execution times after the given time 获取给定时间之后的下N次执行时间- Parameters:
from- the start time | 开始时间count- the number of executions | 执行次数- Returns:
- the list of execution times | 执行时间列表
- Throws:
IllegalArgumentException- if count is not positive | 如果count不是正数
-
previousExecution
Gets the previous execution time before the given time 获取给定时间之前的上次执行时间- Parameters:
from- the reference time | 参考时间- Returns:
- the previous execution time, or null if none within 4 years | 上次执行时间,如果4年内没有则返回null
-
previousExecution
Gets the previous execution time with configurable search window 获取可配置搜索窗口的上次执行时间- Parameters:
from- the reference time | 参考时间maxYears- the maximum years to search (1-100) | 最大搜索年数(1-100)- Returns:
- the previous execution time, or null if none within maxYears | 上次执行时间
- Throws:
IllegalArgumentException- if maxYears is not in range 1-100 | 如果maxYears不在1-100范围内
-
previousExecutions
Gets the previous N execution times before the given time 获取给定时间之前的前N次执行时间- Parameters:
from- the reference time | 参考时间count- the number of executions | 执行次数- Returns:
- the list of execution times (newest first) | 执行时间列表(最新在前)
- Throws:
IllegalArgumentException- if count is not positive | 如果count不是正数
-
timeToNextExecution
Gets the duration until the next execution 获取距下次执行的时间间隔- Parameters:
from- the reference time | 参考时间- Returns:
- the duration to next execution, or null if none within search window | 距下次执行的Duration
-
timeFromLastExecution
Gets the duration since the last execution 获取距上次执行的时间间隔- Parameters:
from- the reference time | 参考时间- Returns:
- the duration from last execution, or null if none within search window | 距上次执行的Duration
-
countExecutionsBetween
Counts executions between two times 计算两个时间点之间的执行次数The maximum count is capped at 1,000,000 to prevent excessive computation. If the count reaches this limit, 1,000,000 is returned (which may be an undercount).
最大计数上限为1,000,000以防止过度计算。如果达到此限制,返回1,000,000(可能是不完整的计数)。
- Parameters:
from- the start time (exclusive) | 开始时间(不包含)to- the end time (inclusive) | 结束时间(包含)- Returns:
- the count of executions (capped at 1,000,000) | 执行次数(上限1,000,000)
- Throws:
IllegalArgumentException- if from is not before to | 如果from不在to之前
-
executionsBetween
Lists all executions between two times 列出两个时间点之间的所有执行时间- Parameters:
from- the start time (exclusive) | 开始时间(不包含)to- the end time (inclusive) | 结束时间(包含)- Returns:
- unmodifiable list of execution times | 不可修改的执行时间列表
- Throws:
IllegalArgumentException- if from is not before to | 如果from不在to之前
-
executionsBetween
Lists executions between two times with a limit 列出两个时间点之间的执行时间(带限制)- Parameters:
from- the start time (exclusive) | 开始时间(不包含)to- the end time (inclusive) | 结束时间(包含)limit- the maximum number of results (1-1_000_000) | 最大结果数- Returns:
- unmodifiable list of execution times | 不可修改的执行时间列表
- Throws:
IllegalArgumentException- if from is not before to, or limit is out of range | 如果from不在to之前或limit超出范围
-
isEquivalentTo
Checks if this expression is structurally equivalent to another 检查此表达式是否与另一个结构等价Compares internal parsed state (BitSets, special fields, and field count), not the original expression strings. Note: a 5-field expression and a 6-field expression with second=0 produce the same schedule, but are considered structurally different (hasSeconds differs).
比较内部解析状态(BitSet、特殊字段和字段数),而非原始表达式字符串。 注意:5字段表达式和秒=0的6字段表达式产生相同调度,但被视为结构不同(hasSeconds不同)。
- Parameters:
other- the other expression | 另一个表达式- Returns:
- true if equivalent schedules | 如果调度等价返回true
-
explain
Gets a comprehensive explanation for debugging 获取用于调试的综合解释信息The estimated interval is
Duration.ZEROwhen fewer than 2 upcoming executions can be found within the search window.当搜索窗口内找到的即将执行次数少于2次时,预估间隔为
Duration.ZERO。- Parameters:
from- the reference time for next executions | 用于计算下次执行的参考时间- Returns:
- the explanation | 解释信息
-
stream
Returns a lazy, ordered stream of future execution times 返回一个惰性的、有序的未来执行时间流The stream is computed lazily — each element is calculated on demand. Use
.limit(),.takeWhile(),.filter()etc. to control iteration.流是惰性计算的——每个元素按需计算。 使用
.limit()、.takeWhile()、.filter()等控制迭代。Examples | 示例:
// Next 10 executions | 下10次执行 expr.stream(now).limit(10).toList(); // All executions before deadline | deadline之前的所有执行 expr.stream(now).takeWhile(t -> t.isBefore(deadline)).toList();- Parameters:
from- the start time (exclusive) | 开始时间(不包含)- Returns:
- an ordered, sequential stream of execution times | 有序的顺序执行时间流
-
reverseStream
Returns a lazy, ordered stream of past execution times (newest first) 返回一个惰性的、有序的过去执行时间流(最新在前)The stream is computed lazily — each element is calculated on demand.
流是惰性计算的——每个元素按需计算。
- Parameters:
from- the reference time (exclusive) | 参考时间(不包含)- Returns:
- an ordered, sequential stream of past execution times | 有序的顺序过去执行时间流
-
nextExecution
Gets the next execution time that satisfies a filter 获取满足过滤条件的下次执行时间Skips execution times that do not pass the filter predicate. Stops after 10,000 skipped candidates to prevent infinite loops.
跳过不满足过滤谓词的执行时间。跳过10,000个候选后停止以防止无限循环。
Examples | 示例:
// Skip weekends | 跳过周末 expr.nextExecution(now, t -> t.getDayOfWeek().getValue() <= 5); // Skip holidays | 跳过节假日 Set<LocalDate> holidays = Set.of(LocalDate.of(2026, 1, 1)); expr.nextExecution(now, t -> !holidays.contains(t.toLocalDate()));- Parameters:
from- the start time (exclusive) | 开始时间(不包含)filter- the filter predicate — returns true to accept, false to skip | 过滤谓词- Returns:
- the next matching execution time, or null if none found | 下次匹配的执行时间
-
previousExecution
Gets the previous execution time that satisfies a filter 获取满足过滤条件的上次执行时间Skips execution times that do not pass the filter predicate. Stops after 10,000 skipped candidates to prevent infinite loops.
跳过不满足过滤谓词的执行时间。跳过10,000个候选后停止以防止无限循环。
- Parameters:
from- the reference time (exclusive) | 参考时间(不包含)filter- the filter predicate — returns true to accept, false to skip | 过滤谓词- Returns:
- the previous matching execution time, or null if none found | 上次匹配的执行时间
-
nextOverlap
Finds the next time both this and another expression fire simultaneously 查找此表达式与另一个表达式同时触发的下一个时间Iterates forward through both schedules to find the first overlap. Returns null if no overlap is found within 4 years.
正向遍历两个调度以找到第一个重叠时间。如果4年内找不到重叠则返回null。
- Parameters:
other- the other cron expression | 另一个Cron表达式from- the start time (exclusive) | 开始时间(不包含)- Returns:
- the next overlapping execution time, or null | 下一个重叠执行时间
-
hasOverlapBetween
Checks if this and another expression have overlapping executions in a time range 检查此表达式与另一个表达式在时间范围内是否有重叠执行- Parameters:
other- the other cron expression | 另一个Cron表达式from- the start time (exclusive) | 开始时间(不包含)to- the end time (inclusive) | 结束时间(包含)- Returns:
- true if there is at least one overlapping execution | 如果存在重叠返回true
-
adjustInto
Adjusts the temporal to the next execution time of this cron expression 将时间调节为此Cron表达式的下次执行时间Enables idiomatic usage with
java.time:支持
java.time的惯用写法:ZonedDateTime next = ZonedDateTime.now().with(cronExpr);- Specified by:
adjustIntoin interfaceTemporalAdjuster- Parameters:
temporal- the temporal to adjust | 要调节的时间- Returns:
- the next execution time | 下次执行时间
- Throws:
DateTimeException- if no execution found within search window | 如果搜索窗口内找不到执行时间
-
describe
Gets a human-readable description of this expression 获取此表达式的人类可读描述- Returns:
- the description in English | 英文描述
-
describe
Gets a human-readable description in the specified locale 获取指定语言的人类可读描述- Parameters:
locale- the locale (supports CHINESE/SIMPLIFIED_CHINESE for Chinese, others default to English) 语言(支持CHINESE/SIMPLIFIED_CHINESE返回中文,其他默认英文)- Returns:
- the localized description | 本地化描述
-
getExpression
Gets the original expression string 获取原始表达式字符串- Returns:
- the expression | 表达式
-
hasSeconds
public boolean hasSeconds()Checks if this expression uses 6-field format (with seconds) 检查此表达式是否使用6字段格式(含秒)- Returns:
- true if 6-field format | 如果是6字段格式返回true
-
equals
-
hashCode
-
toString
-