I am trying to convert this date string ("2018-10-29T11:48:09.180022-04:00") to ISO format in Go. But not able to do. Can anyone help?
package main
import (
"fmt"
"time"
)
func main() {
l,_ := time.Parse("2006-01-02T15:04:05Z07:00", "2018-10-29T15:18:20-04:00")
fmt.Println(l, time.Now(), time.Now().UTC().Format("2006-01-02T15:04:05Z07:00"))
}
Output:
2018-10-29 15:18:20 -0400 -0400 2009-11-10 23:00:00 +0000 UTC m=+0.000000001 2009-11-10T23:00:00Z
https://play.golang.org/p/gXw39_Y-hpR
Note that your input string is valid ISO 8601 format.
However, for JSON serialization, JavaScript uses a slightly different (but still completely valid) style of ISO 8601 date format in which only 3 digits are used for fractional seconds (giving millisecond resolution) and the timezone is adjusted to Coordinated Universal Time (UTC), (aka GMT+0, or "Zulu" timezone) designated with a Z.
// JavaScript
JSON.stringify(new Date()); // => "2018-10-30T15:22:30.293Z"
// Millisecond resolution ─────────────────────────────┺┻┛┃
// "Zulu" (UTC) time zone ────────────────────────────────┚
You can convert your timestamp into the JavaScript style by first parsing the input string, then converting to Zulu time via the UTC() method, then formatting with the desired output format.
For example (Go Playground):
const (
INPUT_FORMAT = "2006-01-02T15:04:05.999999999-07:00"
OUTPUT_FORMAT = "2006-01-02T15:04:05.000Z"
)
func timestampToJavaScriptISO(s string) (string, error) {
t, err := time.Parse(INPUT_FORMAT, s)
if err != nil {
return "", err
}
return t.UTC().Format(OUTPUT_FORMAT), nil
}
func main() {
s := "2018-10-29T11:48:09.180022-04:00"
s2, err := timestampToJavaScriptISO(s)
if err != nil {
panic(err)
}
fmt.Println(s2)
// 2018-10-29T15:48:09.180Z
}
you can just convert it by using the RFC3339 format:
unitTimeInRFC3339 :=time.Now().Format(time.RFC3339)
Related
I am taking timestamp from the user like this
2015-05-28T17:00:00
And a timezone "America/Los_Angeles"
Now I want convert the date into something like
2015-05-28T17:00:00-07:00
Is that possible in go ,Please help me out in this ,if you have any links which you can share
You can use ParseInLocation to parse datetime in specific location.
package main
import (
"fmt"
"time"
)
func main() {
loc, err := time.LoadLocation("America/Los_Angeles")
if err != nil {
panic(err)
}
// Note: without explicit zone, returns time in given location.
const shortForm = "2015-05-28T17:00:00"
t, err := time.ParseInLocation("2006-01-02T15:04:05", shortForm, loc)
if err != nil {
panic(err)
}
fmt.Println(t)
}
Its output is:
2015-05-28 17:00:00 -0700 PDT
"timezone" translates to time.Location in go. To load a location by name:
loc, err := time.LoadLocation("America/Los_Angeles")
Parsing:
to interpret the string as "that timestamp in that location":
t, err := time.ParseInLocation("2006-01-02T15:04:05", input, loc)
to interpret the string as "that timestamp in UTC":
t, err := time.Parse("2006-01-02T15:04:05", input)
Formatting:
to format t according to RFC3339 :
fmt.Println(t.Format(time.RFC3339))
t carries its own time.Location, you can also translate that timestamp to the timezone you see fit:
fmt.Println(t.In(loc).Format(time.RFC3339))
fmt.Println(t.UTC().Format(time.RFC3339))
https://go.dev/play/p/g2BgfdYGxU_I
I'm being sent a date in the following format:
2021-05-09T12:10:00+01:00
Which is apparently a valid date format: https://en.wikipedia.org/wiki/ISO_8601
I'm attempting to parse that date in Go:
pt, err := time.Parse("2006-01-02T15:04:05+00:00", dt)
I've also tried to use time.RFC3339
But neither seem to pick up the timezone. In this case I get:
2021/05/10 21:02:02 http: panic serving [::1]:62125: parsing time "2021-05-09T12:10:00 01:00" as "2006-01-02T15:04:05+00:00": cannot parse " 01:00" as "+00:00"
The problem is your layout parameter,
"2006-01-02T15:04:05+00:00"
Instead of +00:00 you should have -07:00
This should help,
package main
import (
"fmt"
"time"
)
func main() {
date := "2021-05-09T12:10:00+01:00"
layout := "2006-01-02T15:04:05-07:00"
t, err := time.Parse(layout, date)
if err != nil {
fmt.Println(err)
}
fmt.Println(t)
}
Output: 2021-05-09 12:10:00 +0100 +0100
Playground: https://play.golang.org/p/UcrIDfJRcNV
Don't get confused as to why the timezone is showing up twice.
It's explained in this answer,
Golang time - time zone showing twice
The special layout parameter only accepts a certain set of valid numbers.
You can refer them here,
https://yourbasic.org/golang/format-parse-string-time-date-example/
You need to relay the timezone via the number -7:00 (not +1:00):
// pt, err := time.Parse("2006-01-02T15:04:05+1:00", dt) // not this
pt, err := time.Parse("2006-01-02T15:04:05-07:00", dt) // this
https://play.golang.org/p/n697vKUHSjD
I'm trying to understand the issue with time conversion in Go language. Here is code example:
package main
import (
"fmt"
"time"
)
func unix2Str(ts int64) string {
const layout = "20060102"
t := time.Unix(ts, 0)
return t.Format(layout)
}
func unixTime(ts string) int64 {
const layout = "20060102"
t, err := time.Parse(layout, ts)
if err != nil {
fmt.Println(err)
return 0
}
return t.Unix()
}
func main() {
ts1 := "20110320"
ts2 := "20110321"
ut1 := unixTime(ts1)
ut2 := unixTime(ts2)
fmt.Println(ts1, ut1, unix2Str(ut1))
fmt.Println(ts2, ut2, unix2Str(ut2))
}
It prints the following output:
20110320 1300579200 20110319
20110321 1300665600 20110320
But since I do the conversion from string format to Unix and reverse I would expect the same results for the date in string format. But it is not the case. In fact, the printed unix time 1300579200 is converted in python to original date I started with, e.g.
>>> time.strftime("%Y%m%d", time.gmtime(1300579200))
'20110320'
Is it a bug in Go code or am I missing something?
It is because of the difference between your local time zone and UTC. Parse returned UTC time and Unix returned local time. For example,
package main
import (
"fmt"
"time"
)
func unix2Str(ts int64) string {
const layout = "20060102"
t := time.Unix(ts, 0)
fmt.Println(t)
return t.Format(layout)
}
func unixTime(ts string) int64 {
const layout = "20060102"
t, err := time.Parse(layout, ts)
if err != nil {
fmt.Println(err)
return 0
}
fmt.Println(t)
return t.Unix()
}
func main() {
ts1 := "20110320"
ts2 := "20110321"
ut1 := unixTime(ts1)
ut2 := unixTime(ts2)
fmt.Println(ts1, ut1, unix2Str(ut1))
fmt.Println(ts2, ut2, unix2Str(ut2))
}
Output:
2011-03-20 00:00:00 +0000 UTC
2011-03-21 00:00:00 +0000 UTC
2011-03-19 20:00:00 -0400 EDT
20110320 1300579200 20110319
2011-03-20 20:00:00 -0400 EDT
20110321 1300665600 20110320
func Parse
func Parse(layout, value string) (Time, error)
Parse parses a formatted string and returns the time value it
represents. The layout defines the format by showing how the reference
time, defined to be
Mon Jan 2 15:04:05 -0700 MST 2006
would be interpreted if it were the value; it serves as an example of
the input format. The same interpretation will then be made to the
input string.
In the absence of a time zone indicator, Parse returns a time in UTC.
func Unix
func Unix(sec int64, nsec int64) Time
Unix returns the local Time corresponding to the given Unix time, sec
seconds and nsec nanoseconds since January 1, 1970 UTC.
I am trying to parse a date time string in go. I pass the exact string as the format and get and error parsing time "01/31/2000 12:59 AM": hour out of range.
I am getting that string from an input. How can I make this work?
Here is the code (https://play.golang.org/p/Kg9KfFpU2z)
func main() {
layout := "01/31/2000 12:59 AM"
if t, err := time.Parse(layout, "01/31/2000 12:59 AM"); err == nil {
fmt.Println("Time decoded:", t)
} else {
fmt.Println("Failed to decode time:", err)
}
}
Based on your shared code, you should change the layout to 01/02/2006 03:04 AM to fix it:
Note:
If you have 24 hours format, you should change the hour part in layout to 15 instead of 03 and also to get rid of AM part e.g. 01/02/2006 15:04
package main
import (
"fmt"
"time"
)
func main() {
layout := "01/02/2006 03:04 AM"
if t, err := time.Parse(layout, "01/31/2000 12:59 AM"); err == nil {
fmt.Println("Time decoded:", t)
} else {
fmt.Println("Failed to decode time:", err)
}
}
Here is a good article that would help you to understand different layouts.
Your format needs to use a very specific date and time, see the docs:
https://golang.org/pkg/time/#example_Parse
Parse parses a formatted string and returns the time value it
represents. The layout defines the format by showing how the reference
time, defined to be
Mon Jan 2 15:04:05 -0700 MST 2006
So you need https://play.golang.org/p/c_Xc_R2OHb
I'm trying to parse an Unix timestamp but I get out of range error. That doesn't really makes sense to me, because the layout is correct (as in the Go docs):
package main
import "fmt"
import "time"
func main() {
tm, err := time.Parse("1136239445", "1405544146")
if err != nil{
panic(err)
}
fmt.Println(tm)
}
Playground
The time.Parse function does not do Unix timestamps. Instead you can use strconv.ParseInt to parse the string to int64 and create the timestamp with time.Unix:
package main
import (
"fmt"
"time"
"strconv"
)
func main() {
i, err := strconv.ParseInt("1405544146", 10, 64)
if err != nil {
panic(err)
}
tm := time.Unix(i, 0)
fmt.Println(tm)
}
Output:
2014-07-16 20:55:46 +0000 UTC
Playground: http://play.golang.org/p/v_j6UIro7a
Edit:
Changed from strconv.Atoi to strconv.ParseInt to avoid int overflows on 32 bit systems.
You can directly use time.Unix function of time which converts the unix time stamp to UTC
package main
import (
"fmt"
"time"
)
func main() {
unixTimeUTC:=time.Unix(1405544146, 0) //gives unix time stamp in utc
unitTimeInRFC3339 :=unixTimeUTC.Format(time.RFC3339) // converts utc time to RFC3339 format
fmt.Println("unix time stamp in UTC :--->",unixTimeUTC)
fmt.Println("unix time stamp in unitTimeInRFC3339 format :->",unitTimeInRFC3339)
}
Output
unix time stamp in UTC :---> 2014-07-16 20:55:46 +0000 UTC
unix time stamp in unitTimeInRFC3339 format :----> 2014-07-16T20:55:46Z
Check in Go Playground: https://play.golang.org/p/5FtRdnkxAd
Sharing a few functions which I created for dates:
Please note that I wanted to get time for a particular location (not just UTC time). If you want UTC time, just remove loc variable and .In(loc) function call.
func GetTimeStamp() string {
loc, _ := time.LoadLocation("America/Los_Angeles")
t := time.Now().In(loc)
return t.Format("20060102150405")
}
func GetTodaysDate() string {
loc, _ := time.LoadLocation("America/Los_Angeles")
current_time := time.Now().In(loc)
return current_time.Format("2006-01-02")
}
func GetTodaysDateTime() string {
loc, _ := time.LoadLocation("America/Los_Angeles")
current_time := time.Now().In(loc)
return current_time.Format("2006-01-02 15:04:05")
}
func GetTodaysDateTimeFormatted() string {
loc, _ := time.LoadLocation("America/Los_Angeles")
current_time := time.Now().In(loc)
return current_time.Format("Jan 2, 2006 at 3:04 PM")
}
func GetTimeStampFromDate(dtformat string) string {
form := "Jan 2, 2006 at 3:04 PM"
t2, _ := time.Parse(form, dtformat)
return t2.Format("20060102150405")
}
I do a lot of logging where the timestamps are float64 and use this function to get the timestamps as string:
func dateFormat(layout string, d float64) string{
intTime := int64(d)
t := time.Unix(intTime, 0)
if layout == "" {
layout = "2006-01-02 15:04:05"
}
return t.Format(layout)
}
for millis unix timestamp precision, in go1.18
i, err := strconv.ParseInt("1652084489543", 10, 64)
if err != nil {
panic(err)
}
tm := time.UnixMilli(i)
fmt.Println(tm)
According to the go documentation, Unix returns a local time.
Unix returns the local Time corresponding to the given Unix time
This means the output would depend on the machine your code runs on, which, most often is what you need, but sometimes, you may want to have the value in UTC.
To do so, I adapted the snippet to make it return a time in UTC:
i, err := strconv.ParseInt("1405544146", 10, 64)
if err != nil {
panic(err)
}
tm := time.Unix(i, 0)
fmt.Println(tm.UTC())
This prints on my machine (in CEST)
2014-07-16 20:55:46 +0000 UTC
This is an old question but I noticed that a practical answer is missing.
For example, we are working with the MavLink protocol and we need to process a message with a structure defined here.
If we have this data structure:
Field Name
Type
Units
Description
time_boot_ms
uint64_t
ms
Timestamp (time since system boot).
press_abs
float
hPa
Absolute pressure
press_diff
float
hPa
Differential pressure 1
temperature
int16_t
cdegC
Absolute pressure temperature
temperature_press_diff **
int16_t
cdegC
Differential pressure temperature (0, if not available). Report values of 0 (or 1) as 1 cdegC.
So, we receive constant updates that we need to process using the time_boot_ms as reference to insert them on the database and synchronize them with other messages.
What can we do?
As we noticed, the time is in milliseconds and everyone, that has some experience with Go, knows that for some unknown reason it's just way too complex to convert a millisecond resolution Unix timestamp to time.Time. The built-in time.Unix() function only supports second and nanosecond precision.
How we can get millisecond precision?
Well, we might wait until they release the version 1.7 of Go or we either have to multiply the milliseconds to nanoseconds or split them into seconds and nanoseconds.
Lets implement the second idea, spit the into seconds and nanoseconds:
unixUTCtime := time.Unix(ms/int64(1000), (ms%int64(1000))*int64(1000000))
Now we can encapsulate it in a func and use it in our main like this:
package main
import (
"fmt"
"time"
)
const msInSecond int64 = 1e3
const nsInMillisecond int64 = 1e6
// UnixToMS Converts Unix Epoch from milliseconds to time.Time
func UnixToMS (ms int64) time.Time {
return time.Unix(ms/msInSecond, (ms%msInSecond)*nsInMillisecond)
}
func main() {
unixTimes := [...]int64{758991688, 758992188, 758992690, 758993186}
var unixUTCTimes []time.Time
for index, unixTime := range unixTimes {
unixUTCTimes = append(unixUTCTimes, UnixToMS(unixTime))
if index > 0 {
timeDifference := unixUTCTimes[index].Sub(unixUTCTimes[index-1])
fmt.Println("Time difference in ms :--->", timeDifference)
}
}
}
The output will be:
Time difference in ms :---> 500ms
Time difference in ms :---> 502ms
Time difference in ms :---> 496ms
Check in Go Playground