Use timestamp from Mysql in humanize.Time() package - go

I have a mariaDB database with a timestamp field. I want the values from that field being parsed to time.Time() values. This is possible by adding the ?parseTime=true to the connection string. After fetching a row, I want to use the value (which is time.Time) with humanize.Time(). Unfortunately values within the past 60 minutes are converted by humanize.Time() as 1 hour from now. When I put directly a time.Time() value into humanize.Time(), it gives me x seconds ago.
So I don't know what I'm doing wrong here. I think I need to convert 2017-04-23 14:00:16 +0000 UTC to 2017-04-23 14:00:16.370758048 +0200 CEST, but how?
package main
import (
"fmt"
"log"
"time"
humanize "github.com/dustin/go-humanize"
)
// value from database: 2017-04-23 14:00:16 +0000 UTC
// typical time.Now() value: 2017-04-23 14:00:16.370758048 +0200 CEST
func main() {
layout := "2006-01-02 15:04:05 -0700 MST"
beforeParsing := "2017-04-23 14:00:16 +0000 UTC"
t, err := time.Parse(layout, beforeParsing)
if err != nil {
log.Fatal(err)
}
fmt.Println(t)
fmt.Println(humanize.Time(t))
}

Related

Timezone parsing from date in string gives empty string

I want to parse a date (having timezone) represented by a string into Time.
I tried the below code:
package main
import (
"fmt"
"time"
)
func main() {
dateString := "Sat Jan 02 15:04:05 -0700 2021"
dateTime, _ := time.Parse("Mon Jan 02 15:04:05 -0700 2006", dateString)
zoneName, _ := dateTime.Zone()
fmt.Println("Zone Name is "+ zoneName)
loc, _ := time.LoadLocation(zoneName)
fmt.Println(loc)
}
On running the code I am getting the zoneName as empty string which eventually transforms into UTC whereas I should be getting a valid time zone? What mistake have I done to parse the date?

time format converted to strftime default format

In the wikipedia entry for Common Log Format, the strftime format is given as:
[10/Oct/2000:13:55:36 -0700] is the date, time, and time zone that the
request was received, by default in strftime format %d/%b/%Y:%H:%M:%S
%z.
When I try using the time.Format function:
package main
import (
"fmt"
"time"
)
func main() {
t, _ := time.Parse(time.UnixDate, "Tue Oct 10 13:55:36 PDT 2000")
fmt.Println(time.Time(t).Format("01/Feb/2006:15:04:05 -0700"))
}
I get the output [10/Feb/2000:13:55:36 +0000], while I was expecting [10/Oct/2000:13:55:36 -0700] (per Wikipedia). What is wrong with my formatting?
I checked that day was a Tuesday and the time zone was -7h (PDT) for that date.
For the Format layout, Jan not Feb. For example,
package main
import (
"fmt"
"time"
)
func main() {
t, err := time.Parse(time.UnixDate, "Tue Oct 10 13:55:36 PDT 2000")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(time.Time(t).Format("01/Jan/2006:15:04:05 -0700"))
}
Output:
10/Oct/2000:13:55:36 +0000
Also, for the time zone, use ParseInLocation,
package main
import (
"fmt"
"time"
)
func main() {
loc, err := time.LoadLocation("America/Los_Angeles")
if err != nil {
fmt.Println(err)
return
}
t, err := time.ParseInLocation(time.UnixDate, "Tue Oct 10 13:55:36 PDT 2000", loc)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(t)
fmt.Println(time.Time(t).Format("01/Jan/2006:15:04:05 -0700"))
}
Playground: https://play.golang.org/p/tBLw5oJSE5t
Output:
2000-10-10 13:55:36 -0700 PDT
10/Oct/2000:13:55:36 -0700

Time conversion issue in go language

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.

How i can to convert RFC3339 to UNIX in golang

