【问题标题】:Convert byte array to time_t将字节数组转换为 time_t
【发布时间】:2017-11-14 16:18:33
【问题描述】:

我有一个 linux 时钟,它向我发送带有字节的时钟,我不知道如何从中取出时钟,我知道它是一种“time_t”(这可能是自1970 年 1 月 1 日),请参阅下面的几个示例,我从时钟接收到的内容 (我不确定它是发送本地时间还是 GMT 时间)

这个字节代表 11/09/2017 16:52(当地时间)或 11/09/2017 21:52(GMT)

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,66,120,53,34,0,0,0

此字节表示 2017 年 11 月 10 日 10:27(当地时间)或 2017 年 11 月 10 日 15:27(格林威治标准时间)

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,162,111,54,34,0,0,0

此字节表示 2017 年 11 月 13 日 14:20(当地时间)或 2017 年 11 月 13 日 19:20(格林威治标准时间)

0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,160,154,58,34,0,0,0

【问题讨论】:

  • 看起来非常不寻常的字节顺序,因为第一个和第五个非零元素的变化最慢。
  • 对,可能这些数字代表的月份和年份都是一样的
  • 变化最慢的是年份和时区,不是吗?

标签: c++ linux time byte


【解决方案1】:

通过一些逆向工程,可以查看来自 Linux 时钟的数据在做什么。

如果您读取数据行,您可以看到最后 7 个字节是一个递增计数器,最低有效字节位于第一个位置。如果您进行数学运算,3 个计数器的总数如下:

573929538
573992866
574266016

查看第一个数字与第二个和第三个数字的差异,您会得到以下信息:

63328
336478

...这是样本之间经过的时间,以秒为单位。

由于某种原因,原始值不是自 Unix 纪元以来的秒数,而是自 1999 年 9 月上旬一天以来的秒数。

无论如何,以下源代码显示了如何将数据转换为本地时间的基础知识。

#include <time.h>

int main(int argc, char* argv[])
{
    const unsigned long localEpoch = 936316800;   // local epoch Sept 1999

    std::vector<std::vector<int>> timeData =
    {
        { 66,  120, 53, 34, 0, 0, 0 },
        { 162, 111, 54, 34, 0, 0, 0 },
        { 160, 154, 58, 34, 0, 0, 0 }
    };

    for (auto& data : timeData)
    {
        // convert to total seconds
        unsigned long total = 0;
        for (std::vector<int>::iterator it = data.begin(); it != data.end(); ++it)
        {
            total += (*it) << (std::distance(data.begin(), it) * 8);  
        }
        std::cout << "Seconds: " << total << std::endl;

        // add to local epoch and display
        time_t raw = total + localEpoch;
        struct tm timeinfo;
        localtime_s(&timeinfo, &raw);

        char fmt[100] = { 0 };
        asctime_s(fmt, 100, &timeinfo);
        std::cout << fmt << std::endl;
    }

    return 0;
}

它给出以下输出:

Seconds: 573929538
Thu Nov  9 16:52:18 2017

Seconds: 573992866
Fri Nov 10 10:27:46 2017

Seconds: 574266016
Mon Nov 13 14:20:16 2017

希望这会有所帮助。 (注意,我是在 VS 中完成的,所以时间格式化函数属于 Windows 类型,但你明白了。)

(编辑):按要求确定,这是一些等效的 C# 代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    class Program
    {
        public static void Main(string[] args)
        {
            int[,] timeData = new int[,]
            {
                {  66, 120, 53, 34, 0, 0, 0 },
                { 162, 111, 54, 34, 0, 0, 0 },
                { 160, 154, 58, 34, 0, 0, 0 }
            };

            for (int line = 0; line < timeData.GetLength(0); ++line)
            {
                ulong total = 0;
                for (int i = 0; i < timeData.GetLength(1); ++i)
                {
                    total += (ulong)timeData[line,i] << (8 * i);
                }
                System.Console.WriteLine("Seconds: " + total.ToString());
                DateTime result = FromUnixTime(total + localEpoch);
                System.Console.WriteLine(result.ToString());
            }

            System.Console.ReadKey();
        }

        public static DateTime FromUnixTime(ulong unixTime)
        {
            return epoch.AddSeconds(unixTime);
        }

        private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

        private static readonly ulong localEpoch = 936316800;   // local epoch Sept 1999
    }
}

(感谢this question Epoch 转换。)

【讨论】:

  • @JosephGoldberger 当然。我用 c++ 回答,因为那是问题的标签。算法简单;将最后 7 个字节转换为单个大数,以秒为单位添加本地纪元,结果是自 Unix 纪元以来的秒数。你想让我发布 c# 等效代码吗?
  • 我尝试转换自己,但我无法想出转换为大数的算法,如果你能发布 C#,那就太好了,在此致谢
  • @JosephGoldberger 好的,我已经发布了示例代码。希望它对你有用。
【解决方案2】:

哇!!!,这对我帮助很大,这是我使用的代码,谢谢@ASMackay

private DateTime convertTime(byte[] bytes)
        {
              ulong localEpoch = 936316800;   // local epoch Sept 1999
            DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            ulong total = 0;
            for (int i = 0; i < bytes.Count(); ++i)
            {
                total += (ulong)bytes[i] << (8 * i);
            }
            return epoch.AddSeconds(total + localEpoch);
        }

【讨论】:

    猜你喜欢
    • 2016-12-11
    • 2013-10-24
    • 2014-08-08
    • 1970-01-01
    • 2019-11-24
    • 1970-01-01
    • 2012-03-18
    • 2013-03-22
    • 2015-03-22
    相关资源
    最近更新 更多