1

I have a linux time clock, that sending me the clock with bytes, I have no idea how to get the clock out of it, I do know that it's a type of "time_t" (which is probably the total seconds since 1/1/1970), See below a few examples what I'm receiving from the clock (I'm not sure if it's sending local or GMT time)

This bytes represents 11/09/2017 16:52(Local time) or 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

This bytes represents 11/10/2017 10:27(Local time) or 11/10/2017 15:27(GMT)

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

This bytes represents 11/13/2017 14:20(Local time) or 11/13/2017 19:20(GMT)

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
Joseph Goldberger
  • 313
  • 1
  • 3
  • 10

2 Answers2

1

With a little reverse engineering, it's possible to see what the data from your Linux clock is doing.

If you read your lines of data, you can see that the final 7 bytes are an incrementing counter, with the least significant byte in the first position. If you do the maths, the 3 counters give the following totals:

573929538
573992866
574266016

Looking at the differences from the first number to the second and third, you get the following:

63328
336478

... which are the elapsed times between your samples, in seconds.

For some reason, the raw values aren't the time in seconds since the Unix Epoch, but the time in seconds since a day early in September 1999.

Anyway, the following source code shows the basics of how you can convert your data into the local time.

#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;
}

And it gives the following outputs:

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

Hope this is of some help. (NB I did this in VS, so the time formatting functions are of the Windows variety, but you get the idea.)

(Edit): OK as requested, here's some equivalent C# code:

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
    }
}

(Thanks to this question for the Epoch conversion.)

AS Mackay
  • 2,831
  • 9
  • 19
  • 25
  • @JosephGoldberger For sure. I answered with c++ as that was the tag on the question. The algorithm is simple; convert the last 7 bytes to a single large number, add the local epoch in seconds, and the result is the number of seconds since the Unix epoch. Do you want me to post the c# equivalent code? – AS Mackay Nov 15 '17 at 15:46
  • I tried to convert myself, but i'm not able to come up with the algorithm to convert to the large number, It will be great if you can post C#, Thanks in advanced – Joseph Goldberger Nov 15 '17 at 15:50
  • @JosephGoldberger OK I've posted sample code. Hope it works for you. – AS Mackay Nov 15 '17 at 16:38
0

WOW!!!, that helped me a lot, Here is the code what I used, Thanks @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);
        }
Joseph Goldberger
  • 313
  • 1
  • 3
  • 10