Created
September 3, 2020 10:12
-
-
Save rhcarvalho/9338c3ff8850897c68bc74797c5dc25b to your computer and use it in GitHub Desktop.
Smart timestamps in Go: decode/encode JSON from Unix timestamp numbers or RFC3339 strings
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://play.golang.org/p/wSZvxQbT3KY | |
package main | |
import ( | |
"encoding/json" | |
"fmt" | |
"os" | |
"strconv" | |
"text/tabwriter" | |
"time" | |
) | |
// Timestamp is like time.Time, but knows how to unmarshal from JSON Unix timestamp numbers or RFC3339 strings, and | |
// marshal back into the same JSON representation. | |
type Timestamp struct { | |
time.Time | |
rfc3339 bool | |
} | |
func (t Timestamp) MarshalJSON() ([]byte, error) { | |
if t.rfc3339 { | |
return t.Time.MarshalJSON() | |
} | |
return t.formatUnix() | |
} | |
func (t *Timestamp) UnmarshalJSON(data []byte) error { | |
err := t.Time.UnmarshalJSON(data) | |
if err != nil { | |
return t.parseUnix(data) | |
} | |
t.rfc3339 = true | |
return nil | |
} | |
func (t Timestamp) formatUnix() ([]byte, error) { | |
sec := float64(t.Time.UnixNano()) * float64(time.Nanosecond) / float64(time.Second) | |
return strconv.AppendFloat(nil, sec, 'f', -1, 64), nil | |
} | |
func (t *Timestamp) parseUnix(data []byte) error { | |
f, err := strconv.ParseFloat(string(data), 64) | |
if err != nil { | |
return err | |
} | |
t.Time = time.Unix(0, int64(f*float64(time.Second/time.Nanosecond))) | |
return nil | |
} | |
func main() { | |
t := Timestamp{Time: time.Now()} | |
fmt.Println("Now:", t.Format(time.RFC3339Nano), "==", t.Unix()) | |
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.Debug) | |
defer w.Flush() | |
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", "INPUT", "PARSED TIME", "INPUT in RFC3339", "ROUNDTRIP TO JSON") | |
for _, s := range []string{ | |
`1257894000`, | |
`1257894000.45221`, | |
`"2009-11-10T23:00:00Z"`, | |
`"2009-11-10T23:00:00.45221Z"`, | |
} { | |
err := json.Unmarshal([]byte(s), &t) | |
if err != nil { | |
panic(err) | |
} | |
j, err := t.MarshalJSON() | |
if err != nil { | |
panic(err) | |
} | |
fmt.Fprintf(w, "%s\t%s\t%t\t%s\n", s, t.Format(time.RFC3339Nano), t.rfc3339, j) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment