Go: How to parse only date to time.Time? - go

I want to parse only date value to time.Time.
For example I have date in this format: 2016-03-31, and I want to parse it, like: time.Parse(FORMAT, "2016-03-31").
But it always fail.
What is the correct format string to use to parse only date with this format?
I have the code below as example, it is on playground also: https://play.golang.org/p/0MNLr9emZd
package main
import (
"fmt"
"time"
)
var dateToParse = "2016-03-31"
func main() {
format := "2006-12-01"
parseDate(format)
}
func parseDate(format string) {
t, err := time.Parse(format, dateToParse)
if err != nil {
fmt.Println("Format:", format)
fmt.Println(err)
fmt.Println("")
return
}
fmt.Println("Works Format:", format)
fmt.Println(t)
fmt.Println("")
}
The output is this:
Format: 2006-12-01
parsing time "2016-03-31" as "2006-12-01": cannot parse "-31" as "2"

Package time
These are predefined layouts for use in Time.Format and Time.Parse.
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
To define your own format, write down what the reference time would
look like formatted your way; see the values of constants like ANSIC,
StampMicro or Kitchen for examples.
Use format := "2006-01-02" for yyyy-mm-dd.

The new format DateOnly = "2006-01-02" of format.go will be added in the Go next release (1.20) per proposal time: add DateTime, DateOnly, TimeOnly format constants and commit
time.Parse(time.DateOnly, dateToParse)

Related

Subtracting time to get age

My aim is to calculate the age of the pod by doing the subtraction of "current_time - pod_creation_time" so that I will get the age, I am getting creation time from metadata but it's in the format "2021-07-13 16:34:22 +0530 IST", so when I trying to subtract it from time.Now(), I am getting parsing error like below:
invalid operation: "t2 : " + t2 (mismatched types string and time.Time)
Anyone could please help how to have creation time "2021-07-13 16:34:22 +0530 IST" from metadata in the proper format so that I can do "time.Now - (creation time)"
I tried some workaround like below:
creatTime, err := time.Parse("2006-01-02 15:04:05 -0700 MST",
pod.ObjectMeta.CreationTimestamp.String())
and then subtracted creationTime from Current Time. It works, but I think this is not the right way.
There's a type mismatch as time.Now() return the current time stored in the type time.Time whereas 2021-07-13 16:34:22 +0530 IST is a string. You can perform the required subtraction operation on mismatched types i.e., time.Time and string.
You have to parse the string by specifying the layout. I'd recommend reading the time package's doc.
I've explained every operation in the sample code below; I hope it helps. If you understand this, you can also then look at helper functions like time.Since that can help you write the same program in fewer lines.
package main
import (
"fmt"
"time"
)
func main() {
// K8s timestamp
t := "2021-07-13 16:34:22 +0530 IST"
// Format of K8s timestamp
format := "2006-01-02 15:04:05 -0700 MST" // Mon Jan 2 15:04:05 -0700 MST 2006
// Parse the timestamp so that it's stored in time.Time
cur, err := time.Parse(format, t)
if err != nil {
panic(err)
}
// Current time
now := time.Now()
// As both are of type time.Time, it's subtractable
dur := now.Sub(cur)
// Print duration
fmt.Println(dur)
// Print duration (in seconds)
fmt.Println(dur.Seconds())
}
Also, I'd like you to learn how to write questions on StackOverflow. The formatting of your question is pretty bad. When seeking good solutions; it is the OP's duty to post the question correctly first so that everybody could understand it and then expect answers.
Read: https://stackoverflow.com/help/how-to-ask

Go parse time to string and back

I am trying to do something in Go that is very simple in languages like Java
I want to parse current time to string and then parse it back to time.
This is the code I tried but as can be seen here it gives unexpected results.
I am facing two problems
time.Now().String() gives a wrong date
If I cast the time to string
and cast it back to time, it gives a totally different date.
What is the right (and easy) way to do this?
p := fmt.Println
startStr := time.Now().String() //2009-11-10 23:00:00 +0000 UTC m=+0.000000001
p(startStr)
startTime, _ := time.Parse(
"2009-11-10 23:00:00 +0000 UTC m=+0.000000001",
startStr)
p(startTime) //0001-01-01 00:00:00 +0000 UTC
time.Now().String() is meant for debugging only (see go doc).
You should instead use time.Format().
For example:
p := fmt.Println
now := time.Now().Format(time.RFC3339)
p(now)
parsed, _ := time.Parse(time.RFC3339, now)
p(parsed.Format(time.RFC3339))
produces:
2009-11-10T23:00:00Z
2009-11-10T23:00:00Z
Your other concern regarding time.Now().String() gives a wrong date is likely due to where you're running the code. e.g. if you're running in "The Go Playgounrd", then the time won't be accurate. You should run it on your own computer, and assuming your computer has the correct time, then you should get the right time printed.
Unlike some other languages, Go does not treat String() as a de facto marshaling method -- instead, it's meant just to print the value out for debugging purposes. You could parse back from that format into a Time if you used a proper format string; however, a proper format string must be for the exact time of Mon Jan 2 15:04:05 MST 2006, not any time; but the format that String() prints out isn't captured by a constant within the Time package so it's probably not worth doing.
Instead, however, what you're trying to do may be better captured by the MarshalText and UnmarshalText methods:
startStr, _ := time.Now().MarshalText()
fmt.Println(string(startStr)) // 2009-11-10T23:00:00Z
startTime := new(time.Time)
startTime.UnmarshalText(startStr)
fmt.Println(startTime) // 2009-11-10 23:00:00 +0000 UTC
The time in the playground is fixed, it is always the date and time of
the Go announcement.
https://github.com/golang/go/issues/10663
So to play with time correctly, you need to run it on your local.
About the parsing time to string or back, you have to pass the format of time string:
For example:
package main
import (
"fmt"
"time"
)
func main() {
current := time.Now()
fmt.Println("Init Time:", current.String())
timeCustomFormatStr := current.Format("2006-01-02 15:04:05 -0700")
fmt.Println("Custom format", timeCustomFormatStr)
parsedTime, err := time.Parse("2006-01-02 15:04:05 -0700",timeCustomFormatStr)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("parsedTime From Custom:", parsedTime)
timeFormatRFC3339 := current.Format(time.RFC3339)
fmt.Println("RFC3339 format", timeFormatRFC3339)
parsedTimeRFC3339, err := time.Parse(time.RFC3339,timeFormatRFC3339)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("parsedTime From Custom:", parsedTimeRFC3339)
}
Ref:
1 https://golang.org/pkg/time/#Time.Format

