Go / golang time.Now (). UnixNano () convertir a milisegundos?

83

¿Cómo puedo obtener la hora Unix en Go en milisegundos?

Tengo la siguiente función:

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

Necesito menos precisión y solo quiero milisegundos.

mconlin
fuente

Respuestas:

130

Solo divídelo:

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

Aquí hay un ejemplo que puede compilar y ejecutar para ver el resultado

package main

import (
    "time"
    "fmt"
)

func main() {
    a := makeTimestamp()

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

func makeTimestamp() int64 {
    return time.Now().UnixNano() / int64(time.Millisecond)
}
Uno de uno
fuente
40
El cálculo anterior realmente no tiene sentido. No divides nanosegundos por milisegundos. Ocurre que golang elige representar tiempos hasta nanosegundos y la constante 'Milisegundo' es 1,000,000. Matemáticamente hablando, el cálculo debe ser: time.Now().UnixNano() * (time.Nanosecond / time.Millisecond). Sin embargo, es mejor cambiar el orden debido a la división de enteros:time.Nanosecond * time.Now().UnixNano() / time.Millisecond
Jonno
4
gracias por eso. Puede confiar en esa garantía, pero en realidad se trata de un error del año 2000. Puede romperse en algún momento en el futuro. ¿Por qué elegir la representación matemática incorrecta?
Jonno
2
son constantes arbitrarias. Pueden cambiar en el futuro. El paquete de tiempo "funciona" actualmente con precisión de nanosegundos, pero esa es una elección arbitraria que lleva a establecer el tiempo. Milisegundos = 1.000.000. Tenga en cuenta que incluso en el mismo archivo al que hizo referencia, time.Milisecond se establece en 1000 * Microsecond, porque matemáticamente hablando eso es lo que debería representar. Me estoy desconectando - Espero que mi explicación ayude
Jonno
11
-1 Esto está mal. Tus unidades no cuadran. Busque el análisis dimensional de la física. Tu resultado no representa el tiempo.
Kugel
7
Respuesta rápida para personas ocupadas. Mire https://gobyexample.com/epoch
honzajde
63

Como señala @Jono en la respuesta de @ OneOfOne, la respuesta correcta debe tener en cuenta la duración de un nanosegundo. P.ej:

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

La respuesta de OneOfOne funciona porque time.Nanosecondresulta ser 1, y dividir por 1 no tiene ningún efecto. No sé lo suficiente sobre ir para saber qué probabilidades hay de que esto cambie en el futuro, pero para la respuesta estrictamente correcta, usaría esta función, no la respuesta de OneOfOne. Dudo que haya alguna desventaja en el rendimiento, ya que el compilador debería poder optimizar esto perfectamente.

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

Otra forma de ver esto es que ambos time.Now().UnixNano()y time.Millisecondusan las mismas unidades (Nanosegundos). Siempre que eso sea cierto, la respuesta de OneOfOne debería funcionar perfectamente.

Bjorn Roche
fuente
4
El valor de la .UnixNano()voluntad siempre sea el tiempo en nanosegundos, time.Millisecondserá siempre el valor de bien, lo has adivinado, una milésima de segundo, por lo que incluso si por cualquier razón estúpida la constante cambia de valor, dividiendo UnixNano por milisegundo será siempre devolver el valor en milisegundos.
OneOfOne
9
Las unidades de Unix.Nano no están en duda; ni tampoco el valor del tiempo. Milisegundos. Lo que está en cuestión es la unidad de tiempo: milisegundos. Resulta que se define en nanosegundos, por lo que su respuesta funciona. Si time.Milliseconds se midieran en otras unidades (digamos, microsegundos), la respuesta que dio no funcionaría.
Bjorn Roche
2
@BjornRoche Llego un poco tarde a esta fiesta, pero ¿no sería la respuesta correcta (int64(time.Now().UnixNano() / int64(time.Nanosecond))/int64(time.Millisecond)? ns/(ms/ns)Vuelve el análisis dimensional ns^2/ms. Tu respuesta también funciona porque time.Nanosecond=1, pero las unidades están apagadas ...
The Puma
1
@thepuma Ha pasado un tiempo, así que podría estar viendo esto mal o entendiéndolo mal, pero ns / (ms / ns) es equivalente a ns ^ 2 / ms, por lo que ambas respuestas deberían funcionar.
Bjorn Roche
Esta respuesta es correcta porque ejecutar esto mostrará el mismo resultado que cuando se convierte utilizando el convertidor en línea unitconverters.net/prefixes/nano-to-milli.htm
user666
55

Mantenlo simple.

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

Creo que es mejor redondear el tiempo a milisegundos antes de la división.

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

Aquí hay un programa de ejemplo:

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

El programa anterior imprimió el resultado a continuación en mi máquina:

123
124
1472313624305
2016-08-28 01:00:24.305 +0900 JST
Hnakamur
fuente
Olvidó mencionar por qué cree que es mejor redondear el tiempo a milisegundos.
Gurpartap Singh
1

La solución de lectura simple pero precisa sería:

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

Esta función:

  1. Redondea correctamente el valor al milisegundo más cercano (compárese con la división de enteros: simplemente descarta la parte decimal del valor resultante);
  2. No se sumerge en los aspectos específicos del tiempo Go. Coerción de duración: ya que utiliza una constante numérica que representa un divisor absoluto de milisegundos / nanosegundos.

PD: He ejecutado pruebas de rendimiento con divisores constantes y compuestos, casi no mostraron diferencias, así que siéntase libre de usar una solución más legible o más estricta en el lenguaje.

Liubov
fuente
Si desea saber el tiempo correcto de Unix en milisegundos (milisegundos desde la Época), no debe usar Round (), ya que redondeará la mitad del tiempo, y su resultado contendrá un milisegundo que aún no ha transcurrido por completo.
Torbenl
Gracias por una nota, @torbenl: esto puede ser importante para la mayoría de los sistemas (la mía es una exclusión, esta vez se almacena solo para el historial).
Liubov