I'm trying to build an RFC3339 timestamp in C. How do I get the timezone offset?
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.
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 time timezone timezoneoffset rfc3339
|
show 5 more comments
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.
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 time timezone timezoneoffset rfc3339
Have you tried stackoverflow.com/questions/13804095/… ?
– Antonin GAVREL
Feb 13 '18 at 16:58
Yes, and I see the following error: 'struct tm' has no member named 'tm_gmtoff'; did you mean 'tm_mon'?
– K. Haskins
Feb 13 '18 at 17:06
1
Re: "where the +02 is the offset in hours". How do you want to handle offsets that are −2:30 or +05:45?
– chux
Feb 13 '18 at 17:13
1
Which C are you running on what platform? Not all C compilers have what you need.
– VladP
Feb 13 '18 at 17:28
1
Does your std library not have strftime?
– jwdonahue
Feb 13 '18 at 17:49
|
show 5 more comments
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.
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 time timezone timezoneoffset rfc3339
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.
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 time timezone timezoneoffset rfc3339
c time timezone timezoneoffset rfc3339
edited Feb 13 '18 at 17:01
K. Haskins
asked Feb 13 '18 at 16:55
K. HaskinsK. Haskins
133
133
Have you tried stackoverflow.com/questions/13804095/… ?
– Antonin GAVREL
Feb 13 '18 at 16:58
Yes, and I see the following error: 'struct tm' has no member named 'tm_gmtoff'; did you mean 'tm_mon'?
– K. Haskins
Feb 13 '18 at 17:06
1
Re: "where the +02 is the offset in hours". How do you want to handle offsets that are −2:30 or +05:45?
– chux
Feb 13 '18 at 17:13
1
Which C are you running on what platform? Not all C compilers have what you need.
– VladP
Feb 13 '18 at 17:28
1
Does your std library not have strftime?
– jwdonahue
Feb 13 '18 at 17:49
|
show 5 more comments
Have you tried stackoverflow.com/questions/13804095/… ?
– Antonin GAVREL
Feb 13 '18 at 16:58
Yes, and I see the following error: 'struct tm' has no member named 'tm_gmtoff'; did you mean 'tm_mon'?
– K. Haskins
Feb 13 '18 at 17:06
1
Re: "where the +02 is the offset in hours". How do you want to handle offsets that are −2:30 or +05:45?
– chux
Feb 13 '18 at 17:13
1
Which C are you running on what platform? Not all C compilers have what you need.
– VladP
Feb 13 '18 at 17:28
1
Does your std library not have strftime?
– jwdonahue
Feb 13 '18 at 17:49
Have you tried stackoverflow.com/questions/13804095/… ?
– Antonin GAVREL
Feb 13 '18 at 16:58
Have you tried stackoverflow.com/questions/13804095/… ?
– Antonin GAVREL
Feb 13 '18 at 16:58
Yes, and I see the following error: 'struct tm' has no member named 'tm_gmtoff'; did you mean 'tm_mon'?
– K. Haskins
Feb 13 '18 at 17:06
Yes, and I see the following error: 'struct tm' has no member named 'tm_gmtoff'; did you mean 'tm_mon'?
– K. Haskins
Feb 13 '18 at 17:06
1
1
Re: "where the +02 is the offset in hours". How do you want to handle offsets that are −2:30 or +05:45?
– chux
Feb 13 '18 at 17:13
Re: "where the +02 is the offset in hours". How do you want to handle offsets that are −2:30 or +05:45?
– chux
Feb 13 '18 at 17:13
1
1
Which C are you running on what platform? Not all C compilers have what you need.
– VladP
Feb 13 '18 at 17:28
Which C are you running on what platform? Not all C compilers have what you need.
– VladP
Feb 13 '18 at 17:28
1
1
Does your std library not have strftime?
– jwdonahue
Feb 13 '18 at 17:49
Does your std library not have strftime?
– jwdonahue
Feb 13 '18 at 17:49
|
show 5 more comments
1 Answer
1
active
oldest
votes
to build an RFC3339 timestamp in C
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], '' };
sprintf(buf + len - 2, ":%s", minute);
}
printf(""%s"n", buf);
Output
"2018-11-21T13:21:08-06:00"
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:
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 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 %dn", h*60+m);
}
Output for CT
Minute difference -360
Lacking the above choices, code can deduce the timezone offset directly from localtime()
and gmttime()
: do a struct tm
subtraction.
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 %gn", 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 %gn", tz_offset(now)/3600.0);
return 0;
}
Sample output for 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
To print the timezone offset per RFC3339 given hour, minute
:
// Alway print the sign and leading zero digits
printf("%+02d:%02d", hours, abs(minute));
See also What's the difference between ISO 8601 and RFC 3339 Date Formats?
Thestrftime
call you give in the first section does not produce a valid RFC3339 string. In RFC3339, the time zone needs to be formatted with a colon. For your example to be valid, it would have to look like this:"2018-02-13T12:32:52-06:00"
– Luchs
Nov 21 '18 at 8:25
1
@Luchs Answer updated.
– chux
Nov 21 '18 at 21:49
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f48771851%2fim-trying-to-build-an-rfc3339-timestamp-in-c-how-do-i-get-the-timezone-offset%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
to build an RFC3339 timestamp in C
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], '' };
sprintf(buf + len - 2, ":%s", minute);
}
printf(""%s"n", buf);
Output
"2018-11-21T13:21:08-06:00"
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:
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 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 %dn", h*60+m);
}
Output for CT
Minute difference -360
Lacking the above choices, code can deduce the timezone offset directly from localtime()
and gmttime()
: do a struct tm
subtraction.
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 %gn", 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 %gn", tz_offset(now)/3600.0);
return 0;
}
Sample output for 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
To print the timezone offset per RFC3339 given hour, minute
:
// Alway print the sign and leading zero digits
printf("%+02d:%02d", hours, abs(minute));
See also What's the difference between ISO 8601 and RFC 3339 Date Formats?
Thestrftime
call you give in the first section does not produce a valid RFC3339 string. In RFC3339, the time zone needs to be formatted with a colon. For your example to be valid, it would have to look like this:"2018-02-13T12:32:52-06:00"
– Luchs
Nov 21 '18 at 8:25
1
@Luchs Answer updated.
– chux
Nov 21 '18 at 21:49
add a comment |
to build an RFC3339 timestamp in C
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], '' };
sprintf(buf + len - 2, ":%s", minute);
}
printf(""%s"n", buf);
Output
"2018-11-21T13:21:08-06:00"
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:
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 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 %dn", h*60+m);
}
Output for CT
Minute difference -360
Lacking the above choices, code can deduce the timezone offset directly from localtime()
and gmttime()
: do a struct tm
subtraction.
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 %gn", 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 %gn", tz_offset(now)/3600.0);
return 0;
}
Sample output for 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
To print the timezone offset per RFC3339 given hour, minute
:
// Alway print the sign and leading zero digits
printf("%+02d:%02d", hours, abs(minute));
See also What's the difference between ISO 8601 and RFC 3339 Date Formats?
Thestrftime
call you give in the first section does not produce a valid RFC3339 string. In RFC3339, the time zone needs to be formatted with a colon. For your example to be valid, it would have to look like this:"2018-02-13T12:32:52-06:00"
– Luchs
Nov 21 '18 at 8:25
1
@Luchs Answer updated.
– chux
Nov 21 '18 at 21:49
add a comment |
to build an RFC3339 timestamp in C
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], '' };
sprintf(buf + len - 2, ":%s", minute);
}
printf(""%s"n", buf);
Output
"2018-11-21T13:21:08-06:00"
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:
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 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 %dn", h*60+m);
}
Output for CT
Minute difference -360
Lacking the above choices, code can deduce the timezone offset directly from localtime()
and gmttime()
: do a struct tm
subtraction.
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 %gn", 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 %gn", tz_offset(now)/3600.0);
return 0;
}
Sample output for 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
To print the timezone offset per RFC3339 given hour, minute
:
// Alway print the sign and leading zero digits
printf("%+02d:%02d", hours, abs(minute));
See also What's the difference between ISO 8601 and RFC 3339 Date Formats?
to build an RFC3339 timestamp in C
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], '' };
sprintf(buf + len - 2, ":%s", minute);
}
printf(""%s"n", buf);
Output
"2018-11-21T13:21:08-06:00"
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:
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 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 %dn", h*60+m);
}
Output for CT
Minute difference -360
Lacking the above choices, code can deduce the timezone offset directly from localtime()
and gmttime()
: do a struct tm
subtraction.
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 %gn", 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 %gn", tz_offset(now)/3600.0);
return 0;
}
Sample output for 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
To print the timezone offset per RFC3339 given hour, minute
:
// Alway print the sign and leading zero digits
printf("%+02d:%02d", hours, abs(minute));
See also What's the difference between ISO 8601 and RFC 3339 Date Formats?
edited Nov 21 '18 at 19:30
answered Feb 13 '18 at 17:47
chuxchux
81.7k871148
81.7k871148
Thestrftime
call you give in the first section does not produce a valid RFC3339 string. In RFC3339, the time zone needs to be formatted with a colon. For your example to be valid, it would have to look like this:"2018-02-13T12:32:52-06:00"
– Luchs
Nov 21 '18 at 8:25
1
@Luchs Answer updated.
– chux
Nov 21 '18 at 21:49
add a comment |
Thestrftime
call you give in the first section does not produce a valid RFC3339 string. In RFC3339, the time zone needs to be formatted with a colon. For your example to be valid, it would have to look like this:"2018-02-13T12:32:52-06:00"
– Luchs
Nov 21 '18 at 8:25
1
@Luchs Answer updated.
– chux
Nov 21 '18 at 21:49
The
strftime
call you give in the first section does not produce a valid RFC3339 string. In RFC3339, the time zone needs to be formatted with a colon. For your example to be valid, it would have to look like this: "2018-02-13T12:32:52-06:00"
– Luchs
Nov 21 '18 at 8:25
The
strftime
call you give in the first section does not produce a valid RFC3339 string. In RFC3339, the time zone needs to be formatted with a colon. For your example to be valid, it would have to look like this: "2018-02-13T12:32:52-06:00"
– Luchs
Nov 21 '18 at 8:25
1
1
@Luchs Answer updated.
– chux
Nov 21 '18 at 21:49
@Luchs Answer updated.
– chux
Nov 21 '18 at 21:49
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f48771851%2fim-trying-to-build-an-rfc3339-timestamp-in-c-how-do-i-get-the-timezone-offset%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Have you tried stackoverflow.com/questions/13804095/… ?
– Antonin GAVREL
Feb 13 '18 at 16:58
Yes, and I see the following error: 'struct tm' has no member named 'tm_gmtoff'; did you mean 'tm_mon'?
– K. Haskins
Feb 13 '18 at 17:06
1
Re: "where the +02 is the offset in hours". How do you want to handle offsets that are −2:30 or +05:45?
– chux
Feb 13 '18 at 17:13
1
Which C are you running on what platform? Not all C compilers have what you need.
– VladP
Feb 13 '18 at 17:28
1
Does your std library not have strftime?
– jwdonahue
Feb 13 '18 at 17:49