Decode Hex Timestamp, probably filetime

不问归期 提交于 2021-01-29 04:40:24

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!