I have an API endpoint which will gather some structured data and one of the fields is a time stamp with this format:
"2022-08-30 09:05:27.567995"
My requirement is to caculate the number of days since this timestamp style.
I have this code which is working but I am looking for improvements goplayground:
package main
import (
"fmt"
"math"
"time"
)
func main() {
s1 := "2023-01-20"
date1, _ := time.Parse("2006-01-02", s1)
t1 := time.Now().Round(0)
days := int(math.Ceil(t1.Sub(date1).Hours() / 24))
fmt.Println("days: ", days)
}
I have two questions:
I was not able to find anything in time.Time that recogizes that time format, so I have done string parsing instead, to get just the date (parsing at first white space), which I will insert into the
s1
as a variable. That is fine (code not listed here) but I would prefer if time.Time could parse just the date, from that format ("2022-08-30 09:05:27.567995"
).Is there a better way to calculate the days since the timestamp, perhaps without having to import the math package? I was somewhat suprised at how difficult this seemed to be because I thought time.Since() would be able to do this, but I was not successful with that, so I came up with this code.
CodePudding user response:
I tried the following with time.Since()
that works, as I think, as expected:
package main
import (
"fmt"
"time"
)
func main() {
// this is the input from JSON
// used this as an example for checking calculation in Go playground
// which starts time at 2009-11-10 23:00:00 UTC
timeStr := "2009-11-11 23:00:00.000000"
parseLayout := "2006-01-02 15:04:05.000000"
t, err := time.Parse(parseLayout, timeStr)
if err != nil {
fmt.Printf("Error parsing datetime value %v: %w", timeStr, err)
}
durationDays := int(time.Since(t).Abs().Hours() / 24)
fmt.Println(durationDays)
}
When you use the format string posted by Matteo your time string should be parsed correctly. See https://pkg.go.dev/time#pkg-constants for format string details.
CodePudding user response:
For the first point of your question, you could parse using the pattern 2006-01-02 15:04:05.999999
like:
package main
import (
"fmt"
"time"
)
func main() {
x := "2022-08-30 09:05:27.567995"
fmt.Println(time.Parse("2006-01-02 15:04:05.999999", x))
}
See https://go.dev/play/p/v4TSXJyNOxg
CodePudding user response:
JSON doesn't have date\datetime data type and you would parse from string.
json := "2022-08-30 09:05:27.567995"
t := time.Parse("2006-01-02 15:04:05.999999", json)
You don't need the Math package:
package main
import (
"fmt"
"time"
)
func main() {
s1 := "2023-01-20" // or "2022-08-30 09:05:27.567995"
date1, _ := time.Parse("2006-01-02", s1)
t1 := time.Now()
// Unfortunately there isn't a direct truncation to Date only
y, m, d := t1.Date()
t1 = time.Date(y, m, d, 0, 0, 0, 0, time.UTC)
// now is truncated to Date
days := t1.Sub(date1).Hours() / 24
fmt.Println("days: ", days)
}
EDIT: Extending to your JSON case, you would need truncation to date a lot. You could do something like this:
package main
import (
"fmt"
"time"
)
type myTime time.Time
func main() {
s1 := "2023-01-20 09:05:27.567995" // or "2022-08-30 09:05:27.567995"
date1, _ := time.Parse("2006-01-02 15:04:05.999999", s1)
date1 = myTime(date1).DateOnly()
t1 := myTime(time.Now()).DateOnly()
days := t1.Sub(date1).Hours() / 24
fmt.Println("days: ", days)
}
func (t myTime) DateOnly() time.Time {
y, m, d := time.Time(t).Date()
return time.Date(y, m, d, 0, 0, 0, 0, time.UTC)
}