【问题标题】:C/C++: how to get integer unix timestamp of build time (not string)C/C++:如何获取构建时间的整数 unix 时间戳(不是字符串)
【发布时间】:2014-04-12 14:59:13
【问题描述】:

我正在尝试实现非常微不足道的事情:我需要存储构建时间的整数 32 位 unix 时间戳,但是我找到的所有宏(__DATE____TIME____TIMESTAMP__)展开为字符串,而不是整数。

看来,我们只是没有它(这对我来说很奇怪)。我真的想要整数,而不是字符串。

获得它的最佳做法是什么?

UPD:

附带说明:我做嵌入式的东西,所以我没有足够的资源(比如,128 KB 的闪存),因此解析字符串真的很糟糕。

我为什么需要它:我只需要每个 beta 版本的唯一版本号。首先,十六进制文件将被命名为my-firmware-v2-33-BETA-1397315745.hex,其次,当我需要在设备屏幕上显示当前版本时,我可能想以各种格式回显它。

【问题讨论】:

  • 能否请您提及一个用例?通常,软件构建时间戳存储在系统文件中,我还没有遇到过在正在构建的软件中知道这一点的用例。您想在 about 中显示它或启用/禁用某些功能而不读取外部文件?
  • 我已经更新了问题。
  • 为什么需要将字符串解析为整数?显示版本不需要,也不需要将时间戳放入文件名(字符串)?我错过了什么吗?
  • 整数更方便。我想要一个数字(与另一个数字相当),并且我希望能够以我想要的 any 格式生成字符串,而不仅仅是编译器生成的字符串。我不想在文件名中有特殊符号(空格、冒号),而且1397315745Feb 12 2014 19:28:01 短得多。
  • 您使用什么构建工具?您可以在 Windows 上使用 Cygwin 吗?

标签: c++ c build-time


【解决方案1】:

所以,今天晚上我玩得很开心,并创建了一个带有宏的头文件来生成 UNIX 时间戳,没有任何外部程序或特殊编译器功能! 只需包含标题并使用__TIME_UNIX__ 宏。

其实代码很简单:

  1. 字符串中的数字字符被转换为带有str[i]-'0' 的数字,正如 loreb 建议的那样,并根据它们的位置进行权衡。
  2. 月份字符串的处理类似于 chux 答案;这些字符被单独检查并使用? : 运算符作为一个组进行评估。
  3. 使用可交换的? : 表达式计算过去几个月的天数。
  4. 闰年计算很简单,因为在 UNIX 时间范围内,每 4 年插入一个闰日
  5. 最后,所有单独的值都用各自的秒数进行加权,以获得 UNIX 时间。请注意,SEC_PER_DAY 必须减去一次,因为JAN 01 1970, 00:00:00 必须是0

代码已在 ATMEL Studio 7 (Visual Studio 2015) 中使用默认编译器和设置(avr-gcc、-O1 优化)进行了测试,并通过检查生成的 .lss 文件确认了结果。

将以下代码复制并粘贴到头文件中,并将其包含在您需要的任何位置。享受吧!

/*
 * compile_time.h
 *
 * Created: 30.05.2017 20:57:58
 *  Author: Dennis (instructable.com/member/nqtronix)
 *
 * This code provides the macro __TIME_UNIX__ which returns the current time in UNIX format. It can
 * be used to identify a version of code on an embedded device, to initialize its RTC and much more.
 * Along that several more constants for seconds, minutes, etc. are provided
 *
 * The macro is based on __TIME__ and __DATE__, which are assumed to be formatted "HH:MM:SS" and
 * "MMM DD YYYY", respectively. The actual value can be calculated by the C compiler at compile time
 * as all inputs are literals. MAKE SURE TO ENABLE OPTIMISATION!
 */ 


#ifndef COMPILE_TIME_H_
#define COMPILE_TIME_H_

// extracts 1..4 characters from a string and interprets it as a decimal value
#define CONV_STR2DEC_1(str, i)  (str[i]>'0'?str[i]-'0':0)
#define CONV_STR2DEC_2(str, i)  (CONV_STR2DEC_1(str, i)*10 + str[i+1]-'0')
#define CONV_STR2DEC_3(str, i)  (CONV_STR2DEC_2(str, i)*10 + str[i+2]-'0')
#define CONV_STR2DEC_4(str, i)  (CONV_STR2DEC_3(str, i)*10 + str[i+3]-'0')

