I've tried the following format which should catch the +0000 timezone offset as I read https://golang.org/pkg/time/#pkg-constants:
ts, err := time.Parse("2006-01-02T15:04:05-0700", "2021-01-19T16:20:04+0000")
But that looks rather strange when the result ist printed (no error):
2021-01-19 16:47:00 +0000 +0000
UPDATE
Running https://play.golang.org/p/wHBYz7iKnLT locally (OSX 11.1) gives the strange result:
❯ gor time.go
2021-01-19 16:20:04 +0000 +0000 <nil>
What you see is the "default" formatting, e.g. when printed like fmt.Println(ts), which is the result of Time.String(). Quoting from Time.String():
String returns the time formatted using the format string
"2006-01-02 15:04:05.999999999 -0700 MST"
As you can see, it contains the zone offset and the zone name in the end.
Also note that you used time.Parse() which documents that:
In the absence of a time zone indicator, Parse returns a time in UTC.
When parsing a time with a zone offset like -0700, if the offset corresponds to a time zone used by the current location (Local), then Parse uses that location and zone in the returned time. Otherwise it records the time as being in a fabricated location with time fixed at the given zone offset.
Since on the Go Playground the local time is set to UTC whose offset matches the offset of the time you parse, that zone will be used, so printing it on the Go Playground you'll see UTC.
When you parse it locally (on your computer) and the local time zone is not UTC or another zone that has 0 offset, as per the doc, that location is recorded as a fabricated location with the name having the offset.
So when you parse and print that time locally, since the default format includes both the zone offset and the zone name, and since both are +0000, you'll see +0000 printed twice.
Worry not, the parsed time is of course correct:
ts, err := time.Parse("2006-01-02T15:04:05-0700", "2021-01-19T16:20:04+0000")
if err != nil {
panic(err)
}
fmt.Println(ts)
fmt.Println(ts.Format("2006-01-02 16:04:05 -0700"))
fmt.Println(ts.Format("2006-01-02 16:04:05 MST"))
This outputs on the Go Playground:
2021-01-19 16:20:04 +0000 UTC
2021-01-19 16:20:04 +0000
2021-01-19 16:20:04 UTC
Locally (having CET zone) it outputs:
2021-01-19 16:20:04 +0000 +0000
2021-01-19 16:20:04 +0000
2021-01-19 16:20:04 +0000
Note that if you'd parse a time with a different zone offset (not being 0), you'll see the same on the Go Playground too. For example:
ts, err := time.Parse("2006-01-02T15:04:05-0700", "2021-01-19T16:20:04+1100")
if err != nil {
panic(err)
}
fmt.Println(ts)
fmt.Println(ts.Format("2006-01-02 16:04:05 -0700"))
fmt.Println(ts.Format("2006-01-02 16:04:05 MST"))
This outputs both on the Go Playground and locally for me (with CET zone):
2021-01-19 16:20:04 +1100 +1100
2021-01-19 16:20:04 +1100
2021-01-19 16:20:04 +1100
Related
I would like to get a datetime from a ticker.C formatted string (over the network) and parse it into a Time object. ticker.C would look like 2023-01-03 17:24:13.986722973 +0100 CET m=+1.002332450. It would probably have to drop the m=+1.002332450 elapsed time as I don't see a way of keeping that in a Time object.
Also, is there a way to get a format string out of a Time object? Something like mytime.GetFormat()
The Stringer format of Time is documented here, https://pkg.go.dev/time#go1.19.4#Time.String:
String returns the time formatted using the format string
"2006-01-02 15:04:05.999999999 -0700 MST"
If the time has a monotonic clock reading, the returned string includes a final field "m=±<value>", where value is the monotonic clock reading formatted as a decimal number of seconds.
The returned string is meant for debugging; for a stable serialized representation, use t.MarshalText, t.MarshalBinary, or t.Format with an explicit format string.
Which suggests you should not try to consume that value and instead depend on a properly marshalled (or formatted) string.
Not mentioned/suggested, time.MarshalJSON is an option:
MarshalJSON implements the json.Marshaler interface. The time is a quoted string in RFC 3339 format, with sub-second precision added if present.
The sender and receiver don't have to do any special work to encode the time.Time value in JSON and then decode it again:
type wireTick struct {
Tick time.Time `json:"tick"`
}
Here's a small example of encoding and decoding the ticker on the wire with that struct, https://go.dev/play/p/Fx73q8-kVFa, which produces output like:
Sent JSON-encoded tick on wire: {"tick":"2009-11-10T23:00:01Z"}
Received tick from wire: {2009-11-10 23:00:01 +0000 UTC}
Sent JSON-encoded tick on wire: {"tick":"2009-11-10T23:00:02Z"}
Received tick from wire: {2009-11-10 23:00:02 +0000 UTC}
...
Can you modify the value being sent on the wire, or ask someone else to modify it so that it's proper?
If not, this should work:
const stringerLayout = "2006-01-02 15:04:05.999999999 -0700 MST"
timeStr := "2009-11-10 23:00:10 +0000 UTC m=+10.000000001"
tickStr := timeStr[:strings.Index(timeStr, "m=")-1]
tick, _ := time.Parse(stringerLayout, tickStr)
fmt.Printf("Received from wire: \t %q\n", timeStr)
fmt.Printf("Chopped off monotonic: \t %q\n", tickStr)
fmt.Printf("Tick is: \t\t %v\n", tick)
Received from wire: "2009-11-10 23:00:10 +0000 UTC m=+10.000000001"
Chopped off monotonic: "2009-11-10 23:00:10 +0000 UTC"
Tick is: 2009-11-10 23:00:10 +0000 UTC
I have a string from db , say
dbString := "2020-03-16 14:46:13 +0530 IST"
My requirement is to insert this string as Timestamptz into another table
I am trying to convert dbString into Time
timeToBeInserted := time.Parse(time.RFC3339,t.VO.DateLastModified)
I see the below error
+0000 UTC parsing time "2020-03-16 14:46:13 +0530 IST" as "2006-01-02T15:04:05Z07:00": cannot parse " 14:46:13 +0530 IST" as "T"
Your date string does not match RFC3339 format:
RFC3339 = "2006-01-02T15:04:05Z07:00"
You should use a custom format. The following one works with your string:
dbString := "2020-03-16 14:46:13 +0530 IST"
fmt.Println(time.Parse("2006-01-02 15:04:05 -0700 MST", dbString))
// Output:
// 2020-03-16 14:46:13 +0530 IST <nil>
Your time string isn't in RFC3339 format, so don't tell time.Parse that it is. Instead use
time.Parse("2006-01-02 15:04:05 -0700 MST", t.VO.DateLastModified)
How can I add or subtract UTC offset (Another time location) value in my current time in GoLang. I tried this link but no use (example)
Example
My input is "UTC+7". I don't know the location. Now I'm in India.
Now I'm getting India (IST) time. Ex: 2019-07-23T15:23:08, Here I need to add UTC+7 in IST. It's possible?
Use time.LoadLocation() to get location information of particular timezone. Then use the .In() method of time object, to convert the current time into expected timezone.
Example:
now := time.Now()
fmt.Println("My place", now)
// 2019-07-23 18:14:23.6036439 +0700 +07
locSingapore, _ := time.LoadLocation("Asia/Singapore")
nowInSingapore := now.In(locSingapore)
fmt.Println("Singapore", nowInSingapore)
// 2019-07-23 19:14:23.6036439 +0800
locLondon, _ := time.LoadLocation("Europe/London")
nowInLondon := now.In(locLondon)
fmt.Println("London", nowInLondon)
// 2019-07-23 12:14:23.6036439 +0100 BST
Explanations:
From code above we can see that time.Now() timezone is +7, it's because I live in West Indonesia.
But nowInSingapore timezone is +8, it's because the now object are adjusted into singapore timezone.
And the last one, nowInLondon is showing another different timezone, +1.
And if we compare all of those time, it's essentially same time.
18:14:23 WIB (GMT +7) == 19:14:23 GMT +8 == 12:14:23 BST (GMT +1)
I Solved the issue.
now := time.Now()
fmt.Println("now:", now.Format("2006-01-02T15:04:05"))
UTC_String_Value := "UTC+7"
UTC_Split_Value := strings.Split(UTC_String_Value, "+")
count, err := strconv.Atoi(UTC_Split_Value [1])
if err != nil {
fmt.Println(err)
}
resp := now.Add(time.Duration(-count) * time.Hour).Format("2006-01-02T15:04:05")
//Subract the utc offset value 7 (hours)
fmt.Println("now:", now.Format("2006-01-02T15:04:05"))
fmt.Println("resp:", resp)
Output
now: 2019-07-24T11:25:17
resp: 2019-07-24T04:25:17
I need to convert any given time zone in RFC3339 format to system time in RFC3339 format.But for few time zone like IST it is throwing the error and the time is still in UTC.
For conversion which function service as better? time.parse or time.In.
I tried to convert the UTC to IST but it failed.
package main
import (
"fmt"
"time"
)
func main() {
//now time
now := time.Now()
fmt.Println("now ", now)
zone, _ := now.Zone()
fmt.Println("zone->", zone)
ll, llerr := time.LoadLocation(zone)
fmt.Println("Load Location", ll, llerr)
// Convert the given time to system based time zone
t, err := time.ParseInLocation(time.RFC3339, "2017-04-25T23:03:00Z", ll)
fmt.Println("t - parsein", t)
fmt.Println("err - parsein", err)
//fmt.Println("t2 - parse", t.In(ll))
}
Error : unknown time zone IST
Expected: Need to convert any time zone to system time zone.
You can't load Indian IST time zone by that name because the name "IST" is ambiguous. It could mean India, Ireland, Israel, etc. time zones, which have different zone offsets and rules. For details, see Why is time.Parse not using the timezone?
If IST is your local zone, the time.Local variable will denote that time zone. If you have a time.Time, you can "switch" to another zone using Time.In(), also Time.Local() returns the time in your local zone.
Of course this code would "break" when ran in another zone. To make sure it behaves the same everywhere, load the Indian IST zone explicitly like this:
loc, err := time.LoadLocation("Asia/Kolkata")
if err != nil {
panic(err)
}
fmt.Println(time.Now())
fmt.Println(time.Now().In(loc))
On the Go Playground it will output:
2009-11-10 23:00:00 +0000 UTC m=+0.000000001
2009-11-11 04:30:00 +0530 IST
I am executing below code to parse a time
var time_format = "2006-01-02T15:04:05.000+0700"
var s = "2018-08-23T14:10:31.692+0700"
p, _ := time.Parse(time_format, s)
fmt.Println(p.String())
The output of above program is as below.
2018-08-23 14:10:31.692 +0000 UTC
It is the same time in UTC while I am parsing a time which is +0700 ahead of UTC so as expeceted result should be
2018-08-23 7:10:31.692 +0000 UTC
Can anyone tell what is the issue here.
It's because your format string is not correct. The timezone indication must be -0700 (not +0700). time.Parse():
The layout defines the format by showing how the reference time, defined to be
Mon Jan 2 15:04:05 -0700 MST 2006
With that change it works:
var format = "2006-01-02T15:04:05.000-0700"
var s = "2018-08-23T14:10:31.692+0700"
p, err := time.Parse(format, s)
fmt.Println(p.String(), err)
This will output (try it on the Go Playground):
2018-08-23 14:10:31.692 +0700 +0700 <nil>