如何在ISO 8601:2004中替换__TIMESTAMP__
?
__TIMESTAMP__
Sat Jul 6 02:50:06 2013
VS
__TIMESTAMP_ISO__
2013-07-06T00:50:06Z
答案 0 :(得分:17)
__TIMESTAMP__
定义不在标准C中。拥有像你提议的__TIMESTAMP_ISO__
那样的格式会很棒(你总是想要祖鲁时间,还是让本地时区偏移会更好?),但坦率地说,最简单的方法是添加它是GCC和Clang等的补丁。
您可以按照user1034749 answer的建议,尝试使用asctime()
进行代理,但我不想尝试。
在GCC 4.8.1 manual中,有一个有趣的警告抑制:
-Wno-builtin-macro-redefined
如果重新定义了某些内置宏,请不要发出警告。这会禁止重新定义__TIMESTAMP__
,__TIME__
,__DATE__
,__FILE__
和__BASE_FILE__
。
这表明你可以尝试:
gcc ... -Wno-builtin-macro-redefined -D__TIMESTAMP__=$(date +'"%Y-%m-%dT%H:%M:%S"') ...
(注意从双引号括起来的date
字符串所需的象形文字。)但是,某些早期版本的GCC不支持该选项;我不记得以前见过它。您仍然可以重新定义__TIMESTAMP__
:
$ gcc -std=c99 -Wall -Wextra -O xx.c -o xx
$ ./xx
Fri Jul 5 19:56:25 2013
$ gcc -std=c99 -Wall -Wextra -D__TIMESTAMP__=$(date +'"%Y-%m-%dT%H:%M:%S"') -O xx.c -o xx
<command-line>: warning: "__TIMESTAMP__" redefined
$ ./xx
2013-07-05T20:10:28
$
不是很漂亮,但它有效...哦,只是为了记录,源代码是(微不足道的):
#include <stdio.h>
int main(void)
{
printf("%s\n", __TIMESTAMP__);
return 0;
}
答案 1 :(得分:1)
@Jonathan Leffler的回答提供了一个很好的解决方案,但可能有一件事被忽略了:
最初的问题是询问__TIMESTAMP__
的替代格式,而__TIMESTAMP__
将扩展为当前源文件的最后修改日期时间的字符串。
但是,原始答案实际上是为__TIMESTAMP__
分配了运行gcc的日期时间(即 build 时间),该日期时间是__DATE__
和__TIME__
如何改进:
使用@mmond的answer,将date +'"%Y-%m-%dT%H:%M:%S"'
中的-D__TIMESTAMP__=...
命令替换为date +'"%Y-%m-%dT%H:%M:%S"' -r xx.c
,即添加选项-r xx.c
以引用 xx.c 在运行date
命令时。 xx.c 是正在构建的源代码。
参考:
根据海湾合作委员会的[manual][2]
__TIMESTAMP__
该宏扩展为一个字符串常量,该字符串常量描述了当前源文件的最后一次修改的日期和时间。
答案 2 :(得分:1)
这是一种定义字符串常量的方法,该常量包含编译时间戳记的日期部分。添加时间部分并使其从__TIMESTAMP__
而不是__DATE__
开始工作,并非难事。
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);
答案 3 :(得分:0)
如果您需要一种真正的跨平台方式来使用ISO 8601格式化的编译时间戳字符串或在编译时定义的任何其他格式,您可以考虑使用CMake(这总是很好考虑使用)。
答案 4 :(得分:-1)
clang和gcc为此目的使用了C函数“asctime”,我想icc也使用它。在Linux上,您可以使用LD_PRELOAD来捕获asctime调用并替换为您想要的任何字符串。