// Some definitions for calculation
#define SEC_PER_MIN             60UL
#define SEC_PER_HOUR            3600UL
#define SEC_PER_DAY             86400UL
#define SEC_PER_YEAR            (SEC_PER_DAY*365)
#define UNIX_START_YEAR         1970UL

// Custom "glue logic" to convert the month name to a usable number
#define GET_MONTH(str, i)      (str[i]=='J' && str[i+1]=='a' && str[i+2]=='n' ? 1 :     \
                                str[i]=='F' && str[i+1]=='e' && str[i+2]=='b' ? 2 :     \
                                str[i]=='M' && str[i+1]=='a' && str[i+2]=='r' ? 3 :     \
                                str[i]=='A' && str[i+1]=='p' && str[i+2]=='r' ? 4 :     \
                                str[i]=='M' && str[i+1]=='a' && str[i+2]=='y' ? 5 :     \
                                str[i]=='J' && str[i+1]=='u' && str[i+2]=='n' ? 6 :     \
                                str[i]=='J' && str[i+1]=='u' && str[i+2]=='l' ? 7 :     \
                                str[i]=='A' && str[i+1]=='u' && str[i+2]=='g' ? 8 :     \
                                str[i]=='S' && str[i+1]=='e' && str[i+2]=='p' ? 9 :     \
                                str[i]=='O' && str[i+1]=='c' && str[i+2]=='t' ? 10 :    \
                                str[i]=='N' && str[i+1]=='o' && str[i+2]=='v' ? 11 :    \
                                str[i]=='D' && str[i+1]=='e' && str[i+2]=='c' ? 12 : 0)

#define GET_MONTH2DAYS(month)  ((month == 1 ? 0 : 31 +                      \
                                (month == 2 ? 0 : 28 +                      \
                                (month == 3 ? 0 : 31 +                      \
                                (month == 4 ? 0 : 30 +                      \
                                (month == 5 ? 0 : 31 +                      \
                                (month == 6 ? 0 : 30 +                      \
                                (month == 7 ? 0 : 31 +                      \
                                (month == 8 ? 0 : 31 +                      \
                                (month == 9 ? 0 : 30 +                      \
                                (month == 10 ? 0 : 31 +                     \
                                (month == 11 ? 0 : 30))))))))))))           \


#define GET_LEAP_DAYS           ((__TIME_YEARS__-1968)/4 - (__TIME_MONTH__ <=2 ? 1 : 0))



#define __TIME_SECONDS__        CONV_STR2DEC_2(__TIME__, 6)
#define __TIME_MINUTES__        CONV_STR2DEC_2(__TIME__, 3)
#define __TIME_HOURS__          CONV_STR2DEC_2(__TIME__, 0)
#define __TIME_DAYS__           CONV_STR2DEC_2(__DATE__, 4)
#define __TIME_MONTH__          GET_MONTH(__DATE__, 0)
#define __TIME_YEARS__          CONV_STR2DEC_4(__DATE__, 7)

#define __TIME_UNIX__         ((__TIME_YEARS__-UNIX_START_YEAR)*SEC_PER_YEAR+       \
                                GET_LEAP_DAYS*SEC_PER_DAY+                          \
                                GET_MONTH2DAYS(__TIME_MONTH__)*SEC_PER_DAY+         \
                                __TIME_DAYS__*SEC_PER_DAY-SEC_PER_DAY+              \
                                __TIME_HOURS__*SEC_PER_HOUR+                        \
                                __TIME_MINUTES__*SEC_PER_MIN+                       \
                                __TIME_SECONDS__)

#endif /* COMPILE_TIME_H_ */

编辑:

初始版本不考虑 100 和 400 模年对 2 月天数的影响。这应该不是2001到2101之间的问题,但是这里有一个更通用的宏:

