3

I need to read time with ISO extended format, and convert it to UTC time, like Javascript's Date objects do:

new Date("2014-12-19T15:53:14.533+01:00")

2014-12-19T14:53:14.533Z

In boost, there is no boost::posix_time::from_iso_extended_string and boost::posix_time::from_iso_string does not parse time-zones. I try to use boost::local_time::local_date_time but it seems that it also do not work:

    std::stringstream ss("2014-12-19T15:53:14.533+01:00");
    boost::local_time::local_time_input_facet* 
            ifc= new boost::local_time::local_time_input_facet();
    ifc->set_iso_extended_format();
    ss.imbue(std::locale(ss.getloc(), ifc));
    boost::local_time::local_date_time 
             zonetime(boost::local_time::not_a_date_time);
    if( ss >> zonetime ) {
        time = zonetime.utc_time();
    }

Any help or suggestions?

Live on coliru

Cartier
  • 429
  • 4
  • 15
Arpegius
  • 5,817
  • 38
  • 53

1 Answers1

3

The time zone isn't parsed at all:

Live On Coliru

#include <iostream>
#include <sstream>
#include <boost/date_time.hpp>

int main()
{
    boost::posix_time::ptime time;
    try 
    {
        std::stringstream ss("2014-12-19T15:53:14.533+01:00");
        boost::local_time::local_time_input_facet* ifc= new boost::local_time::local_time_input_facet();
        ifc->set_iso_extended_format();
        ss.imbue(std::locale(ss.getloc(), ifc));
        boost::local_time::local_date_time zonetime(boost::local_time::not_a_date_time);
        if( ss >> zonetime ) {
            time = zonetime.utc_time();
        }

        std::string remains;
        if (std::getline(ss, remains))
            std::cout << "Remaining: '" << remains << "'\n";

    }
    catch( std::exception const& e )
    {
        std::cout << "ERROR:" << e.what() <<std::endl;
    }

    std::cout << "UTC time: " << time;

    return 0;  
}

Prints:

Remaining: '+01:00'
UTC time: 2014-Dec-19 15:53:14.533000

The documentation says:

At this time, local_date_time objects can only be streamed in with a Posix Time Zone string. A complete description of a Posix Time Zone string can be found in the documentation for the posix_time_zone class.

So, you'll need to either parse timezones separately or use POSIX time zones. Yes, I reckon this is very confusing and a deficiency. In effect, you cannot use extended iso format with local times.

You migth be able to use the %ZP instead:

Live On Coliru

#include <iostream>
#include <sstream>
#include <boost/date_time.hpp>

int main()
{
    boost::posix_time::ptime time;
    try 
    {
        std::stringstream ss("2014-12-19T15:53:14.533-07:00");

        boost::local_time::local_time_input_facet* ifc= new boost::local_time::local_time_input_facet("%Y-%m-%d %H:%M:%S%F %ZP");
        //ifc->set_iso_extended_format();
        ss.imbue(std::locale(ss.getloc(), ifc));

        using namespace boost::local_time;
        local_date_time ldt(not_a_date_time);

        if(ss >> ldt) {
            time = ldt.utc_time();

            std::string remains;
            if (std::getline(ss, remains))
                std::cout << "Remaining: '" << remains << "'\n";
        }

    }
    catch( std::exception const& e )
    {
        std::cout << "ERROR:" << e.what() <<std::endl;
    }

    std::cout << "UTC time: " << time;

    return 0;  
}

Prints

UTC time: 2014-Dec-19 22:53:14.533000
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks. it work. POSIX time zone are different that they have seconds, but i think nobody will ever use parts of a minutes. Please change time string to "2014-12-19T15:53:14.533-07:00", that's what I am asking. – Arpegius Jan 28 '15 at 15:01
  • @Arpegius TBH, the only reason I can see why this is simply not implemented: apparently everyone is content exchanging UTC datetimes in transit (and pass the timezone out of band if needed) – sehe Jan 28 '15 at 15:03
  • You might be right, but it is good to do more then just check for the "Z" character in string. – Arpegius Jan 28 '15 at 15:13