__DATE__宏的不同格式

Different format of __DATE__ macro

本文关键字:格式 DATE      更新时间:2023-10-16

C有一个预定义的宏__DATE__,它显示编译的源文件的日期
日期显示格式为"Mmm-dd-yyyy"

有什么方法可以使用宏来格式化这个日期吗
采用此格式"yyyy-Mmm-dd"

而不是:

2013年7月19日

应为:

2013年7月19日

在C中,您可以有一个宏来动态生成具有您喜欢的顺序的复合文字,类似

#define FDATE (char const[]){ __DATE__[7], __DATE__[8], ..., ' ', ... , '' }

在所有重要的地方,优化器都应该能够有效地处理这一问题。

如果有人正在寻找将Mmm DD YYYY转换为仅包含ASCII数字的字符串YYMMDD(如"220103")的方法,那么下面是代码。它应该同时在C和C++中工作:

#include <stdio.h>
const char version[6+1] =
{
   // YY year
   __DATE__[9], __DATE__[10],
   // First month letter, Oct Nov Dec = '1' otherwise '0'
   (__DATE__[0] == 'O' || __DATE__[0] == 'N' || __DATE__[0] == 'D') ? '1' : '0',
   
   // Second month letter
   (__DATE__[0] == 'J') ? ( (__DATE__[1] == 'a') ? '1' :       // Jan, Jun or Jul
                            ((__DATE__[2] == 'n') ? '6' : '7') ) :
   (__DATE__[0] == 'F') ? '2' :                                // Feb 
   (__DATE__[0] == 'M') ? (__DATE__[2] == 'r') ? '3' : '5' :   // Mar or May
   (__DATE__[0] == 'A') ? (__DATE__[1] == 'p') ? '4' : '8' :   // Apr or Aug
   (__DATE__[0] == 'S') ? '9' :                                // Sep
   (__DATE__[0] == 'O') ? '0' :                                // Oct
   (__DATE__[0] == 'N') ? '1' :                                // Nov
   (__DATE__[0] == 'D') ? '2' :                                // Dec
   0,
   // First day letter, replace space with digit
   __DATE__[4]==' ' ? '0' : __DATE__[4],
   // Second day letter
   __DATE__[5],
  ''
};
int main(void)
{
  puts(__DATE__);
  puts(version);
}

输出:

Jan  3 2022
220103

拆卸(gcc x86_64):

version:
        .string "220103"

这里有一个真正的破解:

union {
    const char DOUBLE_DATE[18];
    const char PAD[19];
} DATE_HELPER = { __DATE__ " " __DATE__ };
const char *MY_DATE = DATE_HELPER.DOUBLE_DATE + 7;

我想要C++程序中ISO格式的编译日期,所以我想出了这个:

constexpr unsigned int compileYear = (__DATE__[7] - '0') * 1000 + (__DATE__[8] - '0') * 100 + (__DATE__[9] - '0') * 10 + (__DATE__[10] - '0');
constexpr unsigned int compileMonth = (__DATE__[0] == 'J') ? ((__DATE__[1] == 'a') ? 1 : ((__DATE__[2] == 'n') ? 6 : 7))    // Jan, Jun or Jul
                                    : (__DATE__[0] == 'F') ? 2                                                              // Feb
                                    : (__DATE__[0] == 'M') ? ((__DATE__[2] == 'r') ? 3 : 5)                                 // Mar or May
                                    : (__DATE__[0] == 'A') ? ((__DATE__[2] == 'p') ? 4 : 8)                                 // Apr or Aug
                                    : (__DATE__[0] == 'S') ? 9                                                              // Sep
                                    : (__DATE__[0] == 'O') ? 10                                                             // Oct
                                    : (__DATE__[0] == 'N') ? 11                                                             // Nov
                                    : (__DATE__[0] == 'D') ? 12                                                             // Dec
                                    : 0;
constexpr unsigned int compileDay = (__DATE__[4] == ' ') ? (__DATE__[5] - '0') : (__DATE__[4] - '0') * 10 + (__DATE__[5] - '0');
constexpr char IsoDate[] =
{   compileYear/1000 + '0', (compileYear % 1000)/100 + '0', (compileYear % 100)/10 + '0', compileYear % 10 + '0',
    '-',  compileMonth/10 + '0', compileMonth%10 + '0',
    '-',  compileDay/10 + '0', compileDay%10 + '0',
    0
};
// Test that it gets it right today
#include <cstring>
static_assert(strcmp(IsoDate, "2020-11-06") == 0);

我想要C++程序中ISO格式的编译日期,所以我想出了这个:

感谢"dc42"提供的解决方案。我想建议一种替代解决方案,根据DATE格式编译月份,这可能对所有人来说都更清楚。

unsigned int compileMonth = (int)__DATE__[0]+(int)__DATE__[1]+(int)__DATE__[2];
compileMonth = compileMonth == 281 ? 1
             : compileMonth == 269 ? 2
             : compileMonth == 288 ? 3
             : compileMonth == 291 ? 4
             : compileMonth == 295 ? 5
             : compileMonth == 301 ? 6
             : compileMonth == 299 ? 7
             : compileMonth == 285 ? 8
             : compileMonth == 296 ? 9
             : compileMonth == 294 ? 10
             : compileMonth == 307 ? 11
             : compileMonth == 268 ? 12
             : 0;