Go / golang time.Now (). UnixNano () преобразовать в миллисекунды?

83

Как я могу узнать время Unix в Go в миллисекундах?

У меня есть такая функция:

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

Мне нужно меньше точности и нужны только миллисекунды.

Маконлин
источник

Ответы:

130

Просто разделите это:

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)
}
OneOfOne
источник
40
Приведенный выше расчет на самом деле не имеет смысла. Вы не делите наносекунды на миллисекунды. Бывает так, что голанг предпочитает представлять время с точностью до наносекунды, а постоянная «Миллисекунда» равна 1000000. Математически говоря, расчет должен быть: time.Now().UnixNano() * (time.Nanosecond / time.Millisecond). Однако лучше всего изменить порядок из-за целочисленного деления:time.Nanosecond * time.Now().UnixNano() / time.Millisecond
Jonno
4
Спасибо за это. Вы можете положиться на эту гарантию, но, по сути, это ошибка 2000 года. Он может сломаться в какой-то момент в будущем. Почему выбрали неправильное математическое представление?
Jonno
2
это произвольные константы. Они могут измениться в будущем. Пакет времени в настоящее время «работает» с точностью до наносекунды, но это произвольный выбор, ведущий к установке времени. Миллисекунда = 1 000 000. Обратите внимание, что даже в том же файле, на который вы ссылались, time.Milisecond установлено на 1000 * Microsecond, потому что математически это то, что он должен представлять. Я ухожу в автономный режим - надеюсь, мое объяснение поможет
Джонно
11
-1 Это просто неправильно. Ваши единицы не складываются. Найдите размерный анализ из физики. Ваш результат не отображает время.
Kugel
7
Быстрый ответ для занятых людей. Посмотрите https://gobyexample.com/epoch
honzajde
64

Как указывает @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. Он определяется в наносекундах, поэтому ваш ответ работает. Если время. Миллисекунды были измерены в других единицах (например, микросекундах), ответ, который вы дали, не сработал бы.
Бьорн Рош
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
Этот ответ правильный, потому что при его запуске будет отображаться тот же результат, что и при преобразовании с помощью онлайн-конвертера unitconverters.net/prefixes/nano-to-milli.htm
user666
55

Будь проще.

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
Hnakamur
источник
Вы забыли упомянуть, почему считаете, что время лучше округлить до миллисекунд.
Гурпартап Сингх
1

Простое, но точное решение:

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

Эта функция:

  1. Правильно округляет значение до ближайшей миллисекунды (сравните с целочисленным делением: просто отбрасывает десятичную часть полученного значения);
  2. Не углубляется в специфику времени Go. Приведение продолжительности - так как оно использует числовую константу, которая представляет собой абсолютный делитель миллисекунды / наносекунды.

PS Я проводил тесты с постоянными и составными делителями, они почти не показали разницы, поэтому не стесняйтесь использовать более читаемое или более строгое языковое решение.

Любовь
источник
Если вы хотите узнать правильное время Unix в миллисекундах (миллисекундах с начала эпохи), вам не следует использовать Round (), так как это округлит половину времени, и ваш результат будет содержать миллисекунду, которая еще не полностью истекла.
торбенл
Спасибо за замечание, @torbenl - это может быть важно для большинства систем (моя - исключение, на этот раз сохраняется только для истории).
Любовь