Home > Enterprise >  get time in days from random date in Go
get time in days from random date in Go

Time:01-26

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:

  1. 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").

  2. 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)
}
  • Related