Go time.Now().UnixNano() convert to milliseconds?

How can I get Unix time in Go in milliseconds?

I have the following function:

func makeTimestamp() int64 {
return time.Now().UnixNano() % 1e6 / 1e3
}

I need less precision and only want milliseconds.

195020 次浏览

The 2021 answer:

As of go v1.17, the time package added UnixMicro() and UnixMilli(), so the correct answer would be: time.Now().UnixMilli()

Original answer:

Just divide it:

func makeTimestamp() int64 {
return time.Now().UnixNano() / int64(time.Millisecond)
}

Here is an example that you can compile and run to see the output

package main


import (
"time"
"fmt"
)


func main() {
a := makeTimestamp()


fmt.Printf("%d \n", a)
}


func makeTimestamp() int64 {
return time.Now().UnixNano() / int64(time.Millisecond)
}

As @Jono points out in @OneOfOne's answer, the correct answer should take into account the duration of a nanosecond. Eg:

func makeTimestamp() int64 {
return time.Now().UnixNano() / (int64(time.Millisecond)/int64(time.Nanosecond))
}

OneOfOne's answer works because time.Nanosecond happens to be 1, and dividing by 1 has no effect. I don't know enough about go to know how likely this is to change in the future, but for the strictly correct answer I would use this function, not OneOfOne's answer. I doubt there is any performance disadvantage as the compiler should be able to optimize this perfectly well.

See https://en.wikipedia.org/wiki/Dimensional_analysis

Another way of looking at this is that both time.Now().UnixNano() and time.Millisecond use the same units (Nanoseconds). As long as that is true, OneOfOne's answer should work perfectly well.

I think it's better to round the time to milliseconds before the division.

func makeTimestamp() int64 {
return time.Now().Round(time.Millisecond).UnixNano() / (int64(time.Millisecond)/int64(time.Nanosecond))
}

Here is an example program:

package main


import (
"fmt"
"time"
)


func main() {
fmt.Println(unixMilli(time.Unix(0, 123400000)))
fmt.Println(unixMilli(time.Unix(0, 123500000)))
m := makeTimestampMilli()
fmt.Println(m)
fmt.Println(time.Unix(m/1e3, (m%1e3)*int64(time.Millisecond)/int64(time.Nanosecond)))
}


func unixMilli(t time.Time) int64 {
return t.Round(time.Millisecond).UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond))
}


func makeTimestampMilli() int64 {
return unixMilli(time.Now())
}

The above program printed the result below on my machine:

123
124
1472313624305
2016-08-28 01:00:24.305 +0900 JST

Keep it simple.

func NowAsUnixMilli() int64 {
return time.Now().UnixNano() / 1e6
}

Simple-read but precise solution would be:

func nowAsUnixMilliseconds(){
return time.Now().Round(time.Millisecond).UnixNano() / 1e6
}

This function:

  1. Correctly rounds the value to the nearest millisecond (compare with integer division: it just discards decimal part of the resulting value);
  2. Does not dive into Go-specifics of time.Duration coercion — since it uses a numerical constant that represents absolute millisecond/nanosecond divider.

P.S. I've run benchmarks with constant and composite dividers, they showed almost no difference, so feel free to use more readable or more language-strict solution.

At https://github.com/golang/go/issues/44196 randall77 suggested

time.Now().Sub(time.Unix(0,0)).Milliseconds()

which exploits the fact that Go's time.Duration already have Milliseconds method.

How can I get Unix time in Go in milliseconds?

Go 1.17 and above

No more divisions from nanoseconds. Starting from Go 1.17 you can just use Time.UnixMilli method directly:

// a deterministic date value
t := time.Date(2021, 7, 16, 0, 0, 0, 0, time.UTC)


m := t.UnixMilli()
fmt.Println(m) // 1626393600000

Playground: https://play.golang.org/p/JSExv5jw2ZW