将Go语言中的time.Now().UnixNano()转换为毫秒?

134

如何在Go中以毫秒获取Unix时间?

我有以下函数:

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

我需要的精度较低,只需要毫秒。

7个回答

223
2021年的答案:
截至go v1.17,time包添加了UnixMicro()UnixMilli(),因此正确的答案应该是:time.Now().UnixMilli() 对于go v.1.16及更早版本:
只需进行除法运算:
func makeTimestamp() int64 {
    return time.Now().UnixNano() / 1e6
}

1e6,即1 000 000,是一毫秒中的纳秒数。

这里有一个示例,您可以编译并运行以查看输出结果。

package main

import (
    "time"
    "fmt"
)

func main() {
    a := makeTimestamp()

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

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

52
上述计算并没有实际意义,因为你不能用毫秒除以纳秒。 事实上,golang选择将时间表示为纳秒,而常量“Millisecond”为1,000,000。从数学上讲,正确的计算方式是:time.Now().UnixNano() * (time.Nanosecond / time.Millisecond)。但是由于整数除法的原因,最好更改顺序:time.Nanosecond * time.Now().UnixNano() / time.Millisecond - Jonno
5
谢谢。您可以依靠此保证,但实际上这是一个Y2K问题,未来可能会出现故障。为什么选择错误的数学表达式? - Jonno
15
这是错误的。你的单位不匹配。请查阅物理学中的量纲分析。你得出的结果并不代表时间。 - Kugel
10
忙碌的人们快速回答:查看https://gobyexample.com/epoch。 - honzajde
2
这个答案完全错误。请使用 time.Now().UnixNano() / int64(1e6) - clay
显示剩余10条评论

69

保持简单。

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

1
如果Unix纳秒时间不能由int64表示(即在1678年之前或2262年之后的日期),则UnixNano结果未定义。 - chaokunyang

68

正如@Jono在@OneOfOne的回答中指出的那样,正确的答案应该考虑到纳秒的持续时间。例如:

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

OneOfOne的回答能够奏效,因为time.Nanosecond恰好等于1,除以1没有任何影响。我不了解go语言可能在未来改变的概率有多大,但对于严格正确的答案,我会使用这个函数而不是OneOfOne的答案。我怀疑没有性能劣势,因为编译器应该能够很好地进行优化。

请参阅https://en.wikipedia.org/wiki/Dimensional_analysis

另一种看待这个问题的方法是,time.Now().UnixNano()time.Millisecond都使用相同的单位(纳秒)。只要这是真实的,OneOfOne的答案应该能够完美地工作。


5
.UnixNano() 的值将始终为纳秒时间,time.Millisecond 始终为毫秒的值,因此即使由于某种愚蠢的原因常量的值发生更改,将 UnixNano 除以 Millisecond 将始终返回毫秒值。 - OneOfOne
9
Unix.Nano的单位并不成问题,time.Millisecond的值也不成问题。现在问题是time.Millisecond的单位。它恰好被定义为纳秒,这就是为什么你的答案有效的原因。如果time.Millisecond以其他单位(比如微秒)来衡量,你给出的答案将不再有效。 - Bjorn Roche
2
@BjornRoche 我来晚了,但是正确的答案不应该是 (int64(time.Now().UnixNano() / int64(time.Nanosecond))/int64(time.Millisecond) 吗?维度分析 ns/(ms/ns) 返回 ns^2/ms。你的答案也可以工作,因为 time.Nanosecond=1,但单位不对... - The Puma
1
@thepuma 好久不见了,所以我可能看错了或者误解了你的意思,但是 ns/(ms/ns) 相当于 ns^2/ms,所以两个答案都可以。 - Bjorn Roche
这个答案是正确的,因为运行它将显示与使用在线转换器https://www.unitconverters.net/prefixes/nano-to-milli.htm进行转换时相同的结果。 - user666
如果您需要最佳性能,请将分母转换为常量。没有理由每次想要当前时间时都重新计算:var millisConversion = (int64(time.Millisecond)/int64(time.Nanosecond)) - thebiggestlebowski

12

如何在Go中以毫秒为单位获取Unix时间?

Go 1.17及以上版本

从Go 1.17开始,不再需要将纳秒转换为毫秒。您可以直接使用Time.UnixMilli方法:

// 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


5

3

我认为在除法运算之前,将时间四舍五入到毫秒会更好。

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

这是一个示例程序:

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())
}

上面的程序在我的机器上输出了下面的结果:
123
124
1472313624305
2016-08-28 01:00:24.305 +0900 JST

1
你忘了提到为什么你认为将时间舍入到毫秒更好。 - Gurpartap Singh

2

简单但准确的解决方案是:

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

这个函数:

  1. 可以正确地将值四舍五入到最近的毫秒(与整数除法相比:它只会丢弃结果值的小数部分);
  2. 不会涉及到 Go 特定的时间.Duration 强制转换,因为它使用了一个表示绝对毫秒/纳秒分隔符的数字常量。

P.S. 我已经使用常量和组合分隔符运行了基准测试,它们显示几乎没有差别,所以您可以使用更易读或更符合语言规范的解决方案。


1
如果您想知道正确的Unix毫秒时间(自纪元以来的毫秒数),则不应使用Round()函数,因为它会将一半的时间向上舍入,导致结果包含尚未完全经过的毫秒。 - torbenl
感谢您的留言,@torbenl - 这可能对大多数系统都很重要(我的是个例外,这次只是为了历史记录而保存)。 - Liubov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接