问题
im struggling with a timestamp i want to convert to human readable format, it is from OPCUA protocol and is supposed to be in hundreds of nanoseconds since 1. Jan 1601, so it should be filetime. However, trying various solutions posted here i am not able to convert it to the right time.
Here are some examples,
1c67dc4ab30dd201 -> Sep 13, 2016 13:38:05.343106800 CET
15605a199070d201 -> Jan 17, 2017 08:05:35.012046900 CET
322b4f629970d201 -> Jan 17, 2017 09:12:02.882846600 CET
As wireshark is able to decode it there must be a way, maybe someone is able and willing to tell me which steps are necessary to do it.
回答1:
I don't know the OPCUA protocol, but your hexa timestamps can be converted to Go timetamps like this:
First, the bytes of the timestamps have to be read backward (different byteorder than you used).
So instead of these:
0x1c67dc4ab30dd201, 0x15605a199070d201, 0x322b4f629970d201
You have to reverse the bytes and work with these:
0x01d20db34adc671c, 0x01d27090195a6015, 0x01d27099624f2b32
Next, these values are in 10-microsecond unit, so to get nanoseconds, multiply by 100.
And last, the offset is 369 years compared to Epoch, which is January 1, 1970 UTC.
The final conversion:
var delta = time.Date(1970-369, 1, 1, 0, 0, 0, 0, time.UTC).UnixNano()
func convert(t int64) time.Time {
// reverse bytes:
var t2 int64
for i := 0; i < 8; i, t = i+1, t>>8 {
t2 = t2<<8 | t&0xff
}
return time.Unix(0, t2*100+delta)
}
Testing it:
// If you want results in CET:
cet, err := time.LoadLocation("CET")
if err != nil {
panic(err)
}
ts := []int64{0x1c67dc4ab30dd201, 0x15605a199070d201, 0x322b4f629970d201}
for _, t := range ts {
fmt.Println(convert(t).In(cet))
}
Output (try it on the Go Playground):
2016-09-13 13:38:05.3431068 +0200 CEST
2017-01-17 08:05:35.0120469 +0100 CET
2017-01-17 09:12:02.8828466 +0100 CET
Processing []byte
input
If the timestamp is handed to you as a byte slice ([]byte
), or you have an io.Reader from which you can read a byte slice, you don't need that byte-reversal loop; you can use the following converter function:
func convert2(data []byte) time.Time {
t := binary.LittleEndian.Uint64(data)
return time.Unix(0, int64(t)*100+delta)
}
Testing it:
data := []byte{0x32, 0x2b, 0x4f, 0x62, 0x99, 0x70, 0xd2, 0x01}
fmt.Println(convert2(data).In(cet))
Output (this one is also in the Playground example linked above):
2017-01-17 09:12:02.8828466 +0100 CET
来源:https://stackoverflow.com/questions/41692192/decode-hex-timestamp-probably-filetime