Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert timestamp to ISO format in golang

Tags:

time

go

iso

I'm trying to convert the timestamp 2018-12-17T15:03:49.000+0000 to ISO format in golang, but am getting an error cannot parse "+0000" as "Z07:00"

This is what I tried

ts, err := time.Parse(time.RFC3339, currentTime)

Any ideas?

like image 964
user3226932 Avatar asked Dec 20 '18 18:12

user3226932


1 Answers

Beware, a long answer ahead

(tl;dr) use:

ts, err := time.Parse("2006-01-02T15:04:05-0700", currentTime)
ts.Format(time.RFC3339)

I really like go documentation, and you should do :)

All from https://golang.org/pkg/time/#pkg-constants

RFC3339 = "2006-01-02T15:04:05Z07:00"

Some valid layouts are invalid time values for time.Parse, due to formats such as _ for space padding and Z for zone information

Which means you can't parse +0000 with layout Z07:00.

Also:

The reference time used in the layouts is the specific time:

Mon Jan 2 15:04:05 MST 2006

which is Unix time 1136239445. Since MST is GMT-0700, the reference time can be thought of as

01/02 03:04:05PM '06 -0700

You can either parse numeric time zone offsets format as follows:

-0700  ±hhmm
-07:00 ±hh:mm
-07    ±hh

Or replacing the sign in the format with a Z:

Z0700  Z or ±hhmm
Z07:00 Z or ±hh:mm
Z07    Z or ±hh

fraction:

From this go example https://play.golang.org/p/V9ubSN6gTdG

// If the fraction in the layout is 9s, trailing zeros are dropped.

do("9s for fraction", "15:04:05.99999999", "11:06:39.1234")

So you can parse it like:

ts, err := time.Parse("2006-01-02T15:04:05.999-0700", currentTime)

Also, From the doc

A decimal point followed by one or more zeros represents a fractional second, printed to the given number of decimal places. A decimal point followed by one or more nines represents a fractional second, printed to the given number of decimal places, with trailing zeros removed. When parsing (only), the input may contain a fractional second field immediately after the seconds field, even if the layout does not signify its presence. In that case a decimal point followed by a maximal series of digits is parsed as a fractional second.

Which means you can leave out the decimal points from the layout and it will parse correctly

ts, err := time.Parse("2006-01-02T15:04:05-0700", currentTime)

For getting the time in UTC simply write ts.UTC()

And for formatting it to RFC3339, you can use

ts.Format(time.RFC3339)

Example

currentTime := "2018-12-17T17:02:04.123+0530"
ts, err := time.Parse("2006-01-02T15:04:05-0700", currentTime)
if err != nil {
    panic(err)
}

fmt.Println("ts:        ", ts)
fmt.Println("ts in utc: ", ts.UTC())
fmt.Println("RFC3339:   ", ts.Format(time.RFC3339))


// output
// ts:         2018-12-17 17:02:04.123 +0530 +0530
// ts in utc:  2018-12-17 11:32:04.123 +0000 UTC
// RFC3339:    2018-12-17T17:02:04+05:30

playground: https://play.golang.org/p/vfERDm_YINb

like image 82
oren Avatar answered Sep 30 '22 09:09

oren