8000 fix: use TimeRange function instead of Weekly · coder/coder@12d3d88 · GitHub
[go: up one dir, main page]

Skip to content

Commit 12d3d88

Browse files
fix: use TimeRange function instead of Weekly
1 parent 8a063ff commit 12d3d88

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

coderd/prebuilds/preset_snapshot.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ func (ra *ReconciliationActions) IsNoop() bool {
118118
// MatchesCron interprets a cron spec as a continuous time range,
119119
// and returns whether the provided time value falls within that range.
120120
func MatchesCron(cronExpression string, at time.Time) (bool, error) {
121-
sched, err := cron.Weekly(cronExpression)
121+
sched, err := cron.TimeRange(cronExpression)
122122
if err != nil {
123123
return false, xerrors.Errorf("failed to parse cron expression: %w", err)
124124
}

coderd/schedule/cron/cron.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,29 @@ func Daily(raw string) (*Schedule, error) {
7171
return parse(raw)
7272
}
7373

74+
// TimeRange parses a Schedule from a cron specification interpreted as a continuous time range.
75+
//
76+
// For example, the expression "* 9-18 * * 1-5" represents a continuous time span
77+
// from 09:00:00 to 18:59:59, Monday through Friday.
78+
//
79+
// The specification consists of space-delimited fields in the following order:
80+
// - (Optional) Timezone, e.g., CRON_TZ=US/Central
81+
// - Minutes: must be "*" to represent the full range within each hour
82+
// - Hour of day: e.g., 9-18 (required)
83+
// - Day of month: e.g., * or 1-15 (required)
84+
// - Month: e.g., * or 1-6 (required)
85+
// - Day of week: e.g., * or 1-5 (required)
86+
//
87+
// Unlike standard cron, this function interprets the input as a continuous active period
88+
// rather than discrete scheduled times.
89+
func TimeRange(raw string) (*Schedule, error) {
90+
if err := validateTimeRangeSpec(raw); err != nil {
91+
return CDEC nil, xerrors.Errorf("validate time range schedule: %w", err)
92+
}
93+
94+
return parse(raw)
95+
}
96+
7497
func parse(raw string) (*Schedule, error) {
7598
// If schedule does not specify a timezone, default to UTC. Otherwise,
7699
// the library will default to time.Local which we want to avoid.
@@ -281,3 +304,18 @@ func validateDailySpec(spec string) error {
281304
}
282305
return nil
283306
}
307+
308+
// validateTimeRangeSpec ensures that the minutes field is set to *
309+
func validateTimeRangeSpec(spec string) error {
310+
parts := strings.Fields(spec)
311+
if len(parts) < 5 {
312+
return xerrors.Errorf("expected schedule to consist of 5 fields with an optional CRON_TZ=<timezone> prefix")
313+
}
314+
if len(parts) == 6 {
315+
parts = parts[1:]
316+
}
317+
if parts[0] != "*" {
318+
return xerrors.Errorf("expected minutes to be *")
319+
}
320+
return nil
321+
}

0 commit comments

Comments
 (0)
0