Добавьте наносекунды с эпохи Win32 к Go времени - PullRequest
1 голос
/ 25 января 2020

Я пытаюсь обработать некоторые счетчики WMI, используя Go (как часть обучения Go), и пытаюсь выяснить, как сгенерировать необходимый объект времени.

Основой является эпоха Win32 (1601-01-01), а временная отметка образца составляет 13224382394716547600ns (или, скорее, 132243823947165476 100 нс единиц).

Вот что я пробовал:

тест 1 (добавление наносекунд)

win_epoch := time.Date(1601,1,1, 0, 0, 0, 0, time.UTC)
current_ts_1 := win_epoch.Add(13224382394716547600*time.Nanosecond)

тест 2 (добавление дней)

win_epoch := time.Date(1601,1,1, 0, 0, 0, 0, time.UTC)
current_ts_2 := win_epoch.AddDate(0,0,(132243823947165476/10000000 / 3600 / 24))

current_ts_1 в тесте 1 завершается с ошибкой переполнения.

current_ts_2 в тесте 2 дает мне разрешение только на уровне даты.

В идеале я бы смог получить разрешение в миллисекундах это. Существует ли способ не переполнять Длительность, передаваемую .Add(), и при этом получать это разрешение?

1 Ответ

3 голосов
/ 25 января 2020

Это преобразование требует работы с некоторыми огромными числами. Ваш пример time 13,224,382,394,716,547,600 слишком велик, чтобы поместиться в int64 (макс. 9,223,372,036,854,775,807), но вписывается в unit64.

Вы не можете использовать time.Duration при работе с этим, потому что это подсчет int64 наносекунд; как в документах говорится: «Представление ограничивает наибольшую представляемую продолжительность примерно 290 годами». Вот почему ваша первая попытка не удалась.

Однако есть другой способ создать время, которое будет работать лучше func Unix(sec int64, nsec int64) Time. Это берет данные в формате unix, и это время с 1 января 1970 года UT C (или 11644473600000000000, представленное в виде нс с windows эпоха ).

Использование эта информация позволяет выполнить преобразование:

func main() {
    const unixTimeBaseAsWin = 11644473600000000000 // The unix base time (January 1, 1970 UTC) as ns since Win32 epoch (1601-01-01) 
    const nsToSecFactor = 1000000000

    timeToConvert := uint64(13224382394716547600)

    unixsec := int64(timeToConvert  - unixTimeBaseAsWin ) / nsToSecFactor
    unixns := int64(timeToConvert  % nsToSecFactor)

    time := time.Unix(unixsec, unixns)
    fmt.Println(time.Local())
}

Примечание: я проверил это с помощью нескольких цифр, но предложил бы провести дополнительное тестирование, прежде чем полагаться на него.

...