Idź / golang time.Now (). UnixNano () przekonwertować na milisekundy?

83

Jak uzyskać czas systemu Unix w Go w milisekundach?

Mam następującą funkcję:

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

Potrzebuję mniej precyzji i chcę tylko milisekund.

mconlin
źródło

Odpowiedzi:

130

Po prostu podziel to:

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

Oto przykład, który możesz skompilować i uruchomić, aby zobaczyć dane wyjściowe

package main

import (
    "time"
    "fmt"
)

func main() {
    a := makeTimestamp()

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

func makeTimestamp() int64 {
    return time.Now().UnixNano() / int64(time.Millisecond)
}
OneOfOne
źródło
40
Powyższe obliczenia nie mają sensu. Nie dzieli się nanosekund przez milisekundy. Tak się składa, że ​​golang wybrał przedstawianie czasów z dokładnością do nanosekund, a stała „Milisekunda” to 1 000 000. Matematycznie rzecz biorąc, obliczenie powinno być: time.Now().UnixNano() * (time.Nanosecond / time.Millisecond). Jednak najlepiej zmienić kolejność ze względu na dzielenie liczb całkowitych:time.Nanosecond * time.Now().UnixNano() / time.Millisecond
Jonno
4
Dziękuję za to. Możesz polegać na tej gwarancji, ale w efekcie jest to błąd roku 2000. W pewnym momencie może się zepsuć. Dlaczego wybrać niewłaściwą reprezentację matematyczną?
Jonno
2
są to dowolne stałe. W przyszłości mogą się zmienić. Pakiet czasu obecnie „działa” z dokładnością do nanosekund, ale jest to arbitralny wybór prowadzący do ustawienia czasu. Milisekunda = 1 000 000. Zauważ, że nawet w tym samym pliku, do którego się odnosiliśmy, czas Milisekunda jest ustawiony na 1000 * mikrosekund, ponieważ z matematycznego punktu widzenia to właśnie powinien reprezentować. Przechodzę offline - Mam nadzieję, że moje wyjaśnienie pomoże
Jonno
11
-1 To jest po prostu błędne. Twoje jednostki się nie sumują. Wyszukaj analizę wymiarową z fizyki. Twój wynik nie reprezentuje czasu.
Kugel
7
Szybka odpowiedź dla zapracowanych ludzi. Spójrz na https://gobyexample.com/epoch
honzajde
64

Jak @Jono wskazuje w odpowiedzi @ OneOfOne, poprawna odpowiedź powinna uwzględniać czas trwania nanosekundy. Na przykład:

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

Odpowiedź OneOfOne działa, ponieważ time.Nanosecondtak się składa 1, a dzielenie przez 1 nie ma żadnego efektu. Nie wiem wystarczająco dużo na temat idź, aby wiedzieć, jakie jest prawdopodobieństwo, że to się zmieni w przyszłości, ale dla ściśle poprawnej odpowiedzi użyłbym tej funkcji, a nie odpowiedzi OneOfOne. Wątpię, czy jest jakakolwiek wada wydajności, ponieważ kompilator powinien być w stanie doskonale to zoptymalizować.

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

Innym sposobem patrzenia na to jest to, że oba time.Now().UnixNano()i time.Millisecondużywają tych samych jednostek (nanosekund). Dopóki to prawda, odpowiedź OneOfOne powinna działać doskonale.

Bjorn Roche
źródło
4
Wartość .UnixNano()woli zawsze będzie czas w nanosekund, time.Millisecondbędą zawsze mieć wartość no, to, milisekundy domyślić, więc nawet jeśli z jakiegoś idiotycznego powodem ciągłych zmian wartości, dzieląc UnixNano przez milisekundę będzie zawsze zwraca wartość w milisekundach.
OneOfOne
9
Jednostki Unix.Nano nie są kwestionowane; nie jest też wartością czasu. Milisekunda. Co jest w pytaniu to jednostka time.Millisecond. Zdarza się, że jest definiowany w nanosekundach, dlatego Twoja odpowiedź działa. Gdyby czas Milisekund mierzono w innych jednostkach (powiedzmy mikrosekundach), udzielona przez Ciebie odpowiedź nie zadziała.
Bjorn Roche
2
@BjornRoche Trochę spóźniłem się na tę imprezę, ale czy nie byłaby to prawidłowa odpowiedź (int64(time.Now().UnixNano() / int64(time.Nanosecond))/int64(time.Millisecond)? Analiza wymiarowa ns/(ms/ns)powraca ns^2/ms. Twoja odpowiedź również działa, ponieważ time.Nanosecond=1, ale jednostki są wyłączone ...
Puma,
1
@thepuma Minęło trochę czasu, więc mogę patrzeć na to źle lub źle cię zrozumieć, ale ns / (ms / ns) jest równoważne z ns ^ 2 / ms, więc obie odpowiedzi powinny działać.
Bjorn Roche
Ta odpowiedź jest poprawna, ponieważ uruchomienie tego spowoduje wyświetlenie tego samego wyniku, co podczas konwersji za pomocą konwertera online unitconverters.net/prefixes/nano-to-milli.htm
user666
55

Nie komplikuj.

func NowAsUnixMilli() int64 {
    return time.Now().UnixNano() / 1e6
}
stratovarius
źródło
2

Myślę, że przed podziałem lepiej zaokrąglić czas do milisekund.

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

Oto przykładowy 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())
}

Powyższy program wydrukował poniższy wynik na moim komputerze:

123
124
1472313624305
2016-08-28 01:00:24.305 +0900 JST
hnakamur
źródło
Zapomniałeś wspomnieć, dlaczego uważasz, że lepiej zaokrąglić czas do milisekund.
Gurpartap Singh
1

Prostym do odczytania, ale precyzyjnym rozwiązaniem byłoby:

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

Ta funkcja:

  1. Prawidłowo zaokrągla wartość do najbliższej milisekundy (porównaj z dzieleniem całkowitym: po prostu odrzuca część dziesiętną uzyskanej wartości);
  2. Nie zagłębia się w specyfikę czasu w Go. Koercja czasowa - ponieważ używa stałej numerycznej, która reprezentuje absolutny dzielnik milisekund / nanosekund.

PS Przeprowadziłem testy porównawcze z dzielnikami stałymi i kompozytowymi, nie wykazały one prawie żadnej różnicy, więc nie krępuj się użyć rozwiązania bardziej czytelnego lub bardziej ścisłego językowo.

Lubow
źródło
Jeśli chcesz poznać poprawny czas uniksowy w milisekundach (milisekundach od epoki), nie powinieneś używać metody Round (), ponieważ zaokrągli to w górę połowę czasu, a wynik będzie zawierał milisekundę, która jeszcze nie upłynęła w pełni.
torbenl
Dzięki za uwagę, @torbenl - może to być ważne dla większości systemów (mój jest wyjątkiem, tym razem jest przechowywany tylko dla historii).
Liubov