解码十六进制时间戳记,可能是文件时间 [英] Decode Hex Timestamp, probably filetime

查看:158
本文介绍了解码十六进制时间戳记,可能是文件时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力与时间戳转换,我想将其转换为人类可读格式,它来自OPCUA协议,自1601年1月1日以来应该在几百纳秒内,所以应该是文件时间.但是,尝试这里发布的各种解决方案后,我无法将其转换为正确的时间.

以下是一些示例,

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