1package cli 2 3import ( 4 "flag" 5 "fmt" 6 "time" 7) 8 9// Timestamp wrap to satisfy golang's flag interface. 10type Timestamp struct { 11 timestamp *time.Time 12 hasBeenSet bool 13 layout string 14} 15 16// Timestamp constructor 17func NewTimestamp(timestamp time.Time) *Timestamp { 18 return &Timestamp{timestamp: ×tamp} 19} 20 21// Set the timestamp value directly 22func (t *Timestamp) SetTimestamp(value time.Time) { 23 if !t.hasBeenSet { 24 t.timestamp = &value 25 t.hasBeenSet = true 26 } 27} 28 29// Set the timestamp string layout for future parsing 30func (t *Timestamp) SetLayout(layout string) { 31 t.layout = layout 32} 33 34// Parses the string value to timestamp 35func (t *Timestamp) Set(value string) error { 36 timestamp, err := time.Parse(t.layout, value) 37 if err != nil { 38 return err 39 } 40 41 t.timestamp = ×tamp 42 t.hasBeenSet = true 43 return nil 44} 45 46// String returns a readable representation of this value (for usage defaults) 47func (t *Timestamp) String() string { 48 return fmt.Sprintf("%#v", t.timestamp) 49} 50 51// Value returns the timestamp value stored in the flag 52func (t *Timestamp) Value() *time.Time { 53 return t.timestamp 54} 55 56// Get returns the flag structure 57func (t *Timestamp) Get() interface{} { 58 return *t 59} 60 61// TimestampFlag is a flag with type time 62type TimestampFlag struct { 63 Name string 64 Aliases []string 65 Usage string 66 EnvVars []string 67 FilePath string 68 Required bool 69 Hidden bool 70 Layout string 71 Value *Timestamp 72 DefaultText string 73 HasBeenSet bool 74} 75 76// IsSet returns whether or not the flag has been set through env or file 77func (f *TimestampFlag) IsSet() bool { 78 return f.HasBeenSet 79} 80 81// String returns a readable representation of this value 82// (for usage defaults) 83func (f *TimestampFlag) String() string { 84 return FlagStringer(f) 85} 86 87// Names returns the names of the flag 88func (f *TimestampFlag) Names() []string { 89 return flagNames(f.Name, f.Aliases) 90} 91 92// IsRequired returns whether or not the flag is required 93func (f *TimestampFlag) IsRequired() bool { 94 return f.Required 95} 96 97// TakesValue returns true of the flag takes a value, otherwise false 98func (f *TimestampFlag) TakesValue() bool { 99 return true 100} 101 102// GetUsage returns the usage string for the flag 103func (f *TimestampFlag) GetUsage() string { 104 return f.Usage 105} 106 107// GetValue returns the flags value as string representation and an empty 108// string if the flag takes no value at all. 109func (f *TimestampFlag) GetValue() string { 110 if f.Value != nil { 111 return f.Value.timestamp.String() 112 } 113 return "" 114} 115 116// Apply populates the flag given the flag set and environment 117func (f *TimestampFlag) Apply(set *flag.FlagSet) error { 118 if f.Layout == "" { 119 return fmt.Errorf("timestamp Layout is required") 120 } 121 f.Value = &Timestamp{} 122 f.Value.SetLayout(f.Layout) 123 124 if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok { 125 if err := f.Value.Set(val); err != nil { 126 return fmt.Errorf("could not parse %q as timestamp value for flag %s: %s", val, f.Name, err) 127 } 128 f.HasBeenSet = true 129 } 130 131 for _, name := range f.Names() { 132 set.Var(f.Value, name, f.Usage) 133 } 134 return nil 135} 136 137// Timestamp gets the timestamp from a flag name 138func (c *Context) Timestamp(name string) *time.Time { 139 if fs := lookupFlagSet(name, c); fs != nil { 140 return lookupTimestamp(name, fs) 141 } 142 return nil 143} 144 145// Fetches the timestamp value from the local timestampWrap 146func lookupTimestamp(name string, set *flag.FlagSet) *time.Time { 147 f := set.Lookup(name) 148 if f != nil { 149 return (f.Value.(*Timestamp)).Value() 150 } 151 return nil 152} 153