golang RFC2822 conversion - go

Is there a library or function in the included libraries that converts an RFC timestamp to Unix time (or another format that I can then format into Unix time?)
For example, I'd like to change this Tue Sep 16 21:58:58 +0000 2014 to a Unix timestamp.

For example,
package main
import (
"fmt"
"time"
)
func main() {
s := "Tue Sep 16 21:58:58 +0000 2014"
const rfc2822 = "Mon Jan 02 15:04:05 -0700 2006"
t, err := time.Parse(rfc2822, s)
if err != nil {
fmt.Println(err)
return
}
u := t.Unix()
fmt.Println(u)
f := t.Format(time.UnixDate)
fmt.Println(f)
}
Output:
1410904738
Tue Sep 16 21:58:58 +0000 2014
References:
Package time
RFC2822: 3.3. Date and Time Specification
NOTE:
There is a package time format constant named RubyDate; it's a misnomer.
The Go authors were misled by Go Issue 518 which claimed that Ruby Time.now outputs Tue Jan 12 02:52:59 -0800 2010. However,
#!/usr/bin/env ruby
print Time.now
print "\n"
Output:
2014-09-20 19:40:32 -0400
Later, the issue was revised to say that Tue Jan 12 02:52:59 -0800 2010 was the date format used by the Twitter API. In the beginning, in the "Fail Whale" days, Twitter used Ruby-on-Rails, which may be why they assumed it was a Ruby date format.
I didn't use the time.RubyDate constant in my example since it's misleading. A constant named rfc2822 provides better documentation.
References:
Go: Issue 518: time.Parse - numeric time zones and spacing
Diff of format.go revision 0f80c5e80c0e
Twitter Search is Now 3x Faster

Related

Define custom time format

I am trying to write a custom date format string as required by my application.
Using the Go time package I get the format using a clumsy function (see below).
Also since this function will be called millions of times every day, I want this to be super efficient too. Is there a POSIX style formatting available in Go?
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
fmt.Printf("Time now is %d%02d%02d%02d%02d%02d",
t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second())
}
In Go there are built in layouts to pass to the .Format() method of Time (see func (Time) Format), one of these could be what you are looking for:
func main() {
fmt.Println(time.Now().Format(time.ANSIC))
fmt.Println(time.Now().Format(time.UnixDate))
fmt.Println(time.Now().Format(time.RFC3339))
}
This is going to be faster than fmt.Printf("...", t.Year(), t.Month(), ...), but we're talking about microseconds "faster" here, so there really is no big difference.
Output:
Sun Jun 10 13:18:09 2018
Sun Jun 10 13:18:09 UTC 2018
2018-06-10T13:18:09Z
There are a lot more predefined layouts, so you can check all of them out and see if one of them fits your needs. Here they are directly from the source code:
const (
ANSIC = "Mon Jan _2 15:04:05 2006"
UnixDate = "Mon Jan _2 15:04:05 MST 2006"
RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
RFC822 = "02 Jan 06 15:04 MST"
RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
RFC3339 = "2006-01-02T15:04:05Z07:00"
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
Kitchen = "3:04PM"
// Handy time stamps.
Stamp = "Jan _2 15:04:05"
StampMilli = "Jan _2 15:04:05.000"
StampMicro = "Jan _2 15:04:05.000000"
StampNano = "Jan _2 15:04:05.000000000"
)
Other than that, it's just a matter of creating your own layout, there really is no difference.
To create a custom layout string, quoting from the documentation:
The layout string used by the Parse function and Format method shows by example how the reference time should be represented. We stress that one must show how the reference time is formatted, not a time of the user's choosing. Thus each layout string is a representation of the time stamp: Jan 2 15:04:05 2006 MST.
So, for example:
fmt.Println(time.Now().Format("Mon January 2, 2006 - 15:04:05.000"))
gives:
Sun June 10, 2018 - 17:49:32.557
If you want something different you'll just have to format the date Jan 2 15:04:05 2006 MST how you would want it to be displayed. You can also take a look at the relative page on Go by Example.

How to use time.Parse to parse hh:mm format in Go

I am importing a lot of fields of the format:
09:02 AM
10:02 AM
12:30 PM
04:10 PM
04:50 PM
05:30 PM
I would like to convert the fields into something I can do arithmetic on. For example, do a count down to when the event Occurs. Thus, saving the field in microseconds... or even seconds.
I have been trying to get the time.Parse to work... no joy.
fmt.Println(time.Parse("hh:mm", m.Feed.Entry[i].GsxA100Time.T))
returns...
0001-01-01 00:00:00 +0000 UTC parsing time "07:50 PM" as "hh:mm": cannot parse "07:50 PM" as "hh:mm"
any suggestions?
The layout string for time.Parse does not handle the "hh:mm" format. In your case, the layout string would rather be "03:04 PM" as you can see in the documentation.
To get a time.Duration after parsing the string, you can substract your time with a reference time, in your case I would assume "12:00 AM".
Working example:
package main
import (
"fmt"
"time"
)
func main() {
ref, _ := time.Parse("03:04 PM", "12:00 AM")
t, err := time.Parse("03:04 PM", "11:22 PM")
if err != nil {
panic(err)
}
fmt.Println(t.Sub(ref).Seconds())
}
Output:
84120
Playground
Did you read the documentation of time.Parse? In the very beginning it says:
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
In the beginning of the package documentation there are more details about the layout string. Note that you can omit some of the fields (in your case days, years and timezeone) and those will then always get zero value.
So fmt.Println(time.Parse("3:04 PM", "07:50 PM")) should work.
If you'll check again the documentation about time's Parse method you'll find the fact that Go's approach of parsing the time is totally different than the one that you used to work with in other programming languages. To provide the Parse function the layout of the time that you want to parse you need to transform one specific date (which is Mon Jan 2 15:04:05 -0700 MST 2006) into the layout that you're aiming for. In your case that would be "03:04 PM".
The full code: fmt.Println(time.Parse("03:04 PM", m.Feed.Entry[i].GsxA100Time.T))
Just in case anyone is working with epoch times can use this,
func convert (in int64) string {
u := time.Unix(in/1000, in%1000)
ampm := "AM"
if u.Hour()/12 ==1 { ampm = "PM" }
th := u.Hour()%12
hh := strconv.Itoa(th)
if th < 10 { hh = "0" + hh }
tm := u.Minute()
mm := strconv.Itoa(tm)
if tm < 10 { mm = "0" + mm }
return hh + ":" + mm + " " + ampm
}