/* 
 *
 * Created: 29.03.2018
 *
 * Authors:
 * 
 * Assembled from the code released on Stackoverflow by:
 *   Dennis (instructable.com/member/nqtronix)    |   https://stackoverflow.com/questions/23032002/c-c-how-to-get-integer-unix-timestamp-of-build-time-not-string
 * and
 *   Alexis Wilke                                 |   https://stackoverflow.com/questions/10538444/do-you-know-of-a-c-macro-to-compute-unix-time-and-date
 *
 * Assembled by Jean Rabault
 * 
 * UNIX_TIMESTAMP gives the UNIX timestamp (unsigned long integer of seconds since 1st Jan 1970) of compilation from macros using the compiler defined __TIME__ macro.
 * This should include Gregorian calendar leap days, in particular the 29ths of February, 100 and 400 years modulo leaps.
 * 
 * Careful: __TIME__ is the local time of the computer, NOT the UTC time in general!
 * 
 */

#ifndef COMPILE_TIME_H_
#define COMPILE_TIME_H_

// Some definitions for calculation
#define SEC_PER_MIN             60UL
#define SEC_PER_HOUR            3600UL
#define SEC_PER_DAY             86400UL
#define SEC_PER_YEAR            (SEC_PER_DAY*365)

// extracts 1..4 characters from a string and interprets it as a decimal value
#define CONV_STR2DEC_1(str, i)  (str[i]>'0'?str[i]-'0':0)
#define CONV_STR2DEC_2(str, i)  (CONV_STR2DEC_1(str, i)*10 + str[i+1]-'0')
#define CONV_STR2DEC_3(str, i)  (CONV_STR2DEC_2(str, i)*10 + str[i+2]-'0')
#define CONV_STR2DEC_4(str, i)  (CONV_STR2DEC_3(str, i)*10 + str[i+3]-'0')

// Custom "glue logic" to convert the month name to a usable number
#define GET_MONTH(str, i)      (str[i]=='J' && str[i+1]=='a' && str[i+2]=='n' ? 1 :     \
                                str[i]=='F' && str[i+1]=='e' && str[i+2]=='b' ? 2 :     \
                                str[i]=='M' && str[i+1]=='a' && str[i+2]=='r' ? 3 :     \
                                str[i]=='A' && str[i+1]=='p' && str[i+2]=='r' ? 4 :     \
                                str[i]=='M' && str[i+1]=='a' && str[i+2]=='y' ? 5 :     \
                                str[i]=='J' && str[i+1]=='u' && str[i+2]=='n' ? 6 :     \
                                str[i]=='J' && str[i+1]=='u' && str[i+2]=='l' ? 7 :     \
                                str[i]=='A' && str[i+1]=='u' && str[i+2]=='g' ? 8 :     \
                                str[i]=='S' && str[i+1]=='e' && str[i+2]=='p' ? 9 :     \
                                str[i]=='O' && str[i+1]=='c' && str[i+2]=='t' ? 10 :    \
                                str[i]=='N' && str[i+1]=='o' && str[i+2]=='v' ? 11 :    \
                                str[i]=='D' && str[i+1]=='e' && str[i+2]=='c' ? 12 : 0)

// extract the information from the time string given by __TIME__ and __DATE__
#define __TIME_SECONDS__        CONV_STR2DEC_2(__TIME__, 6)
#define __TIME_MINUTES__        CONV_STR2DEC_2(__TIME__, 3)
#define __TIME_HOURS__          CONV_STR2DEC_2(__TIME__, 0)
#define __TIME_DAYS__           CONV_STR2DEC_2(__DATE__, 4)
#define __TIME_MONTH__          GET_MONTH(__DATE__, 0)
#define __TIME_YEARS__          CONV_STR2DEC_4(__DATE__, 7)

// Days in February
#define _UNIX_TIMESTAMP_FDAY(year) \
    (((year) % 400) == 0UL ? 29UL : \
        (((year) % 100) == 0UL ? 28UL : \
            (((year) % 4) == 0UL ? 29UL : \
                28UL)))

// Days in the year
#define _UNIX_TIMESTAMP_YDAY(year, month, day) \
    ( \
        /* January */    day \
        /* February */ + (month >=  2 ? 31UL : 0UL) \
        /* March */    + (month >=  3 ? _UNIX_TIMESTAMP_FDAY(year) : 0UL) \
        /* April */    + (month >=  4 ? 31UL : 0UL) \
        /* May */      + (month >=  5 ? 30UL : 0UL) \
        /* June */     + (month >=  6 ? 31UL : 0UL) \
        /* July */     + (month >=  7 ? 30UL : 0UL) \
        /* August */   + (month >=  8 ? 31UL : 0UL) \
        /* September */+ (month >=  9 ? 31UL : 0UL) \
        /* October */  + (month >= 10 ? 30UL : 0UL) \
        /* November */ + (month >= 11 ? 31UL : 0UL) \
        /* December */ + (month >= 12 ? 30UL : 0UL) \
    )

