2010-08-04 4 views
5

Je suis en train d'écrire une application C++ qui doit analyser une chaîne de date/heure et donner du temps. Mais le format de la chaîne date/heure peut être plus d'un (dire en fait 25 formats) commeAnalyse de date/heure en C++ (n'importe quelle chaîne de format à 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" 

Maintenant, je dois prendre la chaîne, savoir qu'il appartient à qui de ces formats, puis obtenir le temps à l'époque.

Pouvez-vous suggérer un moyen de le faire. Les exemples de code seront vraiment utiles. Je compte sur les bibliothèques Boost. Faites-moi savoir si cela peut être réalisé par booster les bibliothèques d'analyse de date/heure.

Merci à l'avance, AJ

Répondre

13

Je suppose que vous pourriez essayer de convertir votre chaîne en ptime en utilisant chacun de ces formats et de choisir ceux qui ne donnent pas lieu à un not_a_date_time.

Les boost format flags sont légèrement différent de la vôtre, je ferai juste les cinq derniers pour cet exemple:

#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

Merci Cubbi pour prendre tellement de temps, je vais essayer cela et revenir. – AMM

+1

Maintenant, il semble que% d et% m doivent avoir 2 caractères, c'est-à-dire que ça doit être comme 01 au lieu de 1 et 05 au lieu de 5. Comment puis-je gérer ce cas. Cela semble causer un problème pour moi. Regardé les drapeaux de format n'a pas pu comprendre beaucoup. – AMM

+3

Si vos jours et vos mois peuvent être à un seul chiffre, sans zéro ni espace, certains de ces formats ne peuvent pas être analysés sans ambiguïté. Pour «aaaaMMdj», 2010111 serait-il 2010-01-11 ou 2010-11-01? Dans tous les cas, s'il y a quelque chose que date_time IO ne peut pas gérer, il y a toujours boost.spirit. – Cubbi