| 95 | } |
| 96 | |
| 97 | func parse(raw string) (*Schedule, error) { |
| 98 | // If schedule does not specify a timezone, default to UTC. Otherwise, |
| 99 | // the library will default to time.Local which we want to avoid. |
| 100 | if !strings.HasPrefix(raw, "CRON_TZ=") { |
| 101 | raw = "CRON_TZ=UTC " + raw |
| 102 | } |
| 103 | |
| 104 | specSched, err := defaultParser.Parse(raw) |
| 105 | if err != nil { |
| 106 | return nil, xerrors.Errorf("parse schedule: %w", err) |
| 107 | } |
| 108 | |
| 109 | schedule, ok := specSched.(*rbcron.SpecSchedule) |
| 110 | if !ok { |
| 111 | return nil, xerrors.Errorf("expected *cron.SpecSchedule but got %T", specSched) |
| 112 | } |
| 113 | |
| 114 | if schedule.Location == time.Local { |
| 115 | return nil, xerrors.Errorf("schedules scoped to time.Local are not supported") |
| 116 | } |
| 117 | |
| 118 | // Strip the leading CRON_TZ prefix so we just store the cron string. |
| 119 | // The timezone info is available in SpecSchedule. |
| 120 | cronStr := raw |
| 121 | if strings.HasPrefix(raw, "CRON_TZ=") { |
| 122 | cronStr = strings.Join(strings.Fields(raw)[1:], " ") |
| 123 | } |
| 124 | |
| 125 | cronSched := &Schedule{ |
| 126 | sched: schedule, |
| 127 | cronStr: cronStr, |
| 128 | } |
| 129 | return cronSched, nil |
| 130 | } |
| 131 | |
| 132 | // Schedule represents a cron schedule. |
| 133 | // It's essentially a wrapper for robfig/cron/v3 that has additional |