Go / golang time.Now()。UnixNano()转换为毫秒?


80

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

我有以下功能:

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

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

Answers:


123

只需将其划分:

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

这是一个示例,您可以编译并运行以查看输出

package main

import (
    "time"
    "fmt"
)

func main() {
    a := makeTimestamp()

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

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

39
上面的计算没有任何意义。您不会将纳秒除以毫秒。巧合的是,golang选择将时间表示为纳秒以下,常数“毫秒”为1,000,000。从数学上讲,计算应为:time.Now().UnixNano() * (time.Nanosecond / time.Millisecond)。但是,最好由于整数除法来更改顺序:time.Nanosecond * time.Now().UnixNano() / time.Millisecond
Jonno 2014年

4
感谢那。欢迎您依靠该保证,但这实际上是一个Y2K错误。在将来的某个时候可能会中断。为什么选择错误的数学表示形式?
延诺2014年

2
它们是任意常数。它们将来可能会改变。时间包目前以纳秒精度“工作”,但这是导致设置时间的任意选择。毫秒= 1,000,000。请注意,即使在您引用的同一文件中,time.Milisecond也设置为1000 * Microsecond,因为从数学上讲,这就是它应该表示的内容。我离线-希望我的解释对您
有所

10
-1这是错误的。您的单位不累加。从物理学中查找尺寸分析。您的结果不代表时间。
库格尔2015年

5
忙碌的人们的快速解答。看看https://gobyexample.com/epoch
honzajde 2015年

63

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

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

OneOfOne的答案之所以起作用,是因为time.Nanosecond碰巧是1,并且除以1无效。我对接下来的变化不太了解,但是对于严格正确的答案,我将使用此功能,而不是OneOfOne的答案。我怀疑是否存在性能劣势,因为编译器应该能够很好地对其进行优化。

参见https://en.wikipedia.org/wiki/Dimensional_analysis

看待这个另一种方式是,无论time.Now().UnixNano()time.Millisecond使用相同的单位(纳秒)。只要这是真的,OneOfOne的答案就可以很好地工作。


4
.UnixNano()始终是在十亿分之一秒的时间,time.Millisecond始终是值好了,你猜对了,一毫秒,所以即使任何愚蠢的理由不断变化值,除以UnixNano微差将始终在毫秒返回值。
OneOfOne

9
Unix.Nano的单位不成问题;时间的价值也不是毫秒。什么问题是time.Millisecond的单位。它恰好以纳秒为单位定义,这就是您的答案起作用的原因。如果用其他单位(例如微秒)来度量time.Milliseconds,则您给出的答案将无效。
Bjorn Roche

2
@BjornRoche我参加这个聚会有点晚了,但是正确的答案不是(int64(time.Now().UnixNano() / int64(time.Nanosecond))/int64(time.Millisecond)吗?尺寸分析ns/(ms/ns)返回ns^2/ms。您的答案也有效,因为time.Nanosecond=1,但单位已关闭...
Puma

1
@thepuma已经有一段时间了,所以我可能正在看这个错误或误解您,但是ns /(ms / ns)相当于ns ^ 2 / ms,因此这两个答案都应该起作用。
比约恩·罗氏

这个答案是正确的,因为运行此命令将显示与使用在线转换器unitconverters.net/prefixes/nano-to-milli.htm
user666

54

把事情简单化。

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

2

我认为最好在除法前将时间舍入到毫秒。

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

您忘了提到为什么您认为最好将时间舍入到毫秒。
Gurpartap Singh,

1

简单易读但精确的解决方案是:

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

该功能:

  1. 正确地将值舍入到最接近的毫秒数(与整数除法比较:它只舍弃结果值的小数部分);
  2. 不会深入到时间的Go特定内容。Duration强制—因为它使用表示绝对毫秒/纳秒分频器的数字常数。

PS我已经使用恒定和复合分隔符运行基准测试,它们几乎没有差异,因此请随时使用更具可读性或更多语言限制的解决方案。


如果您想知道正确的Unix时间(以毫秒为单位)(自大纪元以来的毫秒数),则不应该使用Round(),因为这将舍入一半的时间,因此结果将包含尚未完全过去的毫秒。
torbenl

感谢@torbenl的注释-这对于大多数系统而言可能很重要(我的排除在外,此时间仅用于历史记录)。
Liubov
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.