Перехід / час golang. Тепер (). 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)
}

40
Наведений вище розрахунок насправді не має сенсу. Ви не ділите наносекунди на мілісекунди. Буває так, що голанг вирішує представляти часи до наносекунди, а константа "Мілісекунда" становить 1 000 000. Математично кажучи, розрахунок повинен бути: time.Now().UnixNano() * (time.Nanosecond / time.Millisecond). Однак найкраще змінити порядок через цілочисельне ділення:time.Nanosecond * time.Now().UnixNano() / time.Millisecond
Йонно,

4
Дякую за це. Ви можете покластися на цю гарантію, але це фактично помилка Y2K. Це може зламатися в якийсь момент у майбутньому. Чому вибрати неправильне математичне подання?
Jonno,

2
вони довільні константи. Вони можуть змінитися в майбутньому. Наразі пакет часу "працює" з наносекундною точністю, але це довільний вибір, що веде до встановлення часу. Мілісекунда = 1000000 Зверніть увагу, що навіть у тому самому файлі, на який ви посилаєтесь, time.Milisecond має значення 1000 * мікросекунд, оскільки математично кажучи, саме це воно повинно представляти. Я переходжу в офлайн - сподіваюся, моє пояснення допоможе
Джонно

11
-1 Це просто неправильно. Ваші одиниці не складаються. Шукайте розмірний аналіз з фізики. Ваш результат не відображає час.
Кугель

7
Швидка відповідь для зайнятих людей. Подивіться на https://gobyexample.com/epoch
honzajde

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 02

9
Про одиниці Unix.Nano не йдеться; не є значенням часу. Мілісекунда. Що знаходиться під питанням є одиницею time.Millisecond. Трапляється, що це визначається за наносекунди, саме тому ваша відповідь працює. Якби час. Мілісекунди вимірювали в інших одиницях (скажімо, мікросекундах), відповідь, яку ви дали, не спрацювала б.
Bjorn Roche

2
@BjornRoche Я трохи запізнився на цю вечірку, але чи не буде правильною відповіддю (int64(time.Now().UnixNano() / int64(time.Nanosecond))/int64(time.Millisecond)? ns/(ms/ns)Повертається розмірний аналіз ns^2/ms. Ваша відповідь також працює, бо time.Nanosecond=1одиниці вимкнені ...
Пума,

1
@thepuma Минув якийсь час, тому, можливо, я дивлюся на це неправильно або нерозумію вас, але ns / (ms / ns) еквівалентно ns ^ 2 / ms, тому обидві відповіді повинні працювати.
Bjorn Roche

Ця відповідь правильна, оскільки запуск цього покаже той самий результат, що і при перетворенні за допомогою онлайн-перетворювача unitconverters.net/prefixes/nano-to-milli.htm
user666


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

Ви забули згадати, чому вважаєте, що краще округлити час до мілісекунд.
Гурпартап Сінгх

1

Простим для читання, але точним рішенням буде:

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

Ця функція:

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

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


Якщо ви хочете знати правильний час Unix у мілісекундах (мілісекундах з часів Епохи), вам не слід використовувати Round (), оскільки це буде округляти половину часу, а ваш результат міститиме мілісекунду, яка ще не минула повністю.
torbenl

Дякую за примітку, @torbenl - це може бути важливим для більшості систем (моя - це виключення, цей час зберігається лише для історії).
Любов
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.