// get the UNIX timestamp from a digits representation
#define _UNIX_TIMESTAMP(year, month, day, hour, minute, second) \
    ( /* time */ second \
                + minute * SEC_PER_MIN \
                + hour * SEC_PER_HOUR \
    + /* year day (month + day) */ (_UNIX_TIMESTAMP_YDAY(year, month, day) - 1) * SEC_PER_DAY \
    + /* year */ (year - 1970UL) * SEC_PER_YEAR \
                + ((year - 1969UL) / 4UL) * SEC_PER_DAY \
                - ((year - 1901UL) / 100UL) * SEC_PER_DAY \
                + ((year - 1601UL) / 400UL) * SEC_PER_DAY \
    )

// the UNIX timestamp
#define UNIX_TIMESTAMP (_UNIX_TIMESTAMP(__TIME_YEARS__, __TIME_MONTH__, __TIME_DAYS__, __TIME_HOURS__, __TIME_MINUTES__, __TIME_SECONDS__))

#endif

【讨论】:

  • 您的标头几乎可以正常工作,但是当我们尝试将其与单个数字天一起使用时,__TIME_DAYS__ 给出了一个负数,因为__DATE__ 在我们的编译器上给出了一个空格而不是零(" 2017 年 6 月 5 日”)。我们用这个#define CONV_STR2DEC_1(str, i) (str[i]&gt;'0'?str[i]-'0':0) 修复了它。
  • @A.布洛杰特 你完全正确!我已经测试过了,我的电脑也省略了零。感谢修复,我修改了答案:)
  • 您确定此解决方案有效吗?我现在刚刚对其进行了测试,发现date +%s 和您的__TIME_UNIX__ 之间存在差异。我认为您的“GET_LEAP_DAYS”公式可能是错误的,请参见此处的第一个答案stackoverflow.com/questions/10538444/…
  • 对不起,我似乎得到了一个差异,因为 TIME 给出了本地时间,而我在宏和 date +%s 命令中与 UTC 时间进行比较,我的错。
  • 是的,我同意你的看法。 2001 年之后和 2101 年之前的日期应该没问题。但也许有些人会尝试将您的宏用于比您更通用的应用程序。例如,在距离 1999 年的参考点的给定时间距离内触发事件?我认为你应该用一个大的粗体警告来说明你的脚本的有效性域,或者更新你的代码。我有你的代码的更新版本,如果我发布它,告诉我你是否可以(当然是你的帖子)。
【解决方案2】:

您可以在每次构建时生成一个timestamp.h 文件作为预构建步骤,并将该文件包含在您的源代码中。我不知道您使用的是什么构建工具(嵌入式世界非常广泛),到目前为止我看到的每个构建工具都允许用户定义自定义的构建前和构建后步骤(飞思卡尔 CodeWarrior、AVR 工作室、MSVS. ..)。

例如,在 Windows 上的 AVR Studio 中,我使用了这个预构建步骤(请注意,$(SolutionDir) 特定于 AVR stuio,它基于 MSVS,您可以用您需要的任何文件系统路径替换):

FOR /F %%A IN ('C:\cygwin\bin\date +%s') DO SET BUILD_TIMESTAMP=%%A
echo #define BUILD_TIME %BUILD_TIMESTAMP% > "$(SolutionDir)timestamp.h"

在项目的其中一个 C 文件中,我通常会包含这个生成的文件(您到该文件的路径可能不同...):

#include "../timestamp.h"

生成的文件如下所示:

#define BUILD_TIME 1397317498

所以当我点击“构建项目”时,工作室首先运行我的命令,生成新的timestamp.h,然后将其用作任何其他 C 文件中的包含。

请注意,上面的示例使用 Cygwin (C:\cygwin\bin\date +%s) 来获取时间戳。如果您不想使用 Cygwin,您将不得不为 Windows 找到其他方式为您生成时间戳。您可以编写自己的命令行实用程序(它应该是大约 10 行 C 代码:-)或在 Internet 上搜索其他方式。

