2010-05-15 11 views
5

Sto scrivendo una sorta di proxy HTTP, quindi ho bisogno di essere in grado di fare 3 cose:Usa aumentare date_time per analizzare e creare HTTP date

  1. analizzare un HTTP-data indicata una delle 3 formati specificati in RFC 2616, sec 3.3,
  2. Convertire una data del file in una stringa di data HTTP e
  3. Emettere la data in una stringa.

Per riferimento, le tesi sono esempi delle date che devo analizzare. Mi sarà in uscita solo il primo formato:

Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 
    Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 
    Sun Nov 6 08:49:37 1994  ; ANSI C's asctime() format 

Sono abbastanza sicuro Boost date_time posso fare tutto questo, ma sto avendo qualche problema con il numero 1. Qualcuno ha già il codice per fare questo? Forse non sto usando google con competenza, ma non riesco a trovare un esempio di come farlo con boost ovunque.

Grazie per qualsiasi aiuto!

AGGIORNAMENTO: Ho una soluzione, ma il secondo parser ha l'anno sbagliato (credo perché è un anno a 2 cifre) e l'ultimo parser fornisce un'eccezione (vedere l'output di seguito).

try 
{ 
    // output time now in GMT 
    // format we want: Sun, 06 Nov 1994 08:49:37 GMT 
    boost::local_time::local_date_time t(boost::local_time::local_sec_clock::local_time(boost::local_time::time_zone_ptr())); 
    boost::local_time::local_time_facet* lf(new boost::local_time::local_time_facet("%a, %d %b %Y %H:%M:%S GMT")); 
    std::cout.imbue(std::locale(std::cout.getloc(), lf)); 
    std::cout << t << std::endl; 

    // get a file mod time into the correct format 
    boost::filesystem::path p("../code/main.cpp"); 
    boost::posix_time::ptime pt = boost::posix_time::from_time_t(
    boost::filesystem::last_write_time(p)); 
    boost::local_time::local_date_time t2(pt, boost::local_time::time_zone_ptr()); 
    std::cout << t2 << std::endl; 

    std::stringstream ss; 
    ss.exceptions(std::ios_base::failbit); 

    // input date-time 
    boost::local_time::local_time_input_facet* lif1(new boost::local_time::local_time_input_facet("%a, %d %b %Y %H:%M:%S GMT")); 
    ss.imbue(std::locale(std::locale::classic(), lif1)); 
    ss.str("Sun, 06 Nov 1994 08:49:37 GMT"); 
    ss >> t; 
    std::cout << t << std::endl; 

    boost::local_time::local_time_input_facet* lif2(new boost::local_time::local_time_input_facet("%A, %d-%b-%y %H:%M:%S GMT")); 
    ss.imbue(std::locale(std::locale::classic(), lif2)); 
    ss.str("Sunday, 06-Nov-94 08:49:37 GMT"); 
    ss >> t; 
    std::cout << t << std::endl; 

    boost::local_time::local_time_input_facet* lif3(new boost::local_time::local_time_input_facet("%a %b %e %H:%M:%S %Y")); 
    ss.imbue(std::locale(std::locale::classic(), lif3)); 
    ss.str("Sun Nov 6 08:49:37 1994"); 
    ss >> t; 
    std::cout << t << std::endl; 
} 
catch (std::exception& e) 
{ 
    std::cout << "Exception: " << e.what() << std::endl; 
} 

uscita:

Sat, 15 May 2010 03:01:13 GMT 
Sat, 15 May 2010 03:01:01 GMT 
Sun, 06 Nov 1994 08:49:37 GMT 
Sat, 06 Nov 2094 08:49:37 GMT 
Exception: Parse failed. No match found for '' 
+1

è necessario includere sempre le intestazioni nella parte superiore del codice. questo è così che le persone possono prendere il tuo codice e compilarlo. –

risposta

4

Ecco la classe DateTime creo che fa quello che mi serviva. Forse qualcun altro lo userà. Questo codice è di dominio pubblico. Accolgo con favore qualsiasi commento.

A proposito, apparentemente std :: locale prende un puntatore a un facet e quindi lo elimina quando viene eseguito con esso, quindi non è necessario eliminarlo (infatti, eliminarlo interrompe le cose).

datetime.h:

// $Id$ 

#ifndef _DATETIME_H_ 
#define _DATETIME_H_ 

#include <string> 
#include "common.h" 
#include <boost/date_time/local_time/local_time.hpp> 

class DateTime 
{ 
public: 
    DateTime(); 
    DateTime(const std::string& path); 

    // return datetime string 
    std::string str(); 

    // update datetime from file mod date 
    std::string from_file(const std::string& path); 

    // parse datetime string 
    void parse(const std::string& dt); 

    // boolean equal operator 
    friend bool operator==(const DateTime& left, const DateTime& right); 

private: 
    boost::local_time::local_date_time m_dt; 
}; 

#endif // _DATETIME_H_ 

datetime.cpp:

// $Id$ 

#include <sstream> 
#include "common.h" 
#include <boost/date_time.hpp> 
#include <boost/date_time/local_time/local_time.hpp> 
#include <boost/date_time/posix_time/posix_time.hpp> 
#include <boost/filesystem/operations.hpp> 
#include "datetime.h" 

DateTime::DateTime() 
:m_dt(boost::local_time::local_sec_clock::local_time(boost::local_time::time_zone_ptr())) 
{ 
} 

DateTime::DateTime(const std::string& path) 
:m_dt(boost::local_time::local_sec_clock::local_time(boost::local_time::time_zone_ptr())) 
{ 
    from_file(path); 
} 

std::string DateTime::str() 
{ 
    std::string result; 
    boost::local_time::local_time_facet* lf(new boost::local_time::local_time_facet("%a, %d %b %Y %H:%M:%S GMT")); 
    try 
    { 
    std::stringstream ss; 
    ss.imbue(std::locale(ss.getloc(), lf)); 
    ss << m_dt; 
    result = ss.str(); 
    } 
    catch (std::exception& e) 
    { 
    std::cout << "Exception: " << e.what() << std::endl; 
    } 
    return result; 
} 

std::string DateTime::from_file(const std::string& path) 
{ 
    try 
    { 
    boost::filesystem::path p(path); 
    boost::posix_time::ptime pt = boost::posix_time::from_time_t(
     boost::filesystem::last_write_time(p)); 
    m_dt = boost::local_time::local_date_time(pt, boost::local_time::time_zone_ptr()); 
    } 
    catch (std::exception& e) 
    { 
    std::cout << "Exception: " << e.what() << std::endl; 
    } 
    return str(); 
} 

void DateTime::parse(const std::string& dt) 
{ 
    boost::local_time::local_time_input_facet* lif(new boost::local_time::local_time_input_facet("%a, %d %b %Y %H:%M:%S GMT")); 
    std::stringstream ss(dt); 
    ss.imbue(std::locale(std::locale::classic(), lif)); 
    ss >> m_dt; 
} 

bool operator==(const DateTime& left, const DateTime& right) 
{ 
    return (left.m_dt == right.m_dt); 
} 
6

Non credo che avete bisogno di andare così lontano e per raggiungere il Boost :) Si può ottenere via con il semplice codice C:

static const char format[] = "%a, %d %b %Y %H:%M:%S %Z"; // rfc 1123 
struct tm tm; 
bzero(&tm, sizeof(tm)); 
if (strptime(str, format, &tm)) {..} 
+3

-1: questo non funziona su Windows. time.h non ha 'strptime()'. Inoltre, usando C invece di Boost? Neanche a me piace. –

Problemi correlati