4

I found the following problem. I have a string with a time (gotten from a file to which I putoutted using the reverse operations). However, when converting this to a time_point and outputting it to terminal, I find a difference of one hour. I have not been able to find out why. Any ideas?

#include <iostream>
#include <chrono>
#include <sstream>
#include <iomanip>

const char *const TIME_FORMAT = "%Y-%b-%d %H:%M:%S";

int main() {
    //Formatted timestring
    std::string timeString = "2018-Jun-18 09:03:43,24";

    //Logic to parce the string into a time struct
    std::istringstream ss(timeString);
    std::locale locale("");
    ss.imbue(locale);
    std::tm t = {};
    ss >> std::get_time(&t, TIME_FORMAT);

    if (ss.fail()) {
        //TODO throw exception;
        std::cout << "Parse failed\n";
    }

    //Convert to time_point
    time_t time = mktime(&t);
    auto time_point = std::chrono::system_clock::from_time_t(time);

    //Convert  to output string
    auto time_t_again = std::chrono::system_clock::to_time_t(time_point);
    std::cout << "timePoint: " << std::put_time(std::localtime(&time_t_again), TIME_FORMAT);
    return 0;
}

This outputs: timePoint: 2018-Jun-18 10:03:43 instead of the expected 2018-Jun-18 9:03:43

jelmew
  • 543
  • 1
  • 7
  • 15
  • Under Visual Studio 2017 I get "Parse failed". – Jabberwocky Jun 18 '18 at 08:35
  • 1
    Seems to be a Daylight Saving Time issue. It works here if [`t.tm_isdst`](http://en.cppreference.com/w/c/chrono/tm) is set to `-1` before the call to [`mktime`](http://en.cppreference.com/w/c/chrono/mktime). `0`, the current value from the initialization because [`std::get_time`](http://en.cppreference.com/w/cpp/io/manip/get_time) doesn't touch it, tells `mktime` that DST is *not* in effect. – cfillion Jun 18 '18 at 08:45

1 Answers1

3

The problem is mktime. It modifies the time based on t.tm_isdst. You also need to run a std::memset on the struct tm before run (parsers are filling in what they found in the format).

From this point you could have 2 options:

  1. set t.tm_isdst to -1 as suggested and daylight changes made automatically based on the parsed date (handling time as local time),
  2. use timegm or _mkgmtime and keep t.tm_isdst as 0 against mktime (handling time as UTC, simplify the code).
Naszta
  • 7,560
  • 2
  • 33
  • 49