【讨论】:

    【解决方案3】:

    为什么不在命令行中定义呢?

    gcc -DCOMPILE_TIME=`date '+%s'` mysources.c
    

    【讨论】:

    • 因为它只适用于类 unix 系统。我也需要让它在 Windows 上运行。
    • @LaszloPapp,为什么?如果我有整数 unix 时间戳(实际上由 date '+%s' 返回),我可以生成任何我想要的版本字符串。或者,你是什么意思?
    • 这个答案比最初问的宏好多少?
    • @LaszloPapp,宏是跨平台的,date '+%s' 不是。对我来说,可悲的是,目前宏是唯一的方法。
    • @DmitryFrank:如果您重新阅读我的帖子,这正是我所说的。 ;-)
    【解决方案4】:
    /**
     * @brief  Macros to get integer build timestamp:
     *         __DATE_TIME_Y2K__  seconds since 2000-01-01,00:00:00
     *         __DATE_TIME_UNIX__ seconds since 1970-01-01 00:00:00
     *
     *           01234567890              01234567
     * __DATE__ "Jul 27 2019"   __TIME__ "12:34:56"
     */
    #ifndef __DATE_TIME_H__
    #define __DATE_TIME_H__
    
    // For testing
    //#define __DATE__ ("Jan 01 2000")
    //#define __TIME__ ("00:00:00")
    
    #define Y2K_UNIX_EPOCH_DIFF 946684800U
    #define YEARS ((__DATE__[10] - '0' + (__DATE__[9] - '0') * 10))
    #define DAY_OF_MONTH ((__DATE__[5] - '0') \
                      + (((__DATE__[4] > '0')? __DATE__[4] - '0': 0) * 10) - 1)
    #define DAY_OF_YEAR ((DAY_OF_MONTH) + \
    ( /* Jan */ (__DATE__[0] == 'J' && __DATE__[1] == 'a')?   0: \
      /* Feb */ (__DATE__[0] == 'F'                      )?  31: \
      /* Mar */ (__DATE__[0] == 'M' && __DATE__[2] == 'r')?  59: \
      /* Apr */ (__DATE__[0] == 'A' && __DATE__[1] == 'p')?  90: \
      /* May */ (__DATE__[0] == 'M'                      )? 120: \
      /* Jun */ (__DATE__[0] == 'J' && __DATE__[2] == 'n')? 151: \
      /* Jul */ (__DATE__[0] == 'J'                      )? 181: \
      /* Aug */ (__DATE__[0] == 'A'                      )? 212: \
      /* Sep */ (__DATE__[0] == 'S'                      )? 243: \
      /* Oct */ (__DATE__[0] == 'O'                      )? 273: \
      /* Nov */ (__DATE__[0] == 'N'                      )? 304: \
      /* Dec */                                             334  ))
    #define LEAP_DAYS (YEARS / 4 + ((YEARS % 4 == 0 && DAY_OF_YEAR > 58)? 1 : 0) )      
    #define __DATE_TIME_Y2K__ ( (YEARS * 365 + LEAP_DAYS + DAY_OF_YEAR ) * 86400 \
                        + ((__TIME__[0] - '0') * 10 + __TIME__[1] - '0') * 3600 \
                        + ((__TIME__[3] - '0') * 10 + __TIME__[4] - '0') * 60 \
                        + ((__TIME__[6] - '0') * 10 + __TIME__[7] - '0') )
    #define  __DATE_TIME_UNIX__ ( __DATE_TIME_Y2K__ + Y2K_UNIX_EPOCH_DIFF )
    #endif /* __DATE_TIME_H__ */
    

    这只是从@nqtronix 的上述版本开发的更紧凑、更轻的版本。享受吧!

    注意:此宏忽略世纪,因此仅在 2000-01-01,00:00:00 和 2099-12-31,23:59:59 之间有效。

    【讨论】:

      【解决方案5】:

      看看下面的暴行:

      #include <stdio.h>
      #define dec(ch) ((ch)-'0')
      #define t(index, multiplier)    (dec(__TIME__[index]) * (multiplier))
      /* only minutes and seconds - you get the idea */
      #define mmss()  (t(3,600) + t(4,60) + t(6,10) + t(7,1))
      int main()
      {
              /*
              int i;
              printf("time = %s\n", __TIME__);
              for(i=0; __TIME__[i]; i++)
                      printf("t(%d) = %d\n", i, t(i,1));
              */
              printf("mmss = %d\n", mmss());
              return 0;
      }
      

      在我的计算机上 gcc -O 能够将其优化为一个恒定值;要获得完整的 time_t,您将需要 __DATE__ 的表亲宏并查看生成的程序集。

      如果有人问,我没有写这个答案;)

      编辑:为了清楚起见,您可能应该遵循 Roman Hocke 的回答并编写一个简短的 C 程序来为您生成值(当然,如果您正在交叉编译,您应该小心一点......)

      【讨论】:

        【解决方案6】:

        编辑: 根据@Lưu Vĩnh Phúc 的评论,似乎需要解释关键思想:所有计算是在编译时间完成的。请参阅下面生成的 OP 代码。


        下面不是生成time_t,而是在编译器的时区生成struct tm。如果需要,对mktime() 的调用将返回time_t

        time_t CompileTime = mktime(CompileTimeTM());
        printf("%lld\n", (long long) CompileTime);
        

        在其他应用程序中,每个字段分配都简单地打印值以显示版本,而不是返回 struct tm

        else if ((d[3]=='M') && (d[4]=='a') && (d[5]=='y')) Print2Dig(5);
        

        以下冗长的代码在 PIC 编译器中生成的指令很少,因为它优化了很多。类似的方法可以使用__TIMESTAMP__

        // Dummy: used to detect a bad date parsing in Send_ID()
        extern void BadDateM(void);
        
        struct tm *CompileTimeTM(void) {
          static const char d[10] = __DATE__;
          static const char t[10] = __TIME__;
          static struct tm ct;
        
          ct.tm_year = (d[7]-'0')*10 + (d[8]-'0') + 2000 - 1900;
        
          #IGNORE_WARNINGS  204
          if (0) ;
          else if ((d[3]=='J') && (d[4]=='a') && (d[5]=='n')) ct.tm_mon = 1-1;
          else if ((d[3]=='F') && (d[4]=='e') && (d[5]=='b')) ct.tm_mon = 2-1;
          else if ((d[3]=='M') && (d[4]=='a') && (d[5]=='r')) ct.tm_mon = 3-1;
          else if ((d[3]=='A') && (d[4]=='p') && (d[5]=='r')) ct.tm_mon = 4-1;
          else if ((d[3]=='M') && (d[4]=='a') && (d[5]=='y')) ct.tm_mon = 5-1;
          else if ((d[3]=='J') && (d[4]=='u') && (d[5]=='n')) ct.tm_mon = 6-1;
          else if ((d[3]=='J') && (d[4]=='u') && (d[5]=='l')) ct.tm_mon = 7-1;
          else if ((d[3]=='A') && (d[4]=='u') && (d[5]=='g')) ct.tm_mon = 8-1;
          else if ((d[3]=='S') && (d[4]=='e') && (d[5]=='p')) ct.tm_mon = 9-1;
          else if ((d[3]=='O') && (d[4]=='c') && (d[5]=='t')) ct.tm_mon = 10-1;
          else if ((d[3]=='N') && (d[4]=='o') && (d[5]=='v')) ct.tm_mon = 11-1;
          else if ((d[3]=='D') && (d[4]=='e') && (d[5]=='c')) ct.tm_mon = 12-1;
          else BadDateM(); // compile this if no match above, and thus fail link.
          #IGNORE_WARNINGS  NONE
        
          ct.tm_mday = (d[0]-'0')*10 + (d[1]-'0');
          ct.tm_hour = (t[0]-'0')*10 + (t[1]-'0');
          ct.tm_min = (t[3]-'0')*10 + (t[4]-'0');
          ct.tm_sec = (t[6]-'0')*10 + (t[7]-'0');
        
          ct.tm_isdst = -1;  // information is not available.
          // ct.tm_yday = 0;
          // ct.tm_wday = 0;
        
          return &ct;
          }
        

        上市

        struct tm *CompileTimeTM(void) { 
        static const char d[10] = __DATE__; 
        static const char t[10] = __TIME__; 
        static struct tm ct; 
        
        ct.tm_year = (d[7]-'0')*10 + (d[8]-'0') + 2000 - 1900; 
        0F78 200724         MOV     #72,W4         : W4 = 72
        0F7A 8864D4         MOV     W4,C9A         : C9A = W4
        
        #IGNORE_WARNINGS  204 
        if (0) ; 
        else if ((d[3]=='J') && (d[4]=='a') && (d[5]=='n')) ct.tm_mon = 1-1; 
        else if ((d[3]=='F') && (d[4]=='e') && (d[5]=='b')) ct.tm_mon = 2-1; 
        else if ((d[3]=='M') && (d[4]=='a') && (d[5]=='r')) ct.tm_mon = 3-1; 
        else if ((d[3]=='A') && (d[4]=='p') && (d[5]=='r')) ct.tm_mon = 4-1; 
        0F7C 200034         MOV     #3,W4          : W4 = 3
        0F7E 8864C4         MOV     W4,C98         : C98 = W4
        else if ((d[3]=='M') && (d[4]=='a') && (d[5]=='y')) ct.tm_mon = 5-1; 
        else if ((d[3]=='J') && (d[4]=='u') && (d[5]=='n')) ct.tm_mon = 6-1; 
        else if ((d[3]=='J') && (d[4]=='u') && (d[5]=='l')) ct.tm_mon = 7-1; 
        else if ((d[3]=='A') && (d[4]=='u') && (d[5]=='g')) ct.tm_mon = 8-1; 
        else if ((d[3]=='S') && (d[4]=='e') && (d[5]=='p')) ct.tm_mon = 9-1; 
        else if ((d[3]=='O') && (d[4]=='c') && (d[5]=='t')) ct.tm_mon = 10-1; 
        else if ((d[3]=='N') && (d[4]=='o') && (d[5]=='v')) ct.tm_mon = 11-1; 
        else if ((d[3]=='D') && (d[4]=='e') && (d[5]=='c')) ct.tm_mon = 12-1; 
        else BadDateM(); // compile this if no match above, and thus fail link. 
        #IGNORE_WARNINGS  NONE 
        
        ct.tm_mday = (d[0]-'0')*10 + (d[1]-'0'); 
        0F80 2000E4         MOV     #E,W4          : W4 = E
        0F82 8864B4         MOV     W4,C96         : C96 = W4
        ct.tm_hour = (t[0]-'0')*10 + (t[1]-'0'); 
        0F84 2000B4         MOV     #B,W4          : W4 = B
        0F86 8864A4         MOV     W4,C94         : C94 = W4
        ct.tm_min = (t[3]-'0')*10 + (t[4]-'0'); 
        0F88 200354         MOV     #35,W4         : W4 = 35
        0F8A 886494         MOV     W4,C92         : C92 = W4
        ct.tm_sec = (t[6]-'0')*10 + (t[7]-'0'); 
        0F8C 2000D4         MOV     #D,W4          : W4 = D
        0F8E 886484         MOV     W4,C90         : C90 = W4
        

        【讨论】:

        • 函数CompileTimeTM()返回指向堆栈分配的struct tm的指针,它不应该工作。你忘了static,还是我错过了什么?
        • 将上面的函数制作成宏可能会很有用,以便可以在编译时计算日期时间值
        • @Dmitry Frank 是的,ct 应该是 static
        • @Lưu Vĩnh Phúc 日期时间仅在编译时计算。该函数在运行时唯一要做的就是移动值。 没有计算在运行时完成,因为编译器认为dt 是常量并在编译时优化所有计算。
        【解决方案7】:

        我发现如果一个月中的某天小于 10,我必须添加一个特殊检查 - 否则它会返回一个负数

               // special case to handle __DATE__ not inserting leading zero on day of month
               // if Day of month is less than 10 - it inserts a blank character
               // this results in a negative number for tm_mday 
        
               if(d[4] == ' ')
               {
            	   ct.tm_mday =  d[5]-'0';
               }
               else
               {
            	   ct.tm_mday = (d[4]-'0')*10 + (d[5]-'0');
               }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-08-26
          • 1970-01-01
          • 1970-01-01
          • 2014-09-05
          • 2012-07-30
          • 1970-01-01
          • 2016-07-10
          相关资源
          最近更新 更多