Bad
Bad

Reputation: 5299

c++ parse datetime from string with different timezone

How to parse datetime from string which is in different timezone? I have dates and times in simple strings like 2011-01-15 04:01:00, which are from New York timezone (Eastern: UTC -5/-4). I wrote the code below, but it automatically converts timezone to my local timezone.

Is it possible to do it without any additional C++ 11 libraries like Boost so as not to add complexity to a very simple operation? If not, an example with Boost would be nice.

I use Visual Studio 2013 on Windows 8.1.

#include <ctime>
#include <string>
#include <sstream>
#include <vector>
#include <iomanip>
#include <iostream>
using namespace std;

int main()
{
    vector<string> datetimes{ "2011-01-15 04:01:00",
                              "2014-06-07 23:17:00",
                              "2015-11-29 14:55:00" };

    for (auto i : datetimes)
    {
        stringstream ss1(i);
        tm tm;
        ss1 >> get_time(&tm, "%Y-%m-%d %H:%M:%S");
        stringstream ss2;
        ss2 << put_time(&tm, "%c %Z");
        cout << ss2.str() << endl;
    }
}

Output:

01/15/11 04:01:00 Russia TZ 2 Daylight Time
06/07/14 23:17:00 Russia TZ 2 Daylight Time
11/29/15 14:55:00 Russia TZ 2 Daylight Time

But I need the output to be like:

01/15/11 04:01:00 New York / Eastern (or whatever right name)
06/07/14 23:17:00 New York
11/29/15 14:55:00 New York

Upvotes: 2

Views: 2320

Answers (2)

Howard Hinnant
Howard Hinnant

Reputation: 218900

Here is your program using Howard Hinnant's timezone library (free, open-source, will run with VS-2013, does require some installation).

#include "tz.h"
#include <string>
#include <sstream>
#include <vector>
#include <iostream>

int main()
{
    using namespace std;
    using namespace date;
    vector<string> datetimes{ "2011-01-15 04:01:00",
                              "2014-06-07 23:17:00",
                              "2015-11-29 14:55:00" };

    zoned_seconds zt("America/New_York");
    for (auto const& i : datetimes)
    {
        stringstream ss1(i);
        local_seconds tm;
        ss1 >> parse("%F %T", tm);
        zt = tm;
        stringstream ss2;
        ss2 << format("%D %T %Z", zt);
        cout << ss2.str() << endl;
    }
}

Output:

01/15/11 04:01:00 EST
06/07/14 23:17:00 EDT
11/29/15 14:55:00 EST

Upvotes: 2

Nir Friedman
Nir Friedman

Reputation: 17694

Just use boost for this. Seriously. Here is what some sample code looks like for this:

using namespace boost::posix_time;
using namespace boost::gregorian;

//eastern timezone is utc-5
typedef boost::date_time::local_adjustor<ptime, -5, us_dst> us_eastern;

ptime t1(date(2001,Dec,31), hours(19)); //5 hours b/f midnight NY time

ptime t2 =  us_eastern::local_to_utc(t1); // t2 is now in utc

std::cout << to_simple_string(t1) << " in New York is " 
          << to_simple_string(t2) << " UTC time "
          << std::endl

Sample code taken from http://www.boost.org/doc/libs/1_42_0/doc/html/date_time/examples.html and adjusted for readability and brevity, while still answering the question.

Whatever solution you do come to, make sure you are never subtracting by hand for timezone conversions, or anything like that. At some level, you need to use a library. This stuff is full of pitfalls, and very complicated, so forgetting even how much work is or isn't involved, if you do it on your own it almost certainly won't be right.

Upvotes: 2

Related Questions