Updraft::Schedule::CronExpression
Builds a cron expression from a described intent and a named time zone, so a template can say “03:00 in Toronto, weekdays only” instead of a UTC field string that silently drifts by an hour twice a year.
Ref returns
The expressioncron(0 7 ? * MON-FRI *)Fn::GetAtt
7
attributesMinimal template
Every required property, nothing elseResources:
NightlyBackup:
Type: Updraft::Schedule::CronExpression
Properties:
Behavior: Daily
Time: "03:00"
TimeZone: America/Toronto{
"Resources": {
"NightlyBackup": {
"Type": "Updraft::Schedule::CronExpression",
"Properties": {
"Behavior": "Daily",
"Time": "03:00",
"TimeZone": "America/Toronto"
}
}
}
}import { CfnResource } from 'aws-cdk-lib';
const nightly = new CfnResource(this, 'NightlyBackup', {
type: 'Updraft::Schedule::CronExpression',
properties: {
Behavior: 'Daily',
Time: '03:00',
TimeZone: 'America/Toronto',
},
});
// nightly.getAtt('Expression').toString() -> "cron(0 7 * * ? *)"
Fn::GetAtt on Expression. It is already wrapped in
cron(...), so it drops straight into an EventBridge ScheduleExpression.Overview #
Cron expressions describe when badly. They have no time zone, three
incompatible dialects across AWS services, and a day-of-week field whose
numbering differs between them. The gap between “run at 3am Toronto time on
weekdays” and cron(0 7 ? * MON-FRI *) is small enough to cross by hand and
large enough to get wrong.
This resource takes the intent and emits the expression, along with a plain-English description you can check in review.
What it generates #
Intent
Resources:
NightlyBackup:
Type: Updraft::Schedule::CronExpression
Properties:
Behavior: Weekly
DaysOfWeek: [MON, TUE, WED, THU, FRI]
Time: "03:00"
TimeZone: America/Toronto
DaylightSaving: PinStandard
Jitter: 10
Result
Expression: "cron(7 8 ? * MON-FRI *)"
UtcTime: "08:07"
UtcOffsetMinutes: -300
ObservesDaylightSaving: true
LocalDescription: >-
Every weekday at 03:07 America/Toronto
(08:07 UTC, pinned to standard time)
NextOccurrences:
- "2026-08-10T08:07:00Z"
- "2026-08-11T08:07:00Z"
- "2026-08-12T08:07:00Z"
The seven minutes of jitter come from hashing the stack ID. The same stack lands on the same minute every deployment; a different stack lands somewhere else.
Using it with EventBridge #
Expression is already wrapped in cron(...) for the EventBridge dialect, so
it drops straight in:
Resources:
NightlyBackup:
Type: Updraft::Schedule::CronExpression
Properties:
Behavior: Daily
Time: "03:00"
TimeZone: UTC
BackupRule:
Type: AWS::Events::Rule
Properties:
ScheduleExpression: !GetAtt NightlyBackup.Expression
State: ENABLED
Targets:
- Id: backup-lambda
Arn: !GetAtt BackupFunction.Arn
Outputs:
BackupSchedule:
Description: Human-readable form of the backup schedule, for review.
Value: !GetAtt NightlyBackup.LocalDescription
Properties
Expand a row for the full reference; nested types open in placeBehavior StringThe shape of the schedule, which determines which other properties apply. Required No interruption — updates in place
Each behavior consumes a different subset of the remaining properties. A property that does not apply to the chosen behavior is rejected rather than ignored, so a misplaced
DaysOfWeekfails the stack instead of quietly doing nothing.Behavior Uses DailyTimeWeeklyTime,DaysOfWeekMonthlyTime,DayOfMonthEveryNHoursInterval,Time(as the offset within the hour)EveryNMinutesIntervalBusinessHoursTime,EndTime,DaysOfWeek,IntervalCustomExpression- Type
String- Required
- Yes
- Update behaviour
- No interruption
Allowed values
DailyWeeklyMonthlyEveryNHoursEveryNMinutesBusinessHoursCustom
Example values
Daily
TimeZone StringIANA time zone name that Time is expressed in. Required No interruption — updates in place
The zone is resolved against the IANA database at stack-operation time and converted to a fixed UTC expression.- Type
String- Required
- Yes
- Update behaviour
- No interruption
- Pattern
^([A-Za-z_]+/[A-Za-z_+\-0-9/]+|UTC)$IANA zone name. Fixed offsets such as `-05:00` are deliberately not accepted.
Example values
America/TorontoEurope/LondonUTC
DayOfMonth StringDay of the month, or L for the last day. Conditional No interruption — updates in place
Days 29 to 31 simply do not fire in months that lack them; EventBridge does not clamp. UseLfor “end of month” rather than31.- Type
String- Required
- ConditionalRequired for
Monthly. - Update behaviour
- No interruption
- Pattern
^(L|[1-9]|[12]\d|3[01])$
Example values
115L
DaysOfWeek Array of StringDays the schedule fires on. Conditional No interruption — updates in place
Days the schedule fires on.
- Type
Array of String- Required
- ConditionalRequired for
Weekly. Optional forBusinessHours, where it defaults to Monday–Friday. - Update behaviour
- No interruption
- Items
1 – 7must be unique
Allowed values
MONTUEWEDTHUFRISATSUN
Example values
["MON","TUE","WED","THU","FRI"]
EndTime StringLocal end of the window for BusinessHours, exclusive. Conditional No interruption — updates in place
Local end of the window for BusinessHours, exclusive.
- Type
String- Required
- ConditionalRequired for
BusinessHours. - Update behaviour
- No interruption
- Pattern
^([01]\d|2[0-3]):([0-5]\d)$
Example values
17:00
Expression StringA raw six-field cron expression, validated and passed through. Conditional No interruption — updates in place
Escape hatch for schedules the other behaviors cannot express. The expression is still parsed and validated, andNextOccurrencesis still computed, soCustomdoes not mean unchecked.- Type
String- Required
- ConditionalRequired for
Custom. - Update behaviour
- No interruption
Example values
0 7 ? * MON-FRI *
Interval IntegerRepeat interval, in the unit implied by Behavior. Conditional No interruption — updates in place
ForEveryNHoursthe interval must divide 24 evenly, otherwise the schedule skips at midnight.5is rejected for that reason;6and8are fine.- Type
Integer- Required
- ConditionalRequired for
EveryNHours,EveryNMinutes, andBusinessHours. - Update behaviour
- No interruption
- Range
1 – 23
Example values
6
Time StringLocal time of day in 24-hour HH:MM. Conditional No interruption — updates in place
ForEveryNHoursthis is interpreted as the offset within each hour, soTime: "00:20"withInterval: 6fires at 00:20, 06:20, 12:20 and 18:20.- Type
String- Required
- ConditionalRequired for
Daily,Weekly,Monthly, andBusinessHours. - Update behaviour
- No interruption
- Pattern
^([01]\d|2[0-3]):([0-5]\d)$24-hour clock, zero-padded.
Example values
03:0023:30
DaylightSaving StringHow to handle a zone whose UTC offset changes during the year. No interruption — updates in place
Reject— fail the stack operation if the zone observes DST. Forces the decision to be made explicitly, in the template, by whoever can judge it.PinStandard— always use the zone’s standard-time offset. The schedule is an hour late during summer time, and never moves.PinCurrent— use whichever offset is in effect on the deployment date. The schedule is correct today and wrong in six months.SplitExpressions— emit two expressions inExpressionSet, one per offset, each with a month range. Correct all year, but requires the consumer to accept a list of schedules.
- Type
String- Required
- No
- Update behaviour
- No interruption
- Default
Reject
Allowed values
RejectPinStandardPinCurrentSplitExpressions
Jitter IntegerDeterministic spread, in minutes, applied to the computed time. No interruption — updates in place
The offset is derived by hashingJitterSeed, so it is stable across deployments — the same stack always lands on the same minute. This spreads a fleet of identically-scheduled stacks without making any single stack’s schedule unpredictable.- Type
Integer- Required
- No
- Update behaviour
- No interruption
- Default
0- Range
−∞ – 59
JitterSeed StringSeed for the jitter hash. Defaults to the stack ID. No interruption — updates in place
Give two stacks the same seed and they land on the same minute — occasionally useful when two schedules must stay aligned.- Type
String- Required
- No
- Update behaviour
- No interruption
Example values
${AWS::StackId}
Target StringWhich service will consume the expression, which changes its syntax. No interruption — updates in place
EventBridge cron takes six fields and wraps them incron(...). Auto Scaling takes five fields, unwrapped, and treats day-of-week0as Sunday. Emitting the wrong dialect is one of the more tedious ways to lose an afternoon, so the resource emits the right one.- Type
String- Required
- No
- Update behaviour
- No interruption
- Default
EventBridge
Allowed values
EventBridgeAutoScalingBackupSSM
| Property | Type | Required | Update | Description |
|---|---|---|---|---|
| Behavior | String | Yes | None | The shape of the schedule, which determines which other properties apply. |
| TimeZone | String | Yes | None | IANA time zone name that Time is expressed in. |
| DayOfMonth | String | Conditional | None | Day of the month, or L for the last day. |
| DaysOfWeek | Array of String | Conditional | None | Days the schedule fires on. |
| EndTime | String | Conditional | None | Local end of the window for BusinessHours, exclusive. |
| Expression | String | Conditional | None | A raw six-field cron expression, validated and passed through. |
| Interval | Integer | Conditional | None | Repeat interval, in the unit implied by Behavior. |
| Time | String | Conditional | None | Local time of day in 24-hour HH:MM. |
| DaylightSaving | String | No | None | How to handle a zone whose UTC offset changes during the year. |
| Jitter | Integer | No | None | Deterministic spread, in minutes, applied to the computed time. |
| JitterSeed | String | No | None | Seed for the jitter hash. Defaults to the stack ID. |
| Target | String | No | None | Which service will consume the expression, which changes its syntax. |
Generated from the schema. The first pair shows only required and conditionally-required properties — a template you can paste and deploy. Property keys are ordered alphabetically here rather than required-first, because that is the order a template file conventionally uses.
Type: Updraft::Schedule::CronExpression
Properties:
Behavior: Daily
DayOfMonth: '1'
DaysOfWeek:
- String
EndTime: '17:00'
Expression: 0 7 ? * MON-FRI *
Interval: '6'
Time: '03:00'
TimeZone: America/Toronto{
"Type": "Updraft::Schedule::CronExpression",
"Properties": {
"Behavior": "Daily",
"DayOfMonth": "1",
"DaysOfWeek": [
"String"
],
"EndTime": "17:00",
"Expression": "0 7 ? * MON-FRI *",
"Interval": "6",
"Time": "03:00",
"TimeZone": "America/Toronto"
}
}Every property, three levels deep:
Type: Updraft::Schedule::CronExpression
Properties:
Behavior: Daily
DayOfMonth: '1'
DaylightSaving: Reject
DaysOfWeek:
- String
EndTime: '17:00'
Expression: 0 7 ? * MON-FRI *
Interval: '6'
Jitter: 0
JitterSeed: ${AWS::StackId}
Target: EventBridge
Time: '03:00'
TimeZone: America/Toronto{
"Type": "Updraft::Schedule::CronExpression",
"Properties": {
"Behavior": "Daily",
"DayOfMonth": "1",
"DaylightSaving": "Reject",
"DaysOfWeek": [
"String"
],
"EndTime": "17:00",
"Expression": "0 7 ? * MON-FRI *",
"Interval": "6",
"Jitter": 0,
"JitterSeed": "${AWS::StackId}",
"Target": "EventBridge",
"Time": "03:00",
"TimeZone": "America/Toronto"
}
}Return values
What other resources can read from this oneRefFn::GetAtt [ Schedule, Expression ], so it can be dropped straight into a
ScheduleExpression property.!Ref MyResource
→
cron(0 7 ? * MON-FRI *)
Fn::GetAtt attributes
| Attribute | Type | Description | Example value |
|---|---|---|---|
| Expression | String | The generated expression, in the dialect selected by Target. | cron(0 7 ? * MON-FRI *) |
| ExpressionSet | Array | All generated expressions. One entry unless DaylightSaving is SplitExpressions. | ["cron(0 8 ? * MON-FRI *)","cron(0 7 ? * MON-FRI *)"] |
| LocalDescription | String | A plain-English rendering of the schedule. Put it in a stack output — it is the fastest way to catch a wrong schedule during review. | Every weekday at 03:00 America/Toronto (07:00 UTC during standard time) |
| NextOccurrences | Array | The next five fire times in UTC, computed at deploy time. | ["2026-08-10T07:00:00Z","2026-08-11T07:00:00Z"] |
| ObservesDaylightSaving | Boolean | Whether the named zone changes offset during the year. | true |
| UtcOffsetMinutes | Integer | The zone offset applied, in minutes east of UTC. | -300 |
| UtcTime | String | The computed UTC time of day, for eyeballing against the local time you asked for. | 07:00 |
Required permissions
For the principal running the stack operationThis type makes no AWS API calls. It is computed entirely from its own properties during the stack operation, so it needs no permissions beyond those CloudFormation already holds to manage the stack.