Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Converting local time to UTC

50 views
Skip to first unread message

Mark

unread,
Oct 14, 2015, 2:52:06 AM10/14/15
to
I am trying to write some code to convert local time to UTC. I am
using the following which works in many circumstance but a client in
the US has found it not working correctly:

void convertToUTC(const char *input, char *output)
{
struct tm tm_;

memset(&tm_, 0, sizeof(struct tm));

if (!strptime(input, "%d-%b-%Y %T", &tm_))
{
// failed
return;
}
time_t thetime = mktime(&tm_);
// Convert to UTC
struct tm gmcal = *gmtime(&thetime);
thetime = mktime(&gmcal);

struct tm *tm_p;
struct tm tm2;

tm_p = gmtime_r(&thetime, &tm2);

sprintf(output, "%4d-%02d-%02dT%02d:%02d:%02dZ",
tm_p->tm_year + 1900,
tm_p->tm_mon + 1,
tm_p->tm_mday,
tm_p->tm_hour,
tm_p->tm_min,
tm_p->tm_sec);
}

"13-Oct-2015 06:57:17" --> "2015-10-13T22:57:17Z"

Output from 'date' command:
date; date -u
Tue Oct 13 06:58:10 PDT 2015
Tue Oct 13 13:58:10 UTC 2015

Can someone tell me how to fix this?

Lőrinczy Zsigmond

unread,
Oct 14, 2015, 5:30:12 AM10/14/15
to
I think it could be simplified

void convertToUTC(const char *input, char *output)
{
struct tm tmloc, tmutc;
time_t thetime;

memset(&tmloc, 0, sizeof tmloc);
memset(&tmutc, 0, sizeof tmutc);

if (!strptime(input, "%d-%b-%Y %T",&tmloc))
{
// failed
return;
}
thetime = mktime(&tmloc);
gmtime_r(&thetime, &tmutc);

sprintf(output, "%4d-%02d-%02dT%02d:%02d:%02dZ",
tmutc.tm_year + 1900,
tmutc.tm_mon + 1,
tmutc.tm_mday,
tmutc.tm_hour,
tmutc.tm_min,
tmutc.tm_sec);
}

Mark

unread,
Oct 14, 2015, 5:38:25 AM10/14/15
to
Won't this behave in exactly the same way as my code?

Nobody

unread,
Oct 14, 2015, 10:01:48 AM10/14/15
to
On Wed, 14 Oct 2015 07:51:40 +0100, Mark wrote:

> I am trying to write some code to convert local time to UTC. I am
> using the following which works in many circumstance but a client in
> the US has found it not working correctly:
>
> void convertToUTC(const char *input, char *output)
> {
> struct tm tm_;
>
> memset(&tm_, 0, sizeof(struct tm));
>
> if (!strptime(input, "%d-%b-%Y %T", &tm_))
> {
> // failed
> return;
> }
> time_t thetime = mktime(&tm_);

You should probably set tm_.is_dst=-1 prior to calling mktime(). That will
cause it to attempt to determine whether or not DST is in effect based
upon the date and time. That still has a problem when clocks go back as
any time within the last hour of DST or the first hour afterwards will be
ambiguous.

If the is_dst is field zero, DST is not used.

But that's not the biggest issue here.

> // Convert to UTC
> struct tm gmcal = *gmtime(&thetime);
> thetime = mktime(&gmcal);
>
> struct tm *tm_p;
> struct tm tm2;
>
> tm_p = gmtime_r(&thetime, &tm2);

This is bogus. You're taking a time_t (number of seconds since the epoch),
converting it to calendar time as UTC, then requesting the calendar time
be treated as local time and converted to a time_t. Then converting it to
calendar time as UTC again.

The second mktime() call and the gmtime_r() call shouldn't be there. If
you want local time, it's in tm_. If you want UTC, it's in gmcal. The
value in tm2/*tm_p is nonsense; it's had the timezone offset applied twice.

I can't see how this can work in any situation other than where local time
happens to be UTC (or possibly UTC+1 due to DST which is being ignored).

Richard

unread,
Oct 16, 2015, 2:53:22 PM10/16/15
to
[Please do not mail me a copy of your followup]

Mark <i...@dontgetlotsofspamanymore.net> spake the secret code
<bdur1bh61v892is7r...@4ax.com> thusly:

>I am trying to write some code to convert local time to UTC. I am
>using the following which works in many circumstance but a client in
>the US has found it not working correctly:
>
>void convertToUTC(const char *input, char *output)

C-style string char * arguments and C library functions?

Are you sure you're posting to the correct newsgroup?

Did you mean comp.lang.c instead?

This sort of stuff is *trivial* with boost.datetime. They even have
an explicit example demonstrating this exact conversion.

<http://www.boost.org/doc/libs/1_59_0/doc/html/date_time/examples.html#date_time.examples.local_utc_conversion>

No need to use crufty, error-prone, non-typesafe hacks with sprintf.

For well known problems, always prefer a time-tested well known
implementation.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
0 new messages