Roman Kutlak
Roman Kutlak

Reputation: 2784

Strange behaviour when printing/reading time

I am trying to save std::time_point into a std::stream and read it back. One problem is that using the standard functions 'loses' an hour somewhere. I.e., the time I read is 1 hour behind the time I write. I suspect that I need to set up daylight saving somewhere. I put together a small program that prints time to a std::stringstream and reads it back.

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

#include <chrono>
#include <ctime>

using std::chrono::system_clock;
namespace chrono = std::chrono;

void test();

int main(int argc, char** argv)
{
    std::stringstream ss;

    auto start = system_clock::now();

    std::time_t ts = system_clock::to_time_t(start);

    std::tm time_out = *std::localtime(&ts);
    ss << std::put_time(&time_out, "%Y-%m-%d %H:%M:%S %Z") << '\n';

    std::cout << ss.str() << std::endl;

    std::tm time_in;
    ss >> std::get_time(&time_in, "%Y-%m-%d %H:%M:%S %Z");

    std::cout << "Are time dsts equal? : " <<
    (time_out.tm_isdst == time_in.tm_isdst) << '\n';

    std::time_t rawTime = std::mktime(&time_in);
    auto end = std::chrono::system_clock::from_time_t(rawTime);

    std::cout << "Are time points equal? : " << (start == end) << '\n';

    // print the trouble makers
    std::time_t start_time = system_clock::to_time_t(start);
    std::time_t end_time = system_clock::to_time_t(end);

    std::cout << "times: \n"
    << '\t' << std::put_time(std::localtime(&start_time), "%c %z") << '\n'
    << '\t' << std::put_time(std::localtime(&end_time), "%c %z") << '\n';

    // this is a source of strange behaviour...
//    std::cout << "Difference: "
//    << chrono::duration_cast<chrono::seconds>(start - end).count()
//    << std::endl;

    return 0;
}

The strangest thing is that the program prints the following:

Are time dsts equal? : 1
Are time points equal? : 0
times: 
Tue Dec 11 19:26:24 2012 +0000
Tue Dec 11 19:26:24 2012 +0000

And when I uncomment the 3 lines at the end of the program (printing the difference between the time points) the result is:

Are time dsts equal? : 0
Are time points equal? : 0
times: 
Tue Dec 11 19:29:40 2012 +0000
Tue Dec 11 18:29:40 2012 +0000
Difference: 3600

Notice that dst(daylight saving time) is suddenly not equal and neither are the times.

I am using libc++ on Mac OS X 10.8.2 with XCode46-DP2. The clang++ versions I am using are Apple clang version 4.1 and clang version 3.2 (trunk 167239)

I guess my questions are: A) As to the 1 hour difference, is this a bug in my library or am I not using the standard functions correctly? (The latter would not surprise me...)

B) What is going on with the code when I uncomment the three lines at the end of my program? This looks like a bug to me. Anyone care to try it on their platform?

Upvotes: 4

Views: 745

Answers (1)

Howard Hinnant
Howard Hinnant

Reputation: 218890

I think we're looking at a bug with the %Z specifier, and maybe with the %z specifier as well, not sure yet.

I will look into the cause of these bugs more. However I wanted to go ahead and post to get you a workaround. I believe if you zero-initialize your input tm, and always assume it is with respect to your local timezone, then you will eliminate your errors:

std::tm time_in{0};

Upvotes: 1

Related Questions