How to convert UTC time to unix timestamp

I am looking for an option to convert UTC time string to unix timestamp.
The string variable I have is 02/28/2016 10:03:46 PM and it needs to be converted to a unix timestamp like 1456693426
Any idea how to do that?
First of, the unix timestamp 1456693426 does not have the time 10:03:46 PM but 9:03:46 PM in UTC.
In the time package there is the function Parse with expects a layout to parse the time. The layout is constructed from the reference time Mon Jan 2 15:04:05 -0700 MST 2006. So in your case the layout would be 01/02/2006 3:04:05 PM. After using Parse you get a time.Time struct on which you can call Unix to receive the unix timestamp.
package main
import (
"fmt"
"time"
)
func main() {
layout := "01/02/2006 3:04:05 PM"
t, err := time.Parse(layout, "02/28/2016 9:03:46 PM")
if err != nil {
fmt.Println(err)
}
fmt.Println(t.Unix())
}

Go parse string to time

I've got the following string:
Sun, 03 Jan 2016 10:00:07 CET
Id like to parse it into time, but cannot seem to figure out how to write the format.
This is what I've got so far:
layout := "Mon, 01 Jan 03:04:05"
t, _ := time.Parse(layout, "Sun, 03 Jan 2016 10:00:07 CET")
fmt.Println(t)
Output I get is:
0001-01-01 00:00:00 +0000 UTC
First of all: You're silently ignoring the error this is returned as second return value of time.Parse. I'd suggest handling the error appropriately, instead.
Secondly, let's have a look at the documentation of time.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 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.
The time.Parse function expects its layout parameter to represent a fixed example date. So, in order to parse the date Sun, 03 Jan 2016 10:00:07 CET, the appropriate example layout string should be Mon, 02 Jan 2006 15:04:05 MST:
layout := "Mon, 02 Jan 2006 15:04:05 MST"
t, err := time.Parse(layout, "Sun, 03 Jan 2016 10:00:07 CET")
if err != nil {
// handle the error somehow!
}
fmt.Println(t)

How to parse non-standard date / time in Go ? Mitteleuropäische Sommerzeit

I'm trying to parse dates received in email headers. Recently I've got stuck on this one Thu, 7 Aug 2014 14:03:05 +0200 (Mitteleuropäische Sommerzeit). What kind of layout am I supposed to use ? Mon, 02 Jan 2006 15:04:05 -0700 (MST) doesn't do the trick.
I've also tried the workaround below but it still doesn't work. I'm not sure why Mitt... is not being replaced.
if strings.Contains(d, "Mitteleuropäische Sommerzeit") {
d = strings.Replace(d, "Mitteleuropäische Sommerzeit", "CEST", 1)
}
The Mitteleuropäische Sommerzeit part is indeed not recognized by the time package. But it works perfectly when you replace it by CEST:
var d = "Thu, 7 Aug 2014 14:03:05 +0200 (Mitteleuropäische Sommerzeit)"
_, err := time.Parse("Mon, _2 Jan 2006 15:04:05 -0700 (MST)", d)
if err != nil {
fmt.Println(err) // There is indeed an error
}
d = strings.Replace(d, "Mitteleuropäische Sommerzeit", "CEST", 1)
t, err := time.Parse("Mon, _2 Jan 2006 15:04:05 -0700 (MST)", d)
if err != nil {
fmt.Println(err) // No error this time
}
fmt.Println(t) // 2014-08-07 14:03:05 +0200 CEST
On playground.
Do not forget to write _2 instead of 2 in your layout, so that days with two figures can be parsed too.
It is redundant to try and parse the parenthesized timezone name when you already know the correct numeric offset:
Thu, 7 Aug 2014 14:03:05 +0200 (Mitteleuropäische Sommerzeit)
is equally specific as
Thu, 7 Aug 2014 14:03:05 +0200
The only additional information you get out of the first representation is that it was summer when the email was sent and that the region from which the email's author comes from is central Europe (literally "central Europe summertime").
This will not, however, affect the time.Time value's representation in contrast to the second string because the daylight saving adjustment is already reflected in the numerical timezone representation +0200 which would be +0100 during winter.
In other words, in this case you can ignore the spelled-out timezone specification.

Resources