Golang time error: month out of range

Here is my code:
time.Parse(time.Now().String()[0:19],time.Now().String()[0:19])
error:
parsing time "2016-09-20 16:50:08": month out of range
How to parse time string?
First param is layout, see:
func Parse(layout, value string) (Time, error) {
return parse(layout, value, UTC, Local)
}
Docs:
// 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.
//
// Predefined layouts ANSIC, UnixDate, RFC3339 and others describe standard
// and convenient representations of the reference time. For more information
// about the formats and the definition of the reference time, see the
// documentation for ANSIC and the other constants defined by this package.
// Also, the executable example for time.Format demonstrates the working
// of the layout string in detail and is a good reference.
//
// Elements omitted from the value are assumed to be zero or, when
// zero is impossible, one, so parsing "3:04pm" returns the time
// corresponding to Jan 1, year 0, 15:04:00 UTC (note that because the year is
// 0, this time is before the zero Time).
// Years must be in the range 0000..9999. The day of the week is checked
// for syntax but it is otherwise ignored.
//
// 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.
//
// No checking is done that the day of the month is within the month's
// valid dates; any one- or two-digit value is accepted. For example
// February 31 and even February 99 are valid dates, specifying dates
// in March and May. This behavior is consistent with time.Date.
//
// When parsing a time with a zone abbreviation like MST, if the zone abbreviation
// has a defined offset in the current location, then that offset is used.
// The zone abbreviation "UTC" is recognized as UTC regardless of location.
// 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.
You may use
t, err := time.Parse("2006-01-02 15:04:05", time.Now().String()[:19])
Try on The Go Playground:
package main
import (
"fmt"
"time"
)
func main() {
t, err := time.Parse("2006-01-02 15:04:05", time.Now().String()[:19])
if err != nil {
panic(err)
}
fmt.Println(t)
}
output:
2009-11-10 23:00:00 +0000 UTC
I had the same problem, so I came here to say golang will some times mean "month" they meant "DAY OF THE MONTH", the error message is wrong, here is an example:
package main
import (
"fmt"
"time"
)
func main() {
dateAsString:= "31/Oct/2019"
layout := "01/Jan/2006" // BAD BAD BAD SHOULD BE 02 INSTEAD OF 01
fmt.Println("INPUT:" + dateAsString)
t, err := time.Parse(layout, dateAsString)
if err != nil {
fmt.Println("DATE UNPARSEABLE:3", err)
}
fmt.Println(t)
}

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())
}

parse time string type back to time type error

package main
import "fmt"
import "time"
func main() {
source := "2014-04-22 23:41:12.518845115 +0800 CST"
Form := "2014-04-22 23:41:12.518845115 +0800 CST"
t, err := time.Parse(Form, source)
if err == nil {
fmt.Println(t.String())
} else {
fmt.Println(err)
}
}
Error :parsing time "2014-04-22 23:41:12 +0800 CST": month out of range
I get source by time.Now().String(), but I could not convert it back. What's wrong with this piece of code?
From the documentation:
Parse parses a formatted string and returns the time value it
represents. The layout defines the format by showing how the reference
time,
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. Predefined
layouts ANSIC, UnixDate, RFC3339 and others describe standard and
convenient representations of the reference time. For more information
about the formats and the definition of the reference time, see the
documentation for ANSIC and the other constants defined by this
package.
(Bolding mine).
So what you want is
Form := "2006-01-02 15:04:05.000000000 -0700 MST"
Which is the date listed in that quote in the format of your input string. One thing to note while I was writing this on the playground to confirm is that it looks like on the part 05.000000000 (the seconds and fractions of seconds) you need the format string to contain exactly as many decimal points as the string you want to parse.
Here's a playground version showing it works: http://play.golang.org/p/dRniJbqgl7

Resources