解码十六进制时间戳记,可能是文件时间 [英] Decode Hex Timestamp, probably filetime
问题描述
以下是一些示例,
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
wireshark能够解码它,因此必须有一种方法,也许有人能够并且愿意告诉我要做哪些步骤.
我不知道OPCUA协议,但是可以将您的六次时间戳转换为Go时间戳,如下所示:
首先,必须向后(与您使用的字节顺序不同)读取时间戳记的字节.
所以代替这些:
0x1c67dc4ab30dd201, 0x15605a199070d201, 0x322b4f629970d201
您必须反转字节并使用这些字节:
0x01d20db34adc671c, 0x01d27090195a6015, 0x01d27099624f2b32
接下来,这些值以 10微秒为单位,因此要得到纳秒,请乘以100.
最后,与1970年1月1日世界标准时间的纪元相比,偏移量是 369年.
最终转化:
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)
}
测试:
// 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))
}
输出(在游乐场上尝试):
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
处理[]byte
输入
如果时间戳是作为字节片([]byte
)传递给您的,或者您有 io.Reader
,您可以从中读取字节片,而无需该字节反转循环;您可以使用以下转换器功能:
func convert2(data []byte) time.Time {
t := binary.LittleEndian.Uint64(data)
return time.Unix(0, int64(t)*100+delta)
}
测试:
data := []byte{0x32, 0x2b, 0x4f, 0x62, 0x99, 0x70, 0xd2, 0x01}
fmt.Println(convert2(data).In(cet))
输出(此链接也位于上面链接的游乐场示例中)
2017-01-17 09:12:02.8828466 +0100 CET
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.
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
这篇关于解码十六进制时间戳记,可能是文件时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!