2012-03-01 19 views
8

estoy tratando de convertir un std::string a un boost::gregorian::date así:¿Cómo convierto un std :: string a un boost :: gregorian :: date?

using namespace boost::gregorian; 

std::string str = "1 Mar 2012"; 
std::stringstream ss(str); 
date_input_facet *df = new date_input_facet("%e %b %Y"); 
ss.imbue(std::locale(ss.getloc(), df)); 
date d; 

ss >> d; //conversion fails to not-a-date-time 

std::cout << "'" << d << "'" << std::endl; //'not-a-date-time' 

Pero si la cadena contiene "01 mar 2012", la conversión tiene éxito.

¿Cómo puedo convertir cadenas como "1 mar 2012" al equivalente boost::gregorian::date?

Respuesta

10

Esto parece ser un problema con el uso de %e en su faceta de entrada.

El Boost.Gregorian documentation especifica que:

% d           día del mes como decimal 01 a 31

% e #       Como% d, el día del mes como un número decimal, pero un cero inicial se reemplaza por un espacio

El problema es que si nos fijamos en la parte superior de la documentación, se dará cuenta esta advertencia:

Las banderas marcados con un signo de almohadilla (#) son implementados por configuración regional del sistema y se sabe que falta en algunas plataformas

que he probado los siguientes casos:

input_string = " 1" 
date_format = "%e" 
result = failed 

input_string = "01" 
date_format = "%e" 
result = success 

input_string = "2000 Mar 1" 
date_format = "%Y %b %e" 
result = failed 

input_string = "2000 Mar 1" 
date_format = "%Y %b %e" 
result = success 

input_string = "2000 Mar 01" 
date_format = "%Y %b %e" 
result = success 

parece por lo tanto que se trata de una limitación de la aplicación Boost (o, al menos, el hecho de que se basa en una configuración regional específica para el análisis de %e): el análisis falla cuando %e es el primer elemento en la cadena de entrada, y se utiliza un espacio en lugar de un 0 principal.

Mi (ciega) suposición sería que el problema proviene de la tendencia de stringstream a saltear espacios en blanco. Intenté encontrar una solución con el std::noskipws, sin embargo, no pude encontrar algo que funcionara.

Como solución alternativa, recomendaría agregar un cero a la izquierda o, si es posible, usar un formato de fecha diferente.

Otra solución alternativa sería agregar manualmente el espacio e invertir el orden de las "palabras" en la cadena. He logrado una solución de trabajo de la siguiente manera:

#include "boost/date_time/gregorian/gregorian.hpp" 
#include <iostream> 
#include <string> 

int main(void) { 
    using namespace boost::gregorian; 

    std::string input_date("1 Mar 2000"); 

    { // local scope to remove temporary variables as soon as possible 
     std::stringstream tmp_ss(input_date); 
     std::string tmp; 
     input_date.clear(); // empty the initial string 
     while (tmp_ss >> tmp) { 
      input_date.insert(0, tmp); // insert word at beginning of string 
      if(tmp.size() == 1) // if word is one char long, add extra space 
       input_date.insert(0, " "); 
      input_date.insert(0, " "); // add space to separate words 
     } 
    } 

    std::stringstream ss(input_date); 

    // The order of the date is reversed. 
    date_input_facet *df = new date_input_facet("%Y %b %e"); 
    ss.imbue(std::locale(ss.getloc(), df)); 

    date d; //conversion works 

    ss >> d; 

    std::cout << "'" << d << "'" << std::endl; // ouputs date correctly. 

    return 0; 
}  

Buena suerte,

Cuestiones relacionadas