我正在尝试在C中构建RFC3339时间戳.如何获取时区偏移量? [英] I'm trying to build an RFC3339 timestamp in C. How do I get the timezone offset?
问题描述
我正在尝试将RFC3339时间戳放在一起,该时间戳将用于将特定条目写入数据库.格式将设置为例如2004-10-19 10:23:54 + 02,其中+02是距格林尼治标准时间的小时数偏移量.正是这个偏移量被证明很麻烦-我似乎无法在C中得出该值.
I'm attempting to put together an RFC3339 timestamp which will be used to write a certain entry to a database. That would be formatted as, for example, 2004-10-19 10:23:54+02, where the +02 is the offset in hours from GMT. It's this offset which is proving troublesome - I can't seem to derive this value in C.
这是我正在使用的代码.当我尝试构建时,它说tm结构没有名为tm_gmtoff的成员:
Here is the code I'm using. When I try to build, it says the tm struct doesn't have a member named tm_gmtoff:
#include <time.h>
#include <stdio.h>
int main(void)
{
time_t now = time(NULL);
struct tm *tm;
int off_sign;
int off;
if ((tm = localtime(&now)) == NULL) {
return -1;
}
off_sign = '+';
off = (int) tm->tm_gmtoff;
if (tm->tm_gmtoff < 0) {
off_sign = '-';
off = -off;
}
printf("%d-%d-%dT%02d:%02d:%02d%c%02d:%02d",
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
off_sign, off / 3600, off % 3600);
return 0;
}
推荐答案
在C语言中构建RFC3339时间戳
to build an RFC3339 timestamp in C
如果目标是 string ,则简单的解决方案是使用strftime()
.
If a string is the goal, the easy solution is to use 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的成员:
How do I get the timezone offset?
When I try to build, it says the tm struct doesn't have a member named tm_gmtoff:
tm_gmtoff
是struct tm
的可选额外成员.如果可用,则可以使用该成员或其他类似的依赖实现的成员.
The tm_gmtoff
is an optional extra member of struct tm
. When available, that or some other similar implementation dependent member would be good to use.
With access to strftime()
and "%z"
, as suggeted by @jwdonahue.
"%z"
available since C99.
%z由ISO 8601格式'−0430'"(表示4的UTC偏移)代替 比格林威治标准时间UTC晚30分钟),如果没有时间,则不限字符 区域是可以确定的. C11§7.27.3.53
%z is replaced by the offset from UTC in the ISO 8601 format ‘‘−0430’’ (meaning 4 hours 30 minutes behind UTC, west of Greenwich), or by no characters if no time zone is determinable. 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);
}
Minute difference -360
缺少上述选择,代码可以直接从localtime()
和gmttime()
推导出时区偏移:进行struct tm
减法.
Lacking the above choices, code can deduce the timezone offset directly from localtime()
and gmttime()
: do a struct tm
subtraction.
以下内容利用了时间戳的差异在1月1日附近不超过1天的优势.
The below takes advantage that a difference in timestamps does not exceed 1 day near January 1st.
#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;
}
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
的时区偏移量:
To print the timezone offset per RFC3339 given hour, minute
:
// Alway print the sign and leading zero digits
printf("%+02d:%02d", hours, abs(minute));
另请参见 ISO 8601和RFC 3339日期格式之间有何区别?
这篇关于我正在尝试在C中构建RFC3339时间戳.如何获取时区偏移量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!