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).