I'm trying to build an RFC3339 timestamp in C. How do I get the timezone offset?












1















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;


}










share|improve this question

























  • 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
















1















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;


}










share|improve this question

























  • 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














1












1








1








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;


}










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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



















  • 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












1 Answer
1






active

oldest

votes


















0















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?






share|improve this answer


























  • 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





    @Luchs Answer updated.

    – chux
    Nov 21 '18 at 21:49











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
});


}
});














draft saved

draft discarded


















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









0















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?






share|improve this answer


























  • 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





    @Luchs Answer updated.

    – chux
    Nov 21 '18 at 21:49
















0















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?






share|improve this answer


























  • 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





    @Luchs Answer updated.

    – chux
    Nov 21 '18 at 21:49














0












0








0








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?






share|improve this answer
















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?







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 21 '18 at 19:30

























answered Feb 13 '18 at 17:47









chuxchux

81.7k871148




81.7k871148













  • 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





    @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






  • 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


















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

Create new schema in PostgreSQL using DBeaver

Deepest pit of an array with Javascript: test on Codility

Costa Masnaga