X-Git-Url: https://git.giacomolli.uk/onechat/blobdiff_plain/f5c601f1801aaa276f8c335fcb51c373edc0b50c..42b4acd4ba70d3c12da4513d139717e592eefe4a:/schedule_cron.go?ds=sidebyside diff --git a/schedule_cron.go b/schedule_cron.go index 3255f99..bf1424f 100644 --- a/schedule_cron.go +++ b/schedule_cron.go @@ -154,6 +154,31 @@ func (c ScheduleCron) gap() int { return gap } +// 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 +// 03:00. A wall time that the clock repeats, at the end of daylight saving +// time, is its first occurrence, as in cron. +func scheduleWallTime(year int, month time.Month, day, hour, minute int, location *time.Location) time.Time { + t := time.Date(year, month, day, hour, minute, 0, 0, location) + _, before := t.Add(-3 * time.Hour).Zone() + _, offset := t.Zone() + if t.Hour() != hour || t.Minute() != minute || t.Day() != day { + wall := time.Date(year, month, day, hour, minute, 0, 0, time.UTC) + + return wall.Add(-time.Duration(before) * time.Second).In(location) + } + + if before > offset { + earlier := t.Add(-time.Duration(before-offset) * time.Second) + if earlier.Day() == day && earlier.Hour() == hour && earlier.Minute() == minute { + return earlier + } + } + + return t +} + // 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 @@ -209,31 +234,6 @@ func scheduleParseCron(expression string) (ScheduleCron, error) { 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 -// 03:00. A wall time that the clock repeats, at the end of daylight saving -// time, is its first occurrence, as in cron. -func scheduleWallTime(year int, month time.Month, day, hour, minute int, location *time.Location) time.Time { - t := time.Date(year, month, day, hour, minute, 0, 0, location) - _, before := t.Add(-3 * time.Hour).Zone() - _, offset := t.Zone() - if t.Hour() != hour || t.Minute() != minute || t.Day() != day { - wall := time.Date(year, month, day, hour, minute, 0, 0, time.UTC) - - return wall.Add(-time.Duration(before) * time.Second).In(location) - } - - if before > offset { - earlier := t.Add(-time.Duration(before-offset) * time.Second) - if earlier.Day() == day && earlier.Hour() == hour && earlier.Minute() == minute { - return earlier - } - } - - return t -} - // scheduleCronField returns the set of the values of one field, from low to // high. func scheduleCronField(field string, low, high int) (uint64, error) { @@ -277,7 +277,7 @@ func scheduleCronField(field string, low, high int) (uint64, error) { first, err = scheduleCronNumber(base, low, high) if err != nil { - return 0, err + return 0, fmt.Errorf("parse cron field value: %w", err) } last = first