In golang, Time.Format() removes trailing zeros from fractional part - go

How can I prevent go's Time.Format() from removing trailing zeros from fractional part? I have following unit tests that fails.
package main
import (
"testing"
"time"
)
func TestTimeFormatting(t *testing.T) {
timestamp := time.Date(2017, 1,2, 3, 4, 5, 600000*1000, time.UTC)
timestamp_string := timestamp.Format("2006-01-02T15:04:05.999-07:00")
expected := "2017-01-02T03:04:05.600+00:00"
if expected != timestamp_string {
t.Errorf("Invalid timestamp formating, expected %v, got %v", expected, timestamp_string)
}
}
Output:
$ go test
--- FAIL: TestTimeFormatting (0.00s)
main_test.go:14: Invalid timestamp formating, expected 2017-01-02T03:04:05.600+00:00, got 2017-01-02T03:04:05.6+00:00
FAIL
exit status 1
FAIL _/home/sasa/Bugs/go-formatter 0.001s
Any idea how to solve this?

Ah, it was there in documentation. One should use 000 instead of 999 if you want to keep zeros.
package main
import (
"testing"
"time"
)
func TestTimeFormatting(t *testing.T) {
timestamp := time.Date(2017, 1,2, 3, 4, 5, 600000*1000, time.UTC)
timestamp_string := timestamp.Format("2006-01-02T15:04:05.000-07:00")
expected := "2017-01-02T03:04:05.600+00:00"
if expected != timestamp_string {
t.Errorf("Invalid timestamp formating, expected %v, got %v", expected, timestamp_string)
}
}

Related

how to time.Parse() comma separate milliseconds in go

I have logs with timestamps that look like "2020-05-08 22:02:00,845". They have comma separated milliseconds, which is what is giving time.Parse issues. I can't seem to figure out how to make time.Parse happy with it. Here is sample code that produces the error in go version go1.13.4 darwin/amd64 (and in the playground linked below);
package main
import (
"time"
)
func main() {
ts := "2020-05-08 22:02:00,845"
_, err := time.Parse("2006-01-02 15:04:05,000", ts)
print(err.Error())
}
Running that code produces this error
parsing time "2020-05-08 22:02:00,845" as "2006-01-02 15:04:05,000": cannot parse "845" as ",000"
Here a link to the code in the go playground
So what would a format look like to parse this? Thanks for your help.
It's a bug already filed here
The behaviour is documented as such: "A fractional second is represented by adding a period and zeros to the end of the seconds section of layout string, as in "15:04:05.000" to format a time stamp with millisecond precision.
Workaround for that would be replacing "," with "."
package main
import (
"time"
"fmt"
"strings"
)
func main() {
ts := "2020-05-08 22:02:00,845"
ts = strings.Replace(ts, ",", ".", -1)
d, err := time.Parse("2006-01-02 15:04:05.000", ts)
if err != nil{
print(err.Error())
}
fmt.Println(d)
}
here is the Playground

How can you show the error value of Println if Println gets error if you can put it as variable?

It says:
Printf formats according to a format specifier and writes to standard output. It returns the number of bytes written and any write error encountered.
How do I create/test an error and show the error if it is stored in b
when I run the program it shows "nil" since no error, how can i show any error?
a,b :=fmt.Println("Hello, playground")
fmt.Println(a)
fmt.Println(b)
https://golang.org/pkg/fmt/#Println
func Println(a ...interface{}) (n int, err error)
https://play.golang.org/p/8Cjb2Sfunx7
It is unusual to have Println errors, the docs also this. But if you are really interesting in doing a test of it, it works:
package main
import (
"fmt"
"os"
"log"
)
func main() {
const name, age = "Kim", 22
os.Stdout.Close()
_, err := fmt.Println(name, "is", age, "years old.")
log.Fatal(err)
}
In order to artificially trigger an error we are closing the default Stdout file, used by Println. See the os documentation.

Cant explain why "55" is converted to "7"

