解码十六进制时间戳,可能是文件时间。

huangapple go评论84阅读模式
英文:

Decode Hex Timestamp, probably filetime

问题

我正在努力解决一个时间戳的问题,我想将其转换为可读的格式。这个时间戳来自OPCUA协议,应该是自1601年1月1日以来的百纳秒数,所以应该是文件时间。然而,尝试了这里发布的各种解决方案后,我无法将其转换为正确的时间。

以下是一些示例:

1c67dc4ab30dd201 -> 2016年9月13日 13:38:05.343106800 CET
15605a199070d201 -> 2017年1月17日 08:05:35.012046900 CET
322b4f629970d201 -> 2017年1月17日 09:12:02.882846600 CET

由于Wireshark能够解码它,所以一定有办法解决,也许有人能够告诉我需要哪些步骤来完成它。

英文:

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, <br>

1c67dc4ab30dd201 -&gt; Sep 13, 2016 13:38:05.343106800 CET 
15605a199070d201 -&gt; Jan 17, 2017 08:05:35.012046900 CET 
322b4f629970d201 -&gt; 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

得分: 2

我不了解OPCUA协议,但是你的十六进制时间戳可以按照以下方式转换为Go的时间戳:

首先,需要反向读取时间戳的字节(与你使用的字节顺序不同)。

所以,你需要将这些值:

0x1c67dc4ab30dd201, 0x15605a199070d201, 0x322b4f629970d201

反转字节并使用以下值:

0x01d20db34adc671c, 0x01d27090195a6015, 0x01d27099624f2b32

接下来,这些值是以10微秒为单位的,所以要转换为纳秒,需要乘以100。

最后,相对于纪元(1970年1月1日UTC),偏移量为369年

最终的转换代码如下:

var delta = time.Date(1970-369, 1, 1, 0, 0, 0, 0, time.UTC).UnixNano()

func convert(t int64) time.Time {
	// 反转字节:
	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)
}

测试代码如下:

// 如果你想要使用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))
}

输出结果如下(可以在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

处理[]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))

输出结果如下(这个示例也在上面链接的Playground示例中):

2017-01-17 09:12:02.8828466 +0100 CET
英文:

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 &lt; 8; i, t = i+1, t&gt;&gt;8 {
		t2 = t2&lt;&lt;8 | t&amp;0xff
	}

	return time.Unix(0, t2*100+delta)
}

Testing it:

// If you want results in CET:
cet, err := time.LoadLocation(&quot;CET&quot;)
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

huangapple
  • 本文由 发表于 2017年1月17日 16:25:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/41692192.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定