编号到日期时间

Dse*_*Dse 0 c encoding

我有32位编码的日期和时间值.我知道样本32位编码值的日期和时间,但我不知道如何使用c程序或任何其他语言或脚本转换和获取此值.样本数据如下

54 FE C0 72 =(25-Oct-13 20:34:58)
55 01 DC 8B =(26-Oct-13 22:34:51)
57 01 DC 8B =(14-Apr-14 14:34:51)
42 23 8F 96 =(02-Jun-09 17:06:30)
3C F5 28 4B= (31-Mar-00 18:51:55)
3A F4 28 49 =(12-Oct-99 18:51:53)
Run Code Online (Sandbox Code Playgroud)

对于上面的示例数据我尝试使用unix时间戳方法,但我得到错误的日期时间值.使用unix时间戳方法的答案如下

54 FE C0 72 =(10 Mar 2015 09:59:14 GMT
55 01 DC 8B =(12 Mar 2015 18:35:55 GMT)
57 01 DC 8B =(04 Apr 2016 03:16:27 GMT)
Run Code Online (Sandbox Code Playgroud)

请告诉我您将上述32位编码值转换为正确的日期和时间值的指导.请分享除unix timestamp以外的任何其他方法.我认为一些算法在十六进制代码中加密

编辑:

聊天中添加示例:

30067004 =24-mar-1997 07:57:56
2C067004=Tue Apr 16 23:57:56 1996
29567004=Thu Aug 31 15:57:56 1995
13567004=9-jul-90 7:57:56
17567004=15-jun-91 15:57:56
1C567004=15-aug-92 07:57:56
20567004=23-jul-93 15:57:56
24867004=15-jul-94 23:57:56
10067004=29 sep-89 15:57:56
2B067004=21-jan-96 15:57:56

00000000 = 1-Jan-1986
00030000 = 1-jan-1986
00038000 = 1-jan-1994
Run Code Online (Sandbox Code Playgroud)

dbu*_*ush 10

让我们先看看前两个:

54 FE C0 72 =(25-oct-13 20:34:58)
54 FE C0 78 =(25-oct-13 20:35:04)
Run Code Online (Sandbox Code Playgroud)

这两个日期相隔6秒,值相差6.所以我们知道至少最后一个字节指定秒.

55 01 DC 8B =(26-oct-13 22:34:51)
55 01 E3 93 =(26-oct-13 23:04:51)
Run Code Online (Sandbox Code Playgroud)

类似地,这两个相距30分钟(1800秒),值相差1800.所以至少最后两个字节指定秒.

54 FE C0 78 =(25-oct-13 20:35:04)
55 01 DC 8B =(26-oct-13 22:34:51)
Run Code Online (Sandbox Code Playgroud)

值中的范围较大,但请注意,最后两个字节的值似乎相当接近.取DC8Bh - C078h给出1C13h = 7187d.这是2小时(7200秒)减去13秒的差异,这是两个日期的时间部分相隔多远.所以看起来最后两个字节指定时间.但是,一天有86400秒,而C078h = 49272d,它将比20:35:04更接近13:00:00左右,并且您可以存储在16位的最大值是65535.此外,第一个两个字节相差3,但日期相差1.让我们回过头来看一下.

55 01 DC 8B =(26-oct-13 22:34:51)
57 01 DC 8B =(14-Apr-14 14:34:51)
Run Code Online (Sandbox Code Playgroud)

请注意,最后两个字节是相同的,并且分钟和秒是相同的,尽管小时数相差8.因此,最后两个字节可能指定一天中部分时间的秒数.回到前面的例子,当日期相差1时,前两个字节相差3.因此,前两个字节可能指定一个8小时的间隔.当时间相差8或16小时时,这将考虑最后两个字节是相同的.如果我们取5701h - 5501h,我们得到200h = 512d.除以3我们得到169 2/3天.上面的两个日期相差170天,如果你把时间考虑在内,它大概是169 2/3.

所以现在我们有约会.5501h是26-oct-13中的第三个8小时间隔,因此当天的开始是54FFh = 21759d.除以3给出了我们7253.计算回来的日子,这给了我们一个1993-12-17的纪元日期.

现在让我们回到时间.假设最后两个字节是8小时间隔内的秒数.这给了我们最大值28800d.请注意,此值仅需要15位才能存储.DC8Bh具有最高位设置,所以让我们看看如果我们屏蔽该位,我们得到了什么.这给了我们5C8Bh = 23691d,而23691秒是6小时34分51秒.这与第三和第五个例子相匹配,相差8小时.

至于第三个字节中最重要的位,我猜是指定DST.所有示例都设置了此位,所有日期都是DST处于活动状态时.

总结一下:

  • 前两个字节除以3是自1993-12-17以来的天数.
  • 前两个字节mod 3是当天的8小时间隔.将此值乘以28800(即8小时内的秒数),以秒为单位设置初始时间.
  • 最高有效位掩码的最后两个字节是从8小时间隔开始的秒数.将此值添加到上一步的值以从午夜获取秒数.
  • 检查第三个字节中的最高有效位以设置DST标志.

编辑:

所以看起来这个算法给出的结果57 01 DC 8B =(14-Apr-14 14:34:51)是提前一天.让我们看看其中一个新例子:

42 23 8F 96 =(02-Jun-09 17:06:30)
Run Code Online (Sandbox Code Playgroud)

我们的算法给出了09年5月30日的日期,所以它落后了3天.这很有意思,因为它与我们在25-Oct-13和26-Oct-13中获得的大约相差4年.不同的是,介于两者之间.所以也许这种编码假设所有年份都有366天.如果我们回到1993-12-17的纪元日期,我们看到从1994年到2013年有15个非闰年.这给了我们一个新的1994-1-1的纪元日期,这更有意义.因此,在以1994-1-1作为时代进行初始转换之后,我们需要计算非闰年的数量并减去那么多天.

现在让我们来看看这个:

3A F4 28 49 =(12-Oct-99 18:51:53)
Run Code Online (Sandbox Code Playgroud)

时间仍然正确,但日期已经过时了.但请注意,字节3的最高位未设置.这似乎表明了一个不同的时代.99年10月12日的开始是3AF2h = 15090d.除以3得到5030.向后计数给我们一个1986-01-03的时代.但接下来是这样的:

00000000 = 1-Jan-1986
00030000 = 1-jan-1986
Run Code Online (Sandbox Code Playgroud)

因此看起来1986-1-1是时代,但是这个日期有一个特殊的情况,所以实际的时代是1985-12-31.

但是,我们休息了3天.如果所有年份都有366天,则情况并非如此.然而,如果所有年份都有365天,它会工作.这意味着,对于1985-12-31时代,我们需要计算闰年的数量并添加这么多天.这与我们对1994-1-1时代的需要相反.

几乎适用于所有事情.除了这些之外的一切:

3C F5 28 4B= (31-Mar-00 18:51:55)
1C567004=15-aug-92 07:57:56
Run Code Online (Sandbox Code Playgroud)

但它确实有效:

2B067004=21-jan-96 15:57:56
Run Code Online (Sandbox Code Playgroud)

所以看起来这个编码确实进行了闰年检查,但仅适用于当年.

将这些更改应用于算法并将其应用于LP提供的代码,我们现在有:

#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <time.h>

int isleap(int year)
{
    if (year % 4 != 0) return 0;
    if (year % 100 != 0) return 1;
    if (year % 400 != 0) return 0;
    return 1;
}

int main(int argc, char *argv[])
{
    // Read encoding from command line
    uint32_t datetime = strtoul(argv[1],NULL,16);

    uint16_t mydate = datetime >> 16;
    uint16_t mytime = datetime & 0xFFFF;

    int new_encoding = (mytime & 0x8000) != 0;

    // Calculate days
    time_t linuxSeconds = (mydate/3);
    // Calculate the 8 hours on current day of date
    uint8_t third_Count = mydate % 3;

    // Add days from 1/1/1970, that is the base of time in linux
    if (new_encoding)
    {
        // Days between 1970-1-1 and 1994-1-1 minus 1
        linuxSeconds += 8765;
    }
    else
    {
        // Days between 1970-1-1 and 1986-1-1 minus 1
        linuxSeconds += 5843;
    }

    // Calculate total amount of hours
    linuxSeconds *= 24;

    // Calculate total amount of seconds
    linuxSeconds *= 3600;

    // Add seconds of last 8 hours group
    linuxSeconds += (mytime & 0x7FFF);

    // Add alla seconds of grups of 8 hours of date
    linuxSeconds += (third_Count * 28800);

    // Add or subtract days depending on whether new_encoding is set
    struct tm *mytm = gmtime(&linuxSeconds);
    int daydiff = 0, year;
    for (year = new_encoding ? 1994 : 1986; year <= mytm->tm_year + 1900; year++) {
        if (year < mytm->tm_year + 1900) {
            if (new_encoding) {
                // remove a day for non-leap years
                if (!isleap(year)) {
                    daydiff--;
                }
            } else {
                // add a day for leap years unless it's the current year
                if (year != (mytm->tm_year + 1900) && isleap(year)) {
                    daydiff++;
                }
            }
        }
    }

    if (mydate < 0x0003) {
        // special case for day 0
        linuxSeconds += 86400;
    } else {
        linuxSeconds += daydiff * 86400;
    }

    // Print the date with actual GMT
    printf(ctime(&linuxSeconds));

    // Print Greenwich time
    printf(asctime(gmtime(&linuxSeconds)));

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

关于此代码的一个警告:如果它在time_t32位系统上运行,它将无法在2038年之后正确显示日期.如果time_t是64位,则这些日期将正确显示.

编辑2:

代码30068000存在问题,提前一天.检查当前月份时代码中存在错误.该tm_mon字段的struct tm范围为0到11,而不是1到12.固定.

编辑3:

因此,添加/减去天数时的月/日检查似乎完全错误,因为它导致2月28日出现两次.当我删除它时,我发现1994年的计划是提前一天,所以看起来它与1986年计划的第0天具有相同的特殊情况.再次修复.