package main
import (
"fmt"
"strconv"
)
func main() {
v := "55"
if s, err := strconv.Atoi(v); err == nil {
fmt.Println(string(v)) // 55
fmt.Println(s) // 55
fmt.Println(string(s)) // 7
}
}
https://play.golang.org/p/8V1npFiC9iH
s is an integer with the value 55, which is the ASCII (and UTF-8) encoding of the character "7". That's what's printed from the last statement.
When you call s, err := strconv.Atoi("55") you turn s into an integer. When you do string(s) afterwards, you're asking for a string that contains the character represented by that integer.
That character happens to be '7'. Try v := "65" and you'll get 'A', etc.

Golang: parse a signed int

I have some code that needs to be able to parse a string containing a 64-bit value into an int64. For example, ff11223344556677 is valid, but a downstream system wants that in an int64.
strconv.ParseInt("ff11223344556677", 16, 64) gives a range error - it only likes to parse positive integers. Is there a way to go about putting this value into an int64 even though it is going to be negative?
For example,
package main
import (
"fmt"
"strconv"
)
func main() {
u, err := strconv.ParseUint("ff11223344556677", 16, 64)
fmt.Printf("%x %v\n", u, err)
i := int64(u)
fmt.Println(i)
}
Output:
ff11223344556677 <nil>
-67234915848722825

Calculate number of days between two dates?

How can I calculate the number of days between two dates? In the code below I should get the number of hours, which means that I should only need to divide by 24. However, the result I get is something like -44929.000000. I'm only looking a day or two back so I would expect 24 or 48 hours.
package main
import (
"fmt"
"time"
)
func main() {
timeFormat := "2006-01-02"
t, _ := time.Parse(timeFormat, "2014-12-28")
fmt.Println(t)
// duration := time.Since(t)
duration := time.Now().Sub(t)
fmt.Printf("%f", duration.Hours())
}
Here's the executable Go code: http://play.golang.org/p/1MV6wnLVKh
Your program seems to work as intended. I'm getting 45.55 hours. Have you tried to run it locally?
Playground time is fixed, time.Now() will give you 2009-11-10 23:00:00 +0000 UTC always.
package main
import (
"fmt"
"time"
)
func main() {
date := time.Now()
fmt.Println(date)
format := "2006-01-02 15:04:05"
then,_ := time.Parse(format, "2007-09-18 11:58:06")
fmt.Println(then)
diff := date.Sub(then)
//func Since(t Time) Duration
//Since returns the time elapsed since t.
//It is shorthand for time.Now().Sub(t).
fmt.Println(diff.Hours())// number of Hours
fmt.Println(diff.Nanoseconds())// number of Nanoseconds
fmt.Println(diff.Minutes())// number of Minutes
fmt.Println(diff.Seconds())// number of Seconds
fmt.Println(int(diff.Hours()/24))// number of days
}
Here is the running code https://play.golang.org/p/Vbhh1cBKnh
the below code gives the list of all the days along with the number of days between the from date and to date:
you can click on the link for the code in
Go PlayGround:https://play.golang.org/p/MBThBpTqjdz
to := time.Now()
from := to.AddDate(0, -1, 0)
fmt.Println("toDate", to)
fmt.Println("fromDate", from)
days := to.Sub(from) / (24 * time.Hour)
fmt.Println("days", int(days))
noofdays := int(days)
for i := 0; i <= noofdays; i++ {
fmt.Println(from.AddDate(0, 0, i))
}
One caveat to be mindful of when using this technique of timeOne.Sub(timeTwo).Hours() / 24 is that daylights savings can cause a day to contain only 23 hours, throwing this calculation off slightly.
Happy programmer's day
package main
import (
"fmt"
"time"
)
func main() {
loc, _ := time.LoadLocation("UTC")
now := time.Now().In(loc)
firstDate := time.Date(now.Year(), 1, 1, 0, 0, 0, 0, loc)
diff := now.Sub(firstDate)
fmt.Printf("The difference between %s and today %s es %d days\n", now.String(), firstDate.String(), int(diff.Hours()/24)+1)
// Just a joke
if ( int(diff.Hours()/24)+1 == 256 ) {
fmt.Printf("¡Happy programmer's day!")
} else {
fmt.Printf("On my computer it works...!?")
}
}

Resources