1package date 2 3import ( 4 "regexp" 5 "time" 6) 7 8// Azure reports time in UTC but it doesn't include the 'Z' time zone suffix in some cases. 9const ( 10 azureUtcFormatJSON = `"2006-01-02T15:04:05.999999999"` 11 azureUtcFormat = "2006-01-02T15:04:05.999999999" 12 rfc3339JSON = `"` + time.RFC3339Nano + `"` 13 rfc3339 = time.RFC3339Nano 14 tzOffsetRegex = `(Z|z|\+|-)(\d+:\d+)*"*$` 15) 16 17// Time defines a type similar to time.Time but assumes a layout of RFC3339 date-time (i.e., 18// 2006-01-02T15:04:05Z). 19type Time struct { 20 time.Time 21} 22 23// MarshalBinary preserves the Time as a byte array conforming to RFC3339 date-time (i.e., 24// 2006-01-02T15:04:05Z). 25func (t Time) MarshalBinary() ([]byte, error) { 26 return t.Time.MarshalText() 27} 28 29// UnmarshalBinary reconstitutes a Time saved as a byte array conforming to RFC3339 date-time 30// (i.e., 2006-01-02T15:04:05Z). 31func (t *Time) UnmarshalBinary(data []byte) error { 32 return t.UnmarshalText(data) 33} 34 35// MarshalJSON preserves the Time as a JSON string conforming to RFC3339 date-time (i.e., 36// 2006-01-02T15:04:05Z). 37func (t Time) MarshalJSON() (json []byte, err error) { 38 return t.Time.MarshalJSON() 39} 40 41// UnmarshalJSON reconstitutes the Time from a JSON string conforming to RFC3339 date-time 42// (i.e., 2006-01-02T15:04:05Z). 43func (t *Time) UnmarshalJSON(data []byte) (err error) { 44 timeFormat := azureUtcFormatJSON 45 match, err := regexp.Match(tzOffsetRegex, data) 46 if err != nil { 47 return err 48 } else if match { 49 timeFormat = rfc3339JSON 50 } 51 t.Time, err = ParseTime(timeFormat, string(data)) 52 return err 53} 54 55// MarshalText preserves the Time as a byte array conforming to RFC3339 date-time (i.e., 56// 2006-01-02T15:04:05Z). 57func (t Time) MarshalText() (text []byte, err error) { 58 return t.Time.MarshalText() 59} 60 61// UnmarshalText reconstitutes a Time saved as a byte array conforming to RFC3339 date-time 62// (i.e., 2006-01-02T15:04:05Z). 63func (t *Time) UnmarshalText(data []byte) (err error) { 64 timeFormat := azureUtcFormat 65 match, err := regexp.Match(tzOffsetRegex, data) 66 if err != nil { 67 return err 68 } else if match { 69 timeFormat = rfc3339 70 } 71 t.Time, err = ParseTime(timeFormat, string(data)) 72 return err 73} 74 75// String returns the Time formatted as an RFC3339 date-time string (i.e., 76// 2006-01-02T15:04:05Z). 77func (t Time) String() string { 78 // Note: time.Time.String does not return an RFC3339 compliant string, time.Time.MarshalText does. 79 b, err := t.MarshalText() 80 if err != nil { 81 return "" 82 } 83 return string(b) 84} 85 86// ToTime returns a Time as a time.Time 87func (t Time) ToTime() time.Time { 88 return t.Time 89} 90