2010-08-04 15 views
5

Estoy escribiendo una aplicación de C++ que tiene que analizar una cadena de fecha y hora y dar la hora de época. Sin embargo, el formato de la cadena de fecha/hora puede haber más de una (en realidad decir 25 formatos) comoAnálisis de fecha/hora en C++ (Cualquier cadena de formato a Epoch)

"EEE, dd MMM yyyy HH:mm:ss '('ZZZ')'", 
    "EEE, dd MMM yyyy HH:mm:ss '\"'ZZZ'\"'", 
    "EEE, dd MMM yyyy hh:mm:ss z", 
    "EEE, dd MMM yyyy HH:mm Z", 
    "EEE, dd MMM yyyy HH:mm:ss", 
    "EEE, MMM dd, yyyy 'at' HH:mm:ss z", 
    "EEE M/dd/yyyy hh:mm:ss a", 
    "EEE MMM dd HH:mm:ss z yyyy", 
    "EEE MMM dd hh:mm:ss yyyy", 
    "EEEE, MMMM dd, yyyy hh:mm:ss a", 
    "EEEE, MMMM dd, yyyy HH:mm a", 
    "EEEE, MMMM dd, yyyy HH:mm", 
    "MMM dd, yyyy hh:mm:ss a", 
    "dd MMM yyyy hh:mm:ss z", 
    "dd-MMM-yyyy HH:mm:ss z", 
    "dd MMM yy HH:mm:ss", 
    "MM/dd/yyyy hh:mm a (EEEE)", 
    "MM/dd/yyyy hh:mm a (EEEE)", 
    "MM/dd/yyyy hh:mm:ss", 
    "MM/dd/yyyy hh:mm a Z", 
    "MM/dd/yyyy hh:mma Z", 
    "MM/dd/yyyy hh:mma", 
    "MM/dd/yyyy hh:mm a", 
    "MM/dd/yyyy hh:mm Z", 
    "MM/dd/yy hh:mm a Z", 
    "MM/dd/yy hh:mma Z", 
    "MM/dd/yy HH:mm a", 
    "MM/dd/yy HH:mm Z", 
    "MM/dd/yyyy", 
    "yyyy-MM-dd HH:mm:ss", 
    "yyyyMMddhhmmss", 
    "yyyyMMddhhmm", 
    "yyyyMMdd" 

Ahora, necesito tomar la cadena, averiguar que pertenece a cada uno de estos formatos, a continuación, obtener el tiempo en la epoca

¿Puede sugerir una manera de hacerlo? Las muestras de código serán realmente útiles. Cuento con las bibliotecas de Boost. Avíseme si esto se puede lograr aumentando las bibliotecas de análisis de fecha/hora.

Gracias de antemano, AJ

Respuesta

13

supongo que se podría tratar de convertir su cadena en ptime utilizando cada uno de estos formatos y escoger los que no dan lugar a una not_a_date_time:.

El boost format flags son ligeramente diferente a la tuya, haré solo las últimas cinco para este ejemplo:

#include <iostream> 
#include <boost/date_time/posix_time/posix_time.hpp> 
using boost::posix_time::time_input_facet; 
using std::locale; 
const locale inputs[] = { 
    locale(locale::classic(), new time_input_facet("%m/%d/%Y")), 
    locale(locale::classic(), new time_input_facet("%Y-%m-%d %H:%M:%S")), 
    locale(locale::classic(), new time_input_facet("%Y%m%d%H%M%S")), 
    locale(locale::classic(), new time_input_facet("%Y%m%d%H%M")), 
    locale(locale::classic(), new time_input_facet("%Y%m%d")) }; 
const size_t formats = sizeof(inputs)/sizeof(inputs[0]); 

time_t ptime_to_time_t(boost::posix_time::ptime t) 
{ 
     static boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1)); 
     return (t-epoch).ticks()/boost::posix_time::time_duration::ticks_per_second(); 
} 
int main() 
{ 
     std::string msg = "2010-08-04 08:34:12"; 

     for(size_t i=0; i<formats; ++i) 
     { 
      std::istringstream ss(msg); 
      ss.imbue(inputs[i]); 
      boost::posix_time::ptime this_time; 
      ss >> this_time; 

      if(this_time != boost::posix_time::not_a_date_time) 
       std::cout << this_time << " or " << ptime_to_time_t(this_time) << std::endl; 
     } 
} 
+0

Gracias a cubbi por tomar tanto tiempo, intentaré esto y volveré. – AMM

+1

Ahora, parece que% d y% m tienen que tener 2 caracteres, es decir, tiene que ser como 01 en lugar de 1 y 05 en lugar de 5. ¿Cómo puedo manejar ese caso? Esto parece estar causando un problema para mí. Al mirar las banderas de formato no se pudo averiguar mucho. – AMM

+3

Si sus días y meses pueden ser de un solo dígito, sin cero o espacio anterior, algunos de estos formatos no se pueden analizar sin ambigüedad. Para 'yyyyMMdd', ¿2010111 sería 2010-01-11 o 2010-11-01? En cualquier caso, si hay algo que date_time IO no puede manejar, siempre hay boost.spirit. – Cubbi