Skip to content

Commit 377b708

Browse files
committed
improve time parsing
1 parent 0884e0c commit 377b708

File tree

2 files changed

+38
-17
lines changed

2 files changed

+38
-17
lines changed

cli/autostart.go

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ import (
1515
)
1616

1717
const autostartDescriptionLong = `To have your workspace build automatically at a regular time you can enable autostart.
18-
When enabling autostart, enter a schedule in the format: start-time [day-of-week] [timezone].
18+
When enabling autostart, enter a schedule in the format: start-time [day-of-week] [location].
1919
* Start-time (required) is accepted either in 12-hour (hh:mm{am|pm}) format, or 24-hour format hh:mm.
2020
* Day-of-week (optional) allows specifying in the cron format, e.g. 1,3,5 or Mon-Fri.
2121
Aliases such as @daily are not supported.
2222
Default: * (every day)
23-
* Timezone (optional) must be a valid location in the IANA timezone database.
23+
* Location (optional) must be a valid location in the IANA timezone database.
2424
If omitted, we will fall back to either the TZ environment variable or /etc/localtime.
2525
You can check your corresponding location by visiting https://ipinfo.io - it shows in the demo widget on the right.
2626
`
@@ -85,7 +85,7 @@ func autostartShow() *cobra.Command {
8585

8686
func autostartSet() *cobra.Command {
8787
cmd := &cobra.Command{
88-
Use: "set <workspace_name> <start-time> [day-of-week] [timezone]",
88+
Use: "set <workspace_name> <start-time> [day-of-week] [location]",
8989
Args: cobra.RangeArgs(2, 4),
9090
RunE: func(cmd *cobra.Command, args []string) error {
9191
client, err := createClient(cmd)
@@ -156,6 +156,7 @@ func autostartUnset() *cobra.Command {
156156

157157
var errInvalidScheduleFormat = xerrors.New("Schedule must be in the format Mon-Fri 09:00AM America/Chicago")
158158
var errInvalidTimeFormat = xerrors.New("Start time must be in the format hh:mm[am|pm] or HH:MM")
159+
var errUnsupportedTimezone = xerrors.New("The location you provided looks like a timezone. Check https://ipinfo.io for your location.")
159160

160161
// parseCLISchedule parses a schedule in the format HH:MM{AM|PM} [DOW] [LOCATION]
161162
func parseCLISchedule(parts ...string) (*schedule.Schedule, error) {
@@ -178,6 +179,10 @@ func parseCLISchedule(parts ...string) (*schedule.Schedule, error) {
178179
dayOfWeek = parts[1]
179180
loc, err = time.LoadLocation(parts[2])
180181
if err != nil {
182+
_, err = time.Parse("MST", parts[2])
183+
if err == nil {
184+
return nil, errUnsupportedTimezone
185+
}
181186
return nil, xerrors.Errorf("Invalid timezone %q specified: a valid IANA timezone is required", parts[2])
182187
}
183188
case 2:
@@ -217,15 +222,20 @@ func parseCLISchedule(parts ...string) (*schedule.Schedule, error) {
217222
}
218223

219224
func parseTime(s string) (time.Time, error) {
220-
// Assume only time provided, HH:MM[AM|PM]
221-
t, err := time.Parse(time.Kitchen, s)
222-
if err == nil {
223-
return t, nil
224-
}
225-
// Try 24-hour format without AM/PM suffix.
226-
t, err = time.Parse("15:04", s)
227-
if err != nil {
228-
return time.Time{}, errInvalidTimeFormat
225+
// Try a number of possible layouts.
226+
for _, layout := range []string{
227+
time.Kitchen, // 03:04PM
228+
"15:04",
229+
"1504",
230+
"3pm",
231+
"3PM",
232+
"3:04pm",
233+
"3:04PM",
234+
} {
235+
t, err := time.Parse(layout, s)
236+
if err == nil {
237+
return t, nil
238+
}
229239
}
230-
return t, nil
240+
return time.Time{}, errInvalidTimeFormat
231241
}

cli/autostart_internal_test.go

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ func TestParseCLISchedule(t *testing.T) {
3939
expectedSchedule: "CRON_TZ=America/Chicago 0 9 * * *",
4040
tzEnv: "America/Chicago",
4141
},
42+
{
43+
name: "Time24Military",
44+
input: []string{"0900"},
45+
expectedSchedule: "CRON_TZ=America/Chicago 0 9 * * *",
46+
tzEnv: "America/Chicago",
47+
},
4248
{
4349
name: "DayOfWeekAndTime",
4450
input: []string{"09:00AM", "Sun-Sat"},
@@ -53,24 +59,29 @@ func TestParseCLISchedule(t *testing.T) {
5359
},
5460
{
5561
name: "InvalidTime",
56-
input: []string{"9am"},
62+
input: []string{"nine"},
5763
expectedError: errInvalidTimeFormat.Error(),
5864
},
5965
{
6066
name: "DayOfWeekAndInvalidTime",
61-
input: []string{"9am", "Sun-Sat"},
67+
input: []string{"nine", "Sun-Sat"},
6268
expectedError: errInvalidTimeFormat.Error(),
6369
},
6470
{
6571
name: "InvalidTimeAndLocation",
66-
input: []string{"9:", "America/Chicago"},
72+
input: []string{"nine", "America/Chicago"},
6773
expectedError: errInvalidTimeFormat.Error(),
6874
},
6975
{
7076
name: "DayOfWeekAndInvalidTimeAndLocation",
71-
input: []string{"9am", "Sun-Sat", "America/Chicago"},
77+
input: []string{"nine", "Sun-Sat", "America/Chicago"},
7278
expectedError: errInvalidTimeFormat.Error(),
7379
},
80+
{
81+
name: "TimezoneProvidedInsteadOfLocation",
82+
input: []string{"09:00AM", "Sun-Sat", "CST"},
83+
expectedError: errUnsupportedTimezone.Error(),
84+
},
7485
{
7586
name: "WhoKnows",
7687
input: []string{"Time", "is", "a", "human", "construct"},

0 commit comments

Comments
 (0)