我想将当前时间打印为尽可能接近Python的isoformat()的ISO 8601
2024-01-16T09:32:46.090+01:00
。
目前我使用了以下使用 gettimeofday、localtime 和 strftime 的代码片段:
#include <stdio.h> //printf
#include <sys/time.h>
int main(){
struct timeval tv;
struct timezone tz;
gettimeofday(&tv, &tz);
char buf[30]; // 29 chars + '\0'
strftime(buf, 30, "%Y-%m-%dT%H:%M:%S%z", localtime(&tv.tv_sec));
printf("using strftime: %s\n", buf);
}
生成
2024-01-16T09:32:46+01:00
(缺少毫秒)。
我在 strftime 中没有找到任何格式说明符来打印毫秒。
strftime 采用 struct tm 作为输入,并且 struct tm 没有毫秒/微秒的概念,因此 strftime 无法从中获取毫秒。
为了获取毫秒,您需要求助于 gettimeofday 返回的 struct timeval,它有一个名为
tv_usec
的成员,其中的微秒可以通过除以 1000 轻松转换为毫秒。或者使用 clock_gettime 提供纳秒。请参阅底部带有 clock_gettime 的示例。
#include <stdio.h> //printf
#include <sys/time.h>
int main(){
struct timeval tv;
struct timezone tz;
gettimeofday(&tv, &tz);
char buf[30]; // 29 chars + '\0'
int off = 0;
struct tm *local = localtime(&tv.tv_sec);
off = strftime(buf, 30, "%Y-%m-%dT%H:%M:%S", local);
off += snprintf(buf+off, 30-off, ".%03d", tv.tv_usec/1000);
off += strftime(buf+off, 30-off, "%z", local);
printf("using strftime: %s\n", buf);
}
执行时会产生
2024-01-16T14:08:15.079+0100
,它是带有毫秒和 UTC 偏移量的 ISO 8601。不幸的是, %z
产生 UTC 偏移量,格式为 +0100
(无冒号),而不是 +01:00
gcc test.c -g -Wall -std=c11 && ./a.out
using strftime: 2024-01-16T14:08:15.079+0100
如果您确实需要带冒号的 UTC 偏移量。然后您可以使用
gettimeofday中的
struct timezone
。您需要将 off += strftime(buf+off, 30-off, "%z", local);
替换为更复杂的:
if (tz.tz_minuteswest >= 0) {
off += snprintf(buf+off, 30-off, "+%02d:%02d", tz.tz_minuteswest/60, tz.tz_minuteswest%60);
} else {
off += snprintf(buf+off, 30-off, "-%02d:%02d", -tz.tz_minuteswest/60, -tz.tz_minuteswest%60);
}
请注意,gettimeofday被认为已被弃用,取而代之的是clock_gettime,因此完成这一切的最佳方法是:
#include <stdio.h> //printf
#include <sys/time.h>
int main(){
struct timespec tp;
clock_gettime(CLOCK_REALTIME, &tp);
char buf[30]; // 29 chars + '\0'
int off = 0;
struct tm *local = localtime(&tp.tv_sec);
off = strftime(buf, 30, "%Y-%m-%dT%H:%M:%S", local);
off += snprintf(buf+off, 30-off, ".%03ld", tp.tv_nsec/1000000);
if (local->tm_gmtoff >= 0) {
off += snprintf(buf+off, 30-off, "+%02ld:%02ld", local->tm_gmtoff/3600, local->tm_gmtoff%3600);
} else {
off += snprintf(buf+off, 30-off, "-%02ld:%02ld", -local->tm_gmtoff/3600, -local->tm_gmtoff%3600);
}
printf("using strftime: %s\n", buf);
}
唯一的变化是使用 clock_gettime 而不是 gettimeofday 并使用 localtime 在 struct tm 中提供的时区信息作为
tm_gmtoff
。
gcc test.c -g -Wall -std=c11
TZ="Europe/Madrid" ./a.out
using strftime: 2024-01-16T14:47:56.928+01:00
TZ="America/Anchorage" ./a.out
using strftime: 2024-01-16T04:47:39.226-09:00