I want to show some RFC3339 time as seconds. I found how to parse times string, but it not that
t, _ := time.Parse(time.RFC3339, "2012-11-01T22:08:41+00:00")
For example,
package main
import (
"fmt"
"time"
)
func main() {
t, err := time.Parse(time.RFC3339, "2012-11-01T22:08:41+00:00")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(t)
// Unix returns t as a Unix time,
// the number of seconds elapsed since January 1, 1970 UTC.
fmt.Println(t.Unix())
}
Playground: https://play.golang.org/p/LG6G4lMIWt
Output:
2012-11-01 22:08:41 +0000 UTC
1351807721

PST to UTC parsing of time in Golang

I am trying to convert the time from PST to UTC timezone but seeing some unexpected result, while IST to UTC is working fine:
package main
import (
"fmt"
"time"
)
func main() {
const longForm = "2006-01-02 15:04:05 MST"
t, err := time.Parse(longForm, "2016-01-17 20:04:05 IST")
fmt.Println(t, err)
fmt.Printf("IST to UTC: %v\n\n", t.UTC())
s, err1 := time.Parse(longForm, "2016-01-17 23:04:05 PST")
fmt.Println(s, err1)
fmt.Printf("PST to UTC: %v\n\n", s.UTC())
}
Output is :
2016-01-17 20:04:05 +0530 IST <nil>
IST to UTC: 2016-01-17 14:34:05 +0000 UTC
2016-01-17 23:04:05 +0000 PST <nil>
PST to UTC: 2016-01-17 23:04:05 +0000 UTC
When parsing is done for IST, it shows +0530, while for PST shows +0000 and in UTC it print same value of HH:MM:SS (23:04:05) as in PST. Am i missing anything here?
The documentation for time.Parse() says:
If the zone abbreviation is unknown, Parse records the time as being in a fabricated location with the given zone abbreviation and a zero offset. This choice means that such a time can be parsed and reformatted with the same layout losslessly, but the exact instant used in the representation will differ by the actual zone offset. To avoid such problems, prefer time layouts that use a numeric zone offset, or use ParseInLocation.
Here is how to use ParseInLocation:
IST, err := time.LoadLocation("Asia/Kolkata")
if err != nil {
fmt.Println(err)
return
}
PST, err := time.LoadLocation("America/Los_Angeles")
if err != nil {
fmt.Println(err)
return
}
const longForm = "2006-01-02 15:04:05 MST"
t, err := time.ParseInLocation(longForm, "2016-01-17 20:04:05 IST", IST)
fmt.Println(t, err)
fmt.Printf("IST to UTC: %v\n\n", t.UTC())
s, err1 := time.ParseInLocation(longForm, "2016-01-17 23:04:05 PST", PST)
fmt.Println(s, err1)
fmt.Printf("PST to UTC: %v\n\n", s.UTC())
Output:
2016-01-17 20:04:05 +0530 IST <nil>
IST to UTC: 2016-01-17 14:34:05 +0000 UTC
2016-01-17 23:04:05 -0800 PST <nil>
PST to UTC: 2016-01-18 07:04:05 +0000 UTC
Full code on the Go Playground
The documentation for time.Parse() says:
If the zone abbreviation is unknown, Parse records the time as being in a fabricated location with the given zone abbreviation and a zero offset. This choice means that such a time can be parsed and reformatted with the same layout losslessly, but the exact instant used in the representation will differ by the actual zone offset. To avoid such problems, prefer time layouts that use a numeric zone offset, or use ParseInLocation.
So, the system doesn't know what "PST" is. For me, the system also doesn't know what IST is. You can check for supported locations like so:
package main
import (
"fmt"
"time"
)
func main() {
for _, name := range []string{"MST", "UTC", "IST", "PST", "EST", "PT"} {
loc, err := time.LoadLocation(name)
if err != nil {
fmt.Println("No location", name)
} else {
fmt.Println("Location", name, "is", loc)
}
}
}
Output on my system:
Location MST is MST
Location UTC is UTC
No location IST
No location PST
Location EST is EST
No location PT

Resources