This is an old question but I noticed that a practical answer is missing.
For example, we were working with the MavLink protocol and we need to process a message with a structure defined here.
If we have this data structure:
Field Name |
Type |
Units |
Description |
time_boot_ms |
uint64_t |
ms |
Timestamp (time since system boot). |
press_abs |
float |
hPa |
Absolute pressure |
press_diff |
float |
hPa |
Differential pressure 1 |
temperature |
int16_t |
cdegC |
Absolute pressure temperature |
temperature_press_diff ** |
int16_t |
cdegC |
Differential pressure temperature (0, if not available). Report values of 0 (or 1) as 1 cdegC. |
So, we receive constant updates that we need to process using the time_boot_ms
as reference to insert them on the database and synchronize them with other messages.
What can we do?
As we noticed, the time is in milliseconds and everyone, that has some experience with Go, knows that for some unknown reason it's just way too complex to convert a millisecond resolution Unix timestamp
to time.Time
. The built-in time.Unix()
function only supports second and nanosecond precision.
How we can get millisecond precision?
Well, we might wait until they release the version 1.7
of Go or we either have to multiply the milliseconds to nanoseconds or split them into seconds and nanoseconds.
Lets implement the second idea, spit the into seconds and nanoseconds:
unixUTCtime := time.Unix(ms/int64(1000), (ms%int64(1000))*int64(1000000))
Now we can encapsulate it in a func
and use it in our main like this:
package main
import (
"fmt"
"time"
)
const msInSecond int64 = 1e3
const nsInMillisecond int64 = 1e6
// UnixToMS Converts Unix Epoch from milliseconds to time.Time
func UnixToMS (ms int64) time.Time {
return time.Unix(ms/msInSecond, (ms%msInSecond)*nsInMillisecond)
}
func main() {
unixTimes := [...]int64{758991688, 758992188, 758992690, 758993186}
var unixUTCTimes []time.Time
for index, unixTime := range unixTimes {
unixUTCTimes = append(unixUTCTimes, UnixToMS(unixTime))
if index > 0 {
timeDifference := unixUTCTimes[index].Sub(unixUTCTimes[index-1])
fmt.Println("Time difference in ms :--->", timeDifference)
}
}
}
The output will be:
Time difference in ms :---> 500ms
Time difference in ms :---> 502ms
Time difference in ms :---> 496ms
Check in Go Playground
Update
From version 1.7
, go
now provides millisecond resolution either to convert a unix time represented as a int64
number into a Time type (nanosecond precision) using time.UnixMilli function or from Time into millisecond precision using UnixMilli function. This is their implementation:
func Unix(sec int64, nsec int64) Time {
if nsec < 0 || nsec >= 1e9 {
n := nsec / 1e9
sec += n
nsec -= n * 1e9
if nsec < 0 {
nsec += 1e9
sec--
}
}
return unixTime(sec, int32(nsec))
}
func UnixMilli(msec int64) Time {
return Unix(msec/1e3, (msec%1e3)*1e6)
}
func (t Time) UnixMilli() int64 {
return t.unixSec()*1e3 + int64(t.nsec())/1e6
}
How to use this Teo?
Very simple just modify this line from the previous implementation of our example:
unixUTCTimes = append(unixUTCTimes, UnixToMS(unixTime))
with this code:
unixUTCTimes = append(unixUTCTimes, time.UnixMilli(unixTime))
No need of other functions just call time.UnixMilli(unixTime)
. Check the playground here.