2010-05-15 4 views
5

Я пишу своего рода HTTP-прокси, так что мне нужно, чтобы быть в состоянии сделать 3 вещи:Использование повышения date_time для разбора и создания HTTP-даты

  1. разбора HTTP-дата получая любой из 3 форматы, указанные в RFC 2616, sec 3.3,
  2. Преобразование даты даты файла в строку HTTP-даты и
  3. Вывести дату в строку.

Для справки, тезисы являются примерами даты-времени, которые мне нужны для синтаксического анализа. Я буду выводить только первый формат:

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 

Я уверен, что подталкивания date_time может сделать все это, но у меня возникают некоторые проблемы с номером 1. Кто-нибудь уже есть код, чтобы сделать это? Возможно, я не использую google профессионально, но я не могу найти пример того, как это сделать с повышением в любом месте.

Спасибо за помощь!

UPDATE: У меня есть решение, но у второго парсера есть неправильный год (я думаю, потому что это 2-значный год), а последний синтаксический анализатор дает исключение (см. Вывод ниже).

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; 
} 

Выход:

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

Вы всегда должны включать заголовки в верхней части кода. это значит, что люди могут поднять ваш код и скомпилировать его. –

ответ

4

Вот класс DateTime я создаю, что делает то, что мне было нужно. Может быть, кто-то другой будет его использовать. Этот код является общедоступным. Я приветствую любые комментарии.

Кстати, по-видимому, std :: locale берет указатель на грань, а затем удаляет его, когда это делается с ним, поэтому нет необходимости его удалять (на самом деле удаление его ломает вещи).

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

Я не думаю, что вам нужно пойти так далеко и достичь подпиточного :) Вы можете уйти с простым кодом 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: Это не работает в Windows. time.h не имеет 'strptime()'. Также, используя C вместо Boost? Мне тоже это не нравится. –