Merge pull request #1432 from julian7/timezoned-timestamp
accept timezone for timestamps
This commit is contained in:
commit
2e71cb8174
@ -1413,6 +1413,19 @@ In this example the flag could be used like this:
|
|||||||
$ myapp --meeting 2019-08-12T15:04:05
|
$ myapp --meeting 2019-08-12T15:04:05
|
||||||
```
|
```
|
||||||
|
|
||||||
|
When the layout doesn't contain timezones, timestamp will render with UTC. To
|
||||||
|
change behavior, a default timezone can be provided with flag definition:
|
||||||
|
|
||||||
|
```go
|
||||||
|
app := &cli.App{
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.TimestampFlag{Name: "meeting", Layout: "2006-01-02T15:04:05", Timezone: time.Local},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
(time.Local contains the system's local time zone.)
|
||||||
|
|
||||||
Side note: quotes may be necessary around the date depending on your layout (if
|
Side note: quotes may be necessary around the date depending on your layout (if
|
||||||
you have spaces for instance)
|
you have spaces for instance)
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ flag_types:
|
|||||||
value_pointer: true
|
value_pointer: true
|
||||||
struct_fields:
|
struct_fields:
|
||||||
- { name: Layout, type: string }
|
- { name: Layout, type: string }
|
||||||
|
- { name: Timezone, type: "*time.Location" }
|
||||||
|
|
||||||
# TODO: enable UintSlice
|
# TODO: enable UintSlice
|
||||||
# UintSlice: {}
|
# UintSlice: {}
|
||||||
|
12
flag_test.go
12
flag_test.go
@ -2364,6 +2364,18 @@ func TestTimestampFlagApply_Fail_Parse_Wrong_Time(t *testing.T) {
|
|||||||
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\""))
|
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\""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTimestampFlagApply_Timezoned(t *testing.T) {
|
||||||
|
pdt := time.FixedZone("PDT", -7*60*60)
|
||||||
|
expectedResult, _ := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
|
||||||
|
fl := TimestampFlag{Name: "time", Aliases: []string{"t"}, Layout: time.ANSIC, Timezone: pdt}
|
||||||
|
set := flag.NewFlagSet("test", 0)
|
||||||
|
_ = fl.Apply(set)
|
||||||
|
|
||||||
|
err := set.Parse([]string{"--time", "Mon Jan 2 08:04:05 2006"})
|
||||||
|
expect(t, err, nil)
|
||||||
|
expect(t, *fl.Value.timestamp, expectedResult.In(pdt))
|
||||||
|
}
|
||||||
|
|
||||||
func TestTimestampFlagValueFromContext(t *testing.T) {
|
func TestTimestampFlagValueFromContext(t *testing.T) {
|
||||||
set := flag.NewFlagSet("test", 0)
|
set := flag.NewFlagSet("test", 0)
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
@ -11,6 +11,7 @@ type Timestamp struct {
|
|||||||
timestamp *time.Time
|
timestamp *time.Time
|
||||||
hasBeenSet bool
|
hasBeenSet bool
|
||||||
layout string
|
layout string
|
||||||
|
location *time.Location
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timestamp constructor
|
// Timestamp constructor
|
||||||
@ -31,9 +32,22 @@ func (t *Timestamp) SetLayout(layout string) {
|
|||||||
t.layout = layout
|
t.layout = layout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set perceived timezone of the to-be parsed time string
|
||||||
|
func (t *Timestamp) SetLocation(loc *time.Location) {
|
||||||
|
t.location = loc
|
||||||
|
}
|
||||||
|
|
||||||
// Parses the string value to timestamp
|
// Parses the string value to timestamp
|
||||||
func (t *Timestamp) Set(value string) error {
|
func (t *Timestamp) Set(value string) error {
|
||||||
timestamp, err := time.Parse(t.layout, value)
|
var timestamp time.Time
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if t.location != nil {
|
||||||
|
timestamp, err = time.ParseInLocation(t.layout, value, t.location)
|
||||||
|
} else {
|
||||||
|
timestamp, err = time.Parse(t.layout, value)
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -104,9 +118,11 @@ func (f *TimestampFlag) Apply(set *flag.FlagSet) error {
|
|||||||
f.Value = &Timestamp{}
|
f.Value = &Timestamp{}
|
||||||
}
|
}
|
||||||
f.Value.SetLayout(f.Layout)
|
f.Value.SetLayout(f.Layout)
|
||||||
|
f.Value.SetLocation(f.Timezone)
|
||||||
|
|
||||||
if f.Destination != nil {
|
if f.Destination != nil {
|
||||||
f.Destination.SetLayout(f.Layout)
|
f.Destination.SetLayout(f.Layout)
|
||||||
|
f.Destination.SetLocation(f.Timezone)
|
||||||
}
|
}
|
||||||
|
|
||||||
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
|
if val, source, found := flagFromEnvOrFile(f.EnvVars, f.FilePath); found {
|
||||||
|
@ -269,6 +269,9 @@ type App struct {
|
|||||||
Version string
|
Version string
|
||||||
// Description of the program
|
// Description of the program
|
||||||
Description string
|
Description string
|
||||||
|
// DefaultCommand is the (optional) name of a command
|
||||||
|
// to run if no command names are passed as CLI arguments.
|
||||||
|
DefaultCommand string
|
||||||
// List of commands to execute
|
// List of commands to execute
|
||||||
Commands []*Command
|
Commands []*Command
|
||||||
// List of flags to parse
|
// List of flags to parse
|
||||||
@ -1754,6 +1757,9 @@ func (t *Timestamp) Set(value string) error
|
|||||||
func (t *Timestamp) SetLayout(layout string)
|
func (t *Timestamp) SetLayout(layout string)
|
||||||
Set the timestamp string layout for future parsing
|
Set the timestamp string layout for future parsing
|
||||||
|
|
||||||
|
func (t *Timestamp) SetLocation(loc *time.Location)
|
||||||
|
Set perceived timezone of the to-be parsed time string
|
||||||
|
|
||||||
func (t *Timestamp) SetTimestamp(value time.Time)
|
func (t *Timestamp) SetTimestamp(value time.Time)
|
||||||
Set the timestamp value directly
|
Set the timestamp value directly
|
||||||
|
|
||||||
@ -1782,6 +1788,8 @@ type TimestampFlag struct {
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
|
|
||||||
Layout string
|
Layout string
|
||||||
|
|
||||||
|
Timezone *time.Location
|
||||||
}
|
}
|
||||||
TimestampFlag is a flag with type *Timestamp
|
TimestampFlag is a flag with type *Timestamp
|
||||||
|
|
||||||
|
@ -280,6 +280,8 @@ type TimestampFlag struct {
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
|
|
||||||
Layout string
|
Layout string
|
||||||
|
|
||||||
|
Timezone *time.Location
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a readable representation of this value (for usage defaults)
|
// String returns a readable representation of this value (for usage defaults)
|
||||||
|
Loading…
Reference in New Issue
Block a user