在 C 中构建 RFC3339 时间戳
如果目标是字符串,那么简单的解决方案是使用strftime()
.
time_t now;
time(&now);
struct tm *p = localtime(&now);
char buf[100];
size_t len = strftime(buf, sizeof buf - 1, "%FT%T%z", p);
// move last 2 digits
if (len > 1) {
char minute[] = { buf[len-2], buf[len-1], '\0' };
sprintf(buf + len - 2, ":%s", minute);
}
printf("\"%s\"\n", buf);
输出
"2018-11-21T13:21:08-06:00"
如何获得时区偏移量?
当我尝试构建时,它说 tm 结构没有名为 tm_gmtoff 的成员:
是的tm_gmtoff
可选额外成员struct tm
。如果可用,该或其他类似的实现相关成员将很适合使用。
可以访问strftime()
and "%z"
,正如@jwdonahue 所建议的那样。
"%z"
从 C99 开始可用。
%z 被 ISO 8601 格式 ''−0430'' 中的 UTC 偏移量(意味着格林威治以西的 UTC 时间晚 4 小时 30 分钟)替换,如果无法确定时区,则替换为无字符。C11 §7.27.3.5 3
int main(void) {
time_t now;
time(&now);
struct tm *p = localtime(&now);
char buf[6];
strftime(buf, sizeof buf, "%z", p);
int h, m;
sscanf(buf, "%3d%d", &h, &m);
if (h < 0) m = -m;
printf("Minute difference %d\n", h*60+m);
}
CT输出
Minute difference -360
缺少上述选择,代码可以直接从 localtime()
和推导出时区偏移量gmttime()
:做struct tm
减法。
下面利用时间戳的差异在 1 月 1 日附近不超过 1 天。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Return difference in seconds.
long tz_offset(time_t t) {
struct tm *p = localtime(&t);
if (p == NULL) return INT_MIN;
printf("%s", asctime(p));
struct tm local = *p;
p = gmtime(&t);
if (p == NULL) return INT_MIN;
printf("%s", asctime(p));
struct tm gmt = *p;
int day = local.tm_yday - gmt.tm_yday;
if (local.tm_year > gmt.tm_year) {
day = 1;
} else if (local.tm_year < gmt.tm_year) {
day = -1;
}
int hour = day*24 + (local.tm_hour - gmt.tm_hour);
if (local.tm_isdst) {
; // no adjustment
}
long diff = (hour*60L + (local.tm_min - gmt.tm_min))*60 + (local.tm_sec - gmt.tm_sec);
return diff;
}
int main(void) {
time_t now;
time(&now);
printf("tz offset %g\n", tz_offset(now)/3600.0);
// Check time 6-months from now, maybe different daylight setting
struct tm *p = localtime(&now);
p->tm_mon += 6;
now = mktime(p);
printf("tz offset %g\n", tz_offset(now)/3600.0);
return 0;
}
CT的样本输出
Tue Feb 13 11:40:00 2018
Tue Feb 13 17:40:00 2018
tz offset -6
Mon Aug 13 12:40:00 2018
Mon Aug 13 17:40:00 2018
tz offset -5
要打印每个RFC3339给定的时区偏移量hour, minute
:
// Alway print the sign and leading zero digits
printf("%+02d:%02d", hours, abs(minute));
另请参阅ISO 8601 和 RFC 3339 日期格式有什么区别?