【问题标题】:Go time.Now().UnixNano() convert to milliseconds?Go time.Now().UnixNano() 转换为毫秒?
【发布时间】:2014-07-30 03:26:35
【问题描述】:

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

我有以下功能:

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

我需要更少的精度,只需要毫秒。

【问题讨论】:

    标签: time go unix-timestamp date-conversion


    【解决方案1】:

    2021 年的答案:

    从 go v1.17 开始,time 包添加了 UnixMicro()UnixMilli(),因此正确答案是:time.Now().UnixMilli()

    原答案:

    分吧:

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

    【讨论】:

    • 上面的计算真的没有意义。您不会将纳秒除以毫秒。碰巧 golang 选择将时间表示到纳秒,而常量“毫秒”是 1,000,000。从数学上讲,计算应该是:time.Now().UnixNano() * (time.Nanosecond / time.Millisecond)。但是,由于整数除法,最好更改顺序:time.Nanosecond * time.Now().UnixNano() / time.Millisecond
    • 谢谢。注意我没有说你得到了错误的结果。那是计算没有意义,并且您正在使用有关 go 常量的信息。如果明天 go 有一个新版本,它为时间单位选择了更高的精度,例如,time.Nanosecond == 10 time.Millisecond == 10,000,000,你的代码就会中断
    • 谢谢。欢迎您依赖该保证,但这实际上是一个 Y2K 错误。它可能会在未来的某个时候中断。为什么选择错误的数学表示?
    • -1 这是错误的。你的单位不加起来。从物理学中查找尺寸分析。您的结果不代表时间。
    • 忙碌人群的快速解答。看https://gobyexample.com/epoch
    【解决方案2】:

    正如@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 的答案应该会非常有效。

    【讨论】:

    • .UnixNano() 的值将始终以纳秒为单位,time.Millisecond始终为 well 的值,您猜对了, 毫秒,所以即使由于任何愚蠢的原因常量改变了值,将 UnixNano 除以毫秒将总是返回以毫秒为单位的值。
    • Unix.Nano 的单位没有问题; time.Millisecond 的值也不是。 is 是时间单位。毫秒。它恰好是在纳秒内定义的,这就是您的答案有效的原因。如果 time.Milliseconds 以其他单位(例如微秒)来衡量,那么您给出的答案将不起作用。
    • @BjornRoche 我参加这个聚会有点晚了,但正确的答案不是(int64(time.Now().UnixNano() / int64(time.Nanosecond))/int64(time.Millisecond)吗?维度分析ns/(ms/ns) 返回ns^2/ms。您的回答也有效,因为time.Nanosecond=1,但单位已关闭...
    • @thepuma 已经有一段时间了,所以我可能看错了或误解了你,但 ns/(ms/ns) 相当于 ns^2/ms,所以两个答案都应该有效。
    • 这个答案是正确的,因为运行它会显示与使用在线转换器unitconverters.net/prefixes/nano-to-milli.htm进行转换时相同的结果@
    【解决方案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
    

    【讨论】:

    • 你忘了说为什么你认为最好将时间四舍五入到毫秒。
    【解决方案4】:

    保持简单。

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

    【讨论】:

      【解决方案5】:

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

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

      这个函数:

      1. 正确地将值四舍五入到最接近的毫秒(与整数除法相比:它只是丢弃结果值的小数部分);
      2. 没有深入研究 Go 特定的时间。持续时间强制 - 因为它使用表示绝对毫秒/纳秒分频器的数字常数。

      附:我已经使用常量和复合分隔符运行基准测试,它们几乎没有差异,因此请随意使用更具可读性或更严格语言的解决方案。

      【讨论】:

      • 如果你想知道正确的 Unix 时间,以毫秒为单位(自纪元以来的毫秒数),你不应该使用 Round(),因为它会将一半的时间四舍五入,然后你的结果将包含一个毫秒,还没有完全过去。
      • 感谢@torbenl 的提醒 - 这对于大多数系统来说可能很重要(我的系统是一个例外,这个时间仅用于历史记录)。
      【解决方案6】:

      https://github.com/golang/go/issues/44196randall77 建议

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

      它利用了 Go 的 time.Duration 已经有 Milliseconds 方法这一事实。

      【讨论】:

        【解决方案7】:

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

        转到 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
        

        游乐场:https://play.golang.org/p/JSExv5jw2ZW

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-07-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-17
          • 2013-06-23
          • 2011-02-13
          • 2011-02-14
          相关资源
          最近更新 更多