]> git.giacomolli.uk - onechat/blobdiff - schedule_cron.go
Separate multiline Go statements
[onechat] / schedule_cron.go
index 91fe8ce8b58e2be552af7138136b945f3b6e114c..3255f99571fdbd968f08352c0c7cbd451012f8c0 100644 (file)
@@ -53,61 +53,6 @@ var scheduleCronFields = []struct {
        },
 }
 
-// scheduleParseCron parses a cron expression of five fields: minute, hour, day
-// of month, month, and day of week, where 0 and 7 are Sunday. A field is a
-// comma list of items, and an item is *, N, or N-M, where * and N-M can have a
-// step /S. Names, macros, the characters ? L W #, and N/S are errors.
-//
-// It refuses an expression whose runs can be less than scheduleCronGap minutes
-// apart. The check takes the wall times of one day from the hour and the minute
-// fields, and the gap across midnight as if the next day matches too. It also
-// refuses an expression that matches no day in scheduleCronYears years, such as
-// one on February 30.
-func scheduleParseCron(expression string) (ScheduleCron, error) {
-       fields := strings.Fields(expression)
-       if len(fields) != len(scheduleCronFields) {
-               return ScheduleCron{}, fmt.Errorf("the cron expression %q has %d fields, not 5: minute, hour, day of month, month, day of week", expression, len(fields))
-       }
-
-       var sets [5]uint64
-
-       for index, field := range fields {
-               set, err := scheduleCronField(field, scheduleCronFields[index].low, scheduleCronFields[index].high)
-               if err != nil {
-                       return ScheduleCron{}, fmt.Errorf("the %s field of %q: %w", scheduleCronFields[index].name, expression, err)
-               }
-
-               sets[index] = set
-       }
-
-       c := ScheduleCron{
-               minutes:     sets[0],
-               hours:       sets[1],
-               days:        sets[2],
-               months:      sets[3],
-               weekdays:    sets[4],
-               anyDay:      strings.HasPrefix(fields[2], "*"),
-               anyWeekday:  strings.HasPrefix(fields[4], "*"),
-               description: strings.Join(fields, " "),
-       }
-
-       if c.weekdays&(1<<7) != 0 {
-               c.weekdays |= 1
-       }
-
-       if c.gap() < scheduleCronGap {
-               return ScheduleCron{}, fmt.Errorf("the runs of %q can be less than %d minutes apart: the runs of a schedule must be at least %d minutes apart", expression, scheduleCronGap, scheduleCronGap)
-       }
-
-       start := time.Date(2024, time.January, 1, 0, 0, 0, 0, time.UTC)
-       _, found := c.Next(start)
-       if !found {
-               return ScheduleCron{}, fmt.Errorf("the cron expression %q matches no day in %d years", expression, scheduleCronYears)
-       }
-
-       return c, nil
-}
-
 // ScheduleCron is a parsed cron expression. Each set holds a bit for each value
 // of its field. anyDay and anyWeekday tell that the day field or the weekday
 // field starts with *. When neither does, a day matches when either field
@@ -209,6 +154,61 @@ func (c ScheduleCron) gap() int {
        return gap
 }
 
+// scheduleParseCron parses a cron expression of five fields: minute, hour, day
+// of month, month, and day of week, where 0 and 7 are Sunday. A field is a
+// comma list of items, and an item is *, N, or N-M, where * and N-M can have a
+// step /S. Names, macros, the characters ? L W #, and N/S are errors.
+//
+// It refuses an expression whose runs can be less than scheduleCronGap minutes
+// apart. The check takes the wall times of one day from the hour and the minute
+// fields, and the gap across midnight as if the next day matches too. It also
+// refuses an expression that matches no day in scheduleCronYears years, such as
+// one on February 30.
+func scheduleParseCron(expression string) (ScheduleCron, error) {
+       fields := strings.Fields(expression)
+       if len(fields) != len(scheduleCronFields) {
+               return ScheduleCron{}, fmt.Errorf("the cron expression %q has %d fields, not 5: minute, hour, day of month, month, day of week", expression, len(fields))
+       }
+
+       var sets [5]uint64
+
+       for index, field := range fields {
+               set, err := scheduleCronField(field, scheduleCronFields[index].low, scheduleCronFields[index].high)
+               if err != nil {
+                       return ScheduleCron{}, fmt.Errorf("the %s field of %q: %w", scheduleCronFields[index].name, expression, err)
+               }
+
+               sets[index] = set
+       }
+
+       c := ScheduleCron{
+               minutes:     sets[0],
+               hours:       sets[1],
+               days:        sets[2],
+               months:      sets[3],
+               weekdays:    sets[4],
+               anyDay:      strings.HasPrefix(fields[2], "*"),
+               anyWeekday:  strings.HasPrefix(fields[4], "*"),
+               description: strings.Join(fields, " "),
+       }
+
+       if c.weekdays&(1<<7) != 0 {
+               c.weekdays |= 1
+       }
+
+       if c.gap() < scheduleCronGap {
+               return ScheduleCron{}, fmt.Errorf("the runs of %q can be less than %d minutes apart: the runs of a schedule must be at least %d minutes apart", expression, scheduleCronGap, scheduleCronGap)
+       }
+
+       start := time.Date(2024, time.January, 1, 0, 0, 0, 0, time.UTC)
+       _, found := c.Next(start)
+       if !found {
+               return ScheduleCron{}, fmt.Errorf("the cron expression %q matches no day in %d years", expression, scheduleCronYears)
+       }
+
+       return c, nil
+}
+
 // scheduleWallTime returns the time of a wall time in location. A wall time
 // that the clock skips, at the start of daylight saving time, is later by the
 // length of the skip: 02:30 becomes 03:30 when the clock goes from 02:00 to