Преобразование времени. Тип значения микросекунд в миллисекундах

Я использую go-ping (https://github.com/sparrc/go-ping) библиотеку golang для непривилегированного пинга ICMP.

timeout := time.Second*1000
interval := time.Second
count := 5
host := p.ipAddr
pinger, cmdErr := ping.NewPinger(host)

pinger.Count = count
pinger.Interval = interval
pinger.Timeout = timeout
pinger.SetPrivileged(false)
pinger.Run()
stats := pinger.Statistics()

latency = stats.AvgRtt  // stats.AvgRtt is time.Duration type
jitter = stats.StdDevRtt// stats.StdDevRtt is time.Duration type

От запуска этого, я получаю латентность в миллисекундах и дрожание в микросекундах. Я хочу, чтобы один и тот же блок для обоих, пусть говорят миллисекунды, поэтому, когда я делаю jitter = stats.StdDevRtt/1000 или jitter = jitter/1000 (для преобразования микросекунд в миллисекунды), то, что я получаю, является джиттером в наносекундах:( Есть ли способ получить одинаковые миллисекунды для как латентность, так и дрожание.

Ответ 1

Число до time.Duration

time.Duration - это тип, имеющий int64 как его базовый тип, который хранит продолжительность в наносекундах.

Если вы знаете значение, но хотите, кроме наносекунд, просто умножьте желаемый блок, например:

d := 100 * time.Microsecond
fmt.Println(d) // Output: 100µs

Вышеупомянутое работает, потому что 100 является нетипизированным constant, и его можно автоматически преобразовать в time.Duration, у которого int64 базовый тип.

Обратите внимание, что если у вас есть значение как типизированное значение, вы должны использовать явное преобразование типа :

value := 100 // value is of type int

d2 := time.Duration(value) * time.Millisecond
fmt.Println(d2) // Output: 100ms

time.Duration на номер

Итак, time.Duration - это всегда наносекунды. Если вам это нужно в миллисекундах, например, все, что вам нужно сделать, это разделить значение time.Duration на количество наносекунд за миллисекунду:

ms := int64(d2 / time.Millisecond)
fmt.Println("ms:", ms) // Output: ms: 100

Другие примеры:

fmt.Println("ns:", int64(d2/time.Nanosecond))  // ns: 100000000
fmt.Println("µs:", int64(d2/time.Microsecond)) // µs: 100000
fmt.Println("ms:", int64(d2/time.Millisecond)) // ms: 100

Попробуйте примеры на Go Playground.

Если ваш дрожание (длительность) меньше единицы, в которую вы хотите преобразовать ее, вам нужно использовать деление с плавающей запятой, иначе будет выполняться целочисленное деление, которое отсекает часть дроби. Подробнее см.: Голанский округ до ближайшего 0,05.

Преобразуйте джиттер и блок в float64 перед делением:

d := 61 * time.Microsecond
fmt.Println(d) // Output: 61µs

ms := float64(d) / float64(time.Millisecond)
fmt.Println("ms:", ms) // Output: ms: 0.061

Вывод (попробуйте на Go Playground):

61µs
ms: 0.061

Ответ 2

Тип переменных latency и jitter равен time.Duration, который в определение его базовый тип - int64 и выражается в наносекунд.

Когда вы используете функции печати, вызывается метод String типа time.Duration и он использует h, s, m, µ, n при печати продолжительности, вот документация для метода String:

// String returns a string representing the duration in the form "72h3m0.5s".
// Leading zero units are omitted. As a special case, durations less than one
// second format use a smaller unit (milli-, micro-, or nanoseconds) to ensure
// that the leading digit is non-zero. The zero duration formats as 0s.

В временном пакете есть предварительно определенные константы, которые вы можете использовать для преобразования переменной продолжительности в предпочитаемую единицу времени, например

latencyInMicroSeconds := int64(jitter / time.Microsecond)

Обратите внимание, что мы преобразовали его в тип int, потому что, если вы его не будете в типе time.Duration, и значение этого типа считается находящимся в nano-втором блоке, но теперь это микро-секунда, вызывают дополнительную проблему в вычислениях, если вы собираетесь использовать функции временного пакета.