why does time.Parse parse the time incorrectly? - time

I'm trying to parse a string as time with but unfortunately go gets the wrong month (January instead of June)
package main
import "fmt"
import "time"
func main() {
t := "2014-06-23T20:29:39.688+01:00"
tc, _ := time.Parse("2006-01-02T15:04:05.000+01:00", t)
fmt.Printf("t was %v and tc was %v", t, tc)
}
Play

The problem is that your timezone offset is ill-defined in the layout: the reference offset is -0700. You defined yours as +01:00, so the 01 is interpreted as the month and erase the previously defined one. And as your working offset is 01 as well, it is parsed as january.
The following example works for me playground
package main
import "fmt"
import "time"
func main() {
t := "2014-06-23T20:29:39.688+01:00"
tc, _ := time.Parse("2006-01-02T15:04:05.000-07:00", t)
fmt.Printf("t was %v and tc was %v", t, tc)
}

Your layout string is incorrect. The numbers in the layout string have special meanings, and you are using 1 twice: once in the month portion and once in the time zone portion. The time zone in the string you are parsing is 01:00, so you are storing 1 into the month. This explains why the returned month was January (the first month).
A corrected layout string is 2006-01-02T15:04:05.000-07:00. Or, if you're happy with using Z to represent UTC, the time.RFC3339 constant might be appropriate.

Related

Convert timestamp as string [duplicate]

This question already has answers here:
Convert time.Time to string
(6 answers)
Closed 2 years ago.
I want to get a timestamp as string. If I use string conversion I got no error but the output is not readable.
Later, I want us it as a part of a filename.
It looks like a question mark for e.g. �
I found some examples like this: https://play.golang.org/p/bq2h3h0YKp
not solves completely me problem. thanks
now := time.Now() // current local time
sec := now.Unix() // number of seconds since January 1, 1970 UTC
fmt.Println(string(sec))
How could I get the timestamp as string?
Something like this works for me
package main
import (
"fmt"
"strconv"
"time"
)
func main() {
now := time.Now()
unix := now.Unix()
fmt.Println(strconv.FormatInt(unix, 10))
}
Here are two examples of how you can convert a unix timestamp to a string.
The first example (s1) uses the strconv package and its function FormatInt. The second example (s2) uses the fmt package (documentation) and its function Sprintf.
Personally, I like the Sprintf option more from an aesthetic point of view. I did not check the performance yet.
package main
import "fmt"
import "time"
import "strconv"
func main() {
t := time.Now().Unix() // t is of type int64
// use strconv and FormatInt with base 10 to convert the int64 to string
s1 := strconv.FormatInt(t, 10)
fmt.Println(s1)
// Use Sprintf to create a string with format:
s2 := fmt.Sprintf("%d", t)
fmt.Println(s2)
}
Golang Playground: https://play.golang.org/p/jk_xHYK_5Vu

Easy way to receive a string from day from time.Now()

I'm trying to get the day as a string from a time.Now() instance.
now := time.Now() // .String() would give me the entire date as a string which I don't need
day := now.Day()) // is what I want but as a String.
So string(day) tells me "can not convert day to string".
For me now.Day().String() would be nice but there is no such method...
I could now try to take time.Now().String() and manipulate until the day is left over. But there should be a easier way to do it...
Use strconv to convert int to string
strconv.Itoa(day)
You can import and use strconv as KibGzr mentioned. Just to give a complete example:
package main
import (
"fmt"
"time"
"strconv"
)
func main() {
now := time.Now()
day := now.Day()
fmt.Printf("%T\n",(day))
fmt.Println(strconv.Itoa(day))
dayString := strconv.Itoa(day)
fmt.Printf("%T",(dayString))
}
https://play.golang.org/p/Mqs24FJhCoi

How to convert a string time with milliseconds (hh:mm:ss.xxx) to time.Time?

Basically I have times like this one as a string:
15:56:36.113
I want to convert it to time.Time.
From what I am reading I cannot use milliseconds when using time.Parse().
Is there another way to convert my string to time.Time ?
Package time
Format Reference Time
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.
For example,
package main
import (
"fmt"
"time"
)
func main() {
t, err := time.Parse("15:04:05", "15:56:36.113")
if err != nil {
fmt.Println(err)
}
fmt.Println(t)
fmt.Println(t.Format("15:04:05.000"))
h, m, s := t.Clock()
ms := t.Nanosecond() / int(time.Millisecond)
fmt.Printf("%02d:%02d:%02d.%03d\n", h, m, s, ms)
}
Output:
0000-01-01 15:56:36.113 +0000 UTC
15:56:36.113
15:56:36.113
Note: The zero value of type Time is 0000-01-01 00:00:00.000000000 UTC.
package main
import (
"fmt"
"time"
)
func main() {
s := "15:56:36.113"
t,_ := time.Parse("15:04:05.000", s)
fmt.Print(t)
}
Output:
0000-01-01 15:56:36.113 +0000 UTC
You can play with it more here: https://play.golang.org/p/3A3e8zHQ8r

