Skip to content

Commit 2e71cb8

Browse files
authored
Merge pull request #1432 from julian7/timezoned-timestamp
accept timezone for timestamps
2 parents d29120f + 1335a70 commit 2e71cb8

File tree

6 files changed

+53
-1
lines changed

6 files changed

+53
-1
lines changed

Diff for: docs/v2/manual.md

+13
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,19 @@ In this example the flag could be used like this:
14131413
$ myapp --meeting 2019-08-12T15:04:05
14141414
```
14151415

1416+
When the layout doesn't contain timezones, timestamp will render with UTC. To
1417+
change behavior, a default timezone can be provided with flag definition:
1418+
1419+
```go
1420+
app := &cli.App{
1421+
Flags: []cli.Flag{
1422+
&cli.TimestampFlag{Name: "meeting", Layout: "2006-01-02T15:04:05", Timezone: time.Local},
1423+
},
1424+
}
1425+
```
1426+
1427+
(time.Local contains the system's local time zone.)
1428+
14161429
Side note: quotes may be necessary around the date depending on your layout (if
14171430
you have spaces for instance)
14181431

Diff for: flag-spec.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ flag_types:
4343
value_pointer: true
4444
struct_fields:
4545
- { name: Layout, type: string }
46+
- { name: Timezone, type: "*time.Location" }
4647

4748
# TODO: enable UintSlice
4849
# UintSlice: {}

Diff for: flag_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -2364,6 +2364,18 @@ func TestTimestampFlagApply_Fail_Parse_Wrong_Time(t *testing.T) {
23642364
expect(t, err, fmt.Errorf("invalid value \"2006-01-02T15:04:05Z\" for flag -time: parsing time \"2006-01-02T15:04:05Z\" as \"Jan 2, 2006 at 3:04pm (MST)\": cannot parse \"2006-01-02T15:04:05Z\" as \"Jan\""))
23652365
}
23662366

2367+
func TestTimestampFlagApply_Timezoned(t *testing.T) {
2368+
pdt := time.FixedZone("PDT", -7*60*60)
2369+
expectedResult, _ := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
2370+
fl := TimestampFlag{Name: "time", Aliases: []string{"t"}, Layout: time.ANSIC, Timezone: pdt}
2371+
set := flag.NewFlagSet("test", 0)
2372+
_ = fl.Apply(set)
2373+
2374+
err := set.Parse([]string{"--time", "Mon Jan 2 08:04:05 2006"})
2375+
expect(t, err, nil)
2376+
expect(t, *fl.Value.timestamp, expectedResult.In(pdt))
2377+
}
2378+
23672379
func TestTimestampFlagValueFromContext(t *testing.T) {
23682380
set := flag.NewFlagSet("test", 0)
23692381
now := time.Now()

Diff for: flag_timestamp.go

+17-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ type Timestamp struct {
1111
timestamp *time.Time
1212
hasBeenSet bool
1313
layout string
14+
location *time.Location
1415
}
1516

1617
// Timestamp constructor
@@ -31,9 +32,22 @@ func (t *Timestamp) SetLayout(layout string) {
3132
t.layout = layout
3233
}
3334

35+
// Set perceived timezone of the to-be parsed time string
36+
func (t *Timestamp) SetLocation(loc *time.Location) {
37+
t.location = loc
38+
}
39+
3440
// Parses the string value to timestamp
3541
func (t *Timestamp) Set(value string) error {
36-
timestamp, err := time.Parse(t.layout, value)
42+
var timestamp time.Time
43+
var err error
44+
45+
if t.location != nil {
46+
timestamp, err = time.ParseInLocation(t.layout, value, t.location)
47+
} else {
48+
timestamp, err = time.Parse(t.layout, value)
49+
}
50+
3751
if err != nil {
3852
return err
3953
}
@@ -104,9 +118,11 @@ func (f *TimestampFlag) Apply(set *flag.FlagSet) error {
104118
f.Value = &Timestamp{}
105119
}
106120
f.Value.SetLayout(f.Layout)
121+
f.Value.SetLocation(f.Timezone)
107122

108123
if f.Destination != nil {
109124
f.Destination.SetLayout(f.Layout)
125+
f.Destination.SetLocation(f.Timezone)
110126
}
111127

112128
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {

Diff for: godoc-current.txt

+8
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,9 @@ type App struct {
269269
Version string
270270
// Description of the program
271271
Description string
272+
// DefaultCommand is the (optional) name of a command
273+
// to run if no command names are passed as CLI arguments.
274+
DefaultCommand string
272275
// List of commands to execute
273276
Commands []*Command
274277
// List of flags to parse
@@ -1754,6 +1757,9 @@ func (t *Timestamp) Set(value string) error
17541757
func (t *Timestamp) SetLayout(layout string)
17551758
Set the timestamp string layout for future parsing
17561759

1760+
func (t *Timestamp) SetLocation(loc *time.Location)
1761+
Set perceived timezone of the to-be parsed time string
1762+
17571763
func (t *Timestamp) SetTimestamp(value time.Time)
17581764
Set the timestamp value directly
17591765

@@ -1782,6 +1788,8 @@ type TimestampFlag struct {
17821788
EnvVars []string
17831789

17841790
Layout string
1791+
1792+
Timezone *time.Location
17851793
}
17861794
TimestampFlag is a flag with type *Timestamp
17871795

Diff for: zz_generated.flags.go

+2
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,8 @@ type TimestampFlag struct {
280280
EnvVars []string
281281

282282
Layout string
283+
284+
Timezone *time.Location
283285
}
284286

285287
// String returns a readable representation of this value (for usage defaults)

0 commit comments

Comments
 (0)