GoLang time zone conversion - go

I am looking to display a time in a specific format for a particular country. My current code:
now := time.Now()
ogTime := time.Date(2022, 8, 1, 0, 0, 0, 0, now.Location())
loc, _ := time.LoadLocation("Asia/Singapore")
convertedTime := ogTime.In(loc)
fmt.Println(convertedTime)
This prints out 2022-08-01 08:00:00 +0800 +08
Is there a way to display 2022-07-31T16:00:00Z? Is it possible to remove the time offset and instead just have a Z? I have tried ogTime.Format(RFC3339) as well as something like ogTime.Format("2006-01-02 T15:04:05Z"), but neither work.

fmt.Println is using the Stringer()-implementation of time.Time to print the value as a string, which determines the formatting for you.
To set the format yourself, use time.Time.Format();
now := time.Now()
fmt.Println(now.Format(`2006-01-02T15:04:05Z07:00`))
A "Z" in the output without an offset means the time is in UTC. If you do not want to print the timezone, omit it from the format;
fmt.Println(convertedTime.Format("2006-01-02T15:04:05"))
2022-08-01T08:00:00
If you want to print in UTC convert the timezone before printing; fmt.Println(convertedTime.UTC().Format("2006-01-02T15:04:05Z07:00"))
2022-08-01T00:00:00Z
Printing a "Z" while the time is not in UTC would require you to concatenate it yourself, but would be silly;
fmt.Println(convertedTime.Format("2006-01-02T15:04:05") + "Z")
2022-08-01T08:00:00Z
If you want to provide local time and print it in UTC, provide your timezone when parsing the date
loc, _ := time.LoadLocation("Asia/Singapore")
ogTime := time.Date(2022, 8, 1, 0, 0, 0, 0, loc)
fmt.Println(ogTime.UTC().Format("2006-01-02T15:04:05Z07:00"))
2022-07-31T16:00:00Z

Related

Golang Time parsing providing the format is returning wrong results

I've got a t time.Time which I'm converting to an specific timezone and from which I need to extract both date and time (separately) as strings as follows:
Data should look like: 2006-09-23
Time should look like: 05:06:23
I'm doing the following:
Setting t to the needed timezone:
var err error
loc, err := time.LoadLocation("America/Los_Angeles")
if err != nil {
return err
} else {
t = t.In(loc)
}
Setting up the format and converting it to string so I can extract its values:
format := "2006-01-02 15:03:04"
timestamp := t.Format(format)
timestampSlice := strings.Fields(timestamp)
fmt.Println(timestampSlice[0])
fmt.Println(timestampSlice[1])
But I'm getting unexpected results for time (date works fine):
When passing
time.Date(2021, time.Month(2), 21, 1, 10, 30, 0, time.UTC)
I'd expect
2021-02-20 and 17:10:30
but I'm getting:
17:05:10 for the time
When passing
time.Date(2022, time.Month(8), 26, 22, 7, 30, 0, time.FixedZone("Asia/Shanghai", 0)),
I'd expect
2022-08-26 and 06:07:30
but I'm getting:
15:03:07
what am I doing wrong? does the values passed in the format have any effect in the parsing? I thought the format was only to signal the way the result should look
From the docs:
// Jan 2 15:04:05 2006 MST
// 1 2 3 4 5 6 -7
So the format 2006-01-02 15:03:04 would be parsed as years-months-days hours-hours-minutes. Note that 15 refers to the hours (00-23), that 03 refers to the hours (1-12), and 04 refers to the minutes.
So the correct format would be
format := "2006-01-02 15:04:05"
You can learn more about formatting time here: https://pkg.go.dev/time#example-Time.Format

check if timestamp between 2 dates

I have dates stored as timestamps in mongo, for example, 1564444800000000000. I want to check if a timestamp is between 2 dates - July 1, 2021 and July, 2021. I converted these 2 dates to timestamps using https://www.epochconverter.com/. I first fetched all records and while looping through the records, I did a check like so
cDate := 1564444800000000000
if cDate > 1625167488000 && cDate < 1627759488000 {
log.Fatal("found one!")
}
But this not seem to work as I get no matches. Is there a better way of doing this?
I mean just looking at the numbers:
cDate := 1564444800000000000
1625167488000
1627759488000
I don't see how one with six more digits than the one's it's supposed to be between would ever be between them. And even if we divided CDate by 1000000 it would be
cDate := 1564444800000
1625167488000
1627759488000
and it's still less than both of those, so it still wouldn't be between them. But that being said, you most likely do just need to divide cDate by 1000000 and your example is just not a good one (since 1564444800000 is July 29 2019)
I suggest to transform in a date then check with the before and after API, as example:
package main
import (
"fmt"
"time"
)
func main() {
cDate := int64(1564444800000000000)
firstJuly := time.Date(2019, 7, 1, 0, 0, 0, 0, time.UTC)
thrirtyOneJuly := time.Date(2019, 7, 31, 0, 0, 0, 0, time.UTC)
date := time.Unix(0, cDate)
// fmt.Println(date) //will print 2019-07-30 00:00:00 +0000 UTC
fmt.Println("Is July?", date.After(firstJuly) && date.Before(thrirtyOneJuly))
}
will print
Is July? true
See on playground

Convert timestamp to ISO format in golang

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?
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
How about this?
ts, err := time.Parse("2006-01-02T15:04:05.000+0000", currentTime)
since time.RFC3339 is just 2006-01-02T15:04:05Z07:00

How to get string or int64 from object time in golang?

I get from input source timestamp and then I make time '00:00:00' for this timestamp. Now I need to get timestamp from object time
timestamp_int:= 1532009163
time := time.Date(
time.Unix(int64(timestamp_int), 0).UTC().Year(),
time.Unix(int64(timestamp_int), 0).UTC().Month(),
time.Unix(int64(timestamp_int), 0).UTC().Day(), 0, 0, 0, 0,
time.Unix(int64(timestamp_int), 0).UTC().Location())
new_time := time.Format("timestamp") //here i need to get new timestamp
You can get the timestamp in seconds by using the Unix method.
timestamp := 1532009163
t := time.Unix(int64(timestamp), 0)
newTimestamp := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.UTC).Unix()
fmt.Println(newTimestamp)
// 1531958400

How can I query all values except the value created today?

q := datastore.NewQuery("Encounter").Filter("PatientID =", patientID).Order("CreatedDate").Order("-CreatedBy")
How can I query all the values except the values created today?
Add a filter by CreatedDate.
t := time.Now()
zone, _ := time.LoadLocation("Europe/Amsterdam")
day := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, zone)
q := datastore.NewQuery("Encounter").Filter("PatientID =", patientID).Filter("CreatedDate <", day).Order("CreatedDate").Order("-CreatedBy")
This only returns items older than today. If you need both older and newer than today, since there is no inequality in filters, you can fetch older and newer than today, then iterate through them and append the results.

Resources