Error parsing time in Go with variable number of microseconds

I'm trying to parse a string into a time object. The issue is that the number of digits in the microseconds term changes, which breaks the parsing. For example, this works fine:
package main
import (
"fmt"
"time"
)
func main() {
timeText := "2017-03-25T10:01:02.1234567Z"
layout := "2006-01-02T15:04:05.0000000Z"
t, _ := time.Parse(layout, timeText)
fmt.Println(t)
}
But this causes an error, because the number of microseconds digits doesn't match the layout:
package main
import (
"fmt"
"time"
)
func main() {
timeText := "2017-03-25T10:01:02.123Z" // notice only 3 microseconds digits here
layout := "2006-01-02T15:04:05.0000000Z"
t, _ := time.Parse(layout, timeText)
fmt.Println(t)
}
How do I fix this so that the microseconds term is still parsed, but it doesn't matter how many digits there are?
Use 9s instead of zeros in the subsecond format, for example:
timeText := "2017-03-25T10:01:02.1234567Z"
layout := "2006-01-02T15:04:05.99Z"
t, _ := time.Parse(layout, timeText)
fmt.Println(t) //prints 2017-03-25 10:01:02.1234567 +0000 UTC
From the docs:
// Fractional seconds can be printed by adding a run of 0s or 9s after
// a decimal point in the seconds value in the layout string.
// If the layout digits are 0s, the fractional second is of the specified
// width. Note that the output has a trailing zero.
do("0s for fraction", "15:04:05.00000", "11:06:39.12340")
// If the fraction in the layout is 9s, trailing zeros are dropped.
do("9s for fraction", "15:04:05.99999999", "11:06:39.1234")

How can I extract the value of my current local time offset?

I'm struggling a bit trying to format and display some IBM mainframe TOD clock data. I want to format the data in both GMT and local time (as the default -- otherwise in the zone the user specifies).
For this, I need to get the value of the local time offset from GMT as a signed integer number of seconds.
In zoneinfo.go (which I confess I don't fully understand), I can see
// A zone represents a single time zone such as CEST or CET.
type zone struct {
name string // abbreviated name, "CET"
offset int // seconds east of UTC
isDST bool // is this zone Daylight Savings Time?
}
but this is not, I think, exported, so this code doesn't work:
package main
import ( "time"; "fmt" )
func main() {
l, _ := time.LoadLocation("Local")
fmt.Printf("%v\n", l.zone.offset)
}
Is there a simple way to get this information?
You can use the Zone() method on the time type:
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
zone, offset := t.Zone()
fmt.Println(zone, offset)
}
Zone computes the time zone in effect at time t, returning the abbreviated name of the zone (such as "CET") and its offset in seconds east of UTC.
Package time
func (Time) Local
func (t Time) Local() Time
Local returns t with the location set to local time.
func (Time) Zone
func (t Time) Zone() (name string, offset int)
Zone computes the time zone in effect at time t, returning the
abbreviated name of the zone (such as "CET") and its offset in seconds
east of UTC.
type Location
type Location struct {
// contains filtered or unexported fields
}
A Location maps time instants to the zone in use at that time.
Typically, the Location represents the collection of time offsets in
use in a geographical area, such as CEST and CET for central Europe.
var Local *Location = &localLoc
Local represents the system's local time zone.
var UTC *Location = &utcLoc
UTC represents Universal Coordinated Time (UTC).
func (Time) In
func (t Time) In(loc *Location) Time
In returns t with the location information set to loc.
In panics if loc is nil.
For example,
package main
import (
"fmt"
"time"
)
func main() {
t := time.Now()
// For a time t, offset in seconds east of UTC (GMT)
_, offset := t.Local().Zone()
fmt.Println(offset)
// For a time t, format and display as UTC (GMT) and local times.
fmt.Println(t.In(time.UTC))
fmt.Println(t.In(time.Local))
}
Output:
-18000
2016-01-24 16:48:32.852638798 +0000 UTC
2016-01-24 11:48:32.852638798 -0500 EST
I don't think it makes sense to manually convert time to another TZ. Use time.Time.In function:
package main
import (
"fmt"
"time"
)
func printTime(t time.Time) {
zone, offset := t.Zone()
fmt.Println(t.Format(time.Kitchen), "Zone:", zone, "Offset UTC:", offset)
}
func main() {
printTime(time.Now())
printTime(time.Now().UTC())
loc, _ := time.LoadLocation("America/New_York")
printTime(time.Now().In(loc))
}

Resources