2015-12-19 2 views
1

Есть некоторая проблема с синтаксисом datetime, что я понятия не имею о большом обходном пути.boost date parse 29FEB

Рассмотрим следующий код:

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

namespace dt = boost::gregorian; 

dt::date parse_date(const std::string& msg, const std::string& format) 
{ 
    std::stringstream s(msg); 
    dt::date_input_facet * f = new dt::date_input_facet(); 
    if (format.empty()) 
    { 
     f->set_iso_format(); 
    } 
    else 
    { 
     f->format(format.c_str()); 
    } 
    std::locale l(std::locale(), f); 
    s.imbue(l); 
    dt::date result; 
    s >> result; 
    return result; 
} 

int main() 
{ 
    const std::string v = "0229"; 
    auto p = parse_date(v, "%m%d"); 
    std::cout << p << std::endl; 
} 

Live example

Проблема в том, что год по умолчанию в даты и времени парсера 1400, что не високосный, так что не 29 февраля в этом году. Главный вопрос, конечно, почему 1400 год по умолчанию, а не какой-либо високосный год, в любом случае мне нужно какое-то хорошее обходное решение, любые идеи?

ответ

3

Я думаю, что вопрос «почему» не имеет особого отношения¹. Это так, как это работает. Ключ в том, что вы знаете, что мешает вам разобрать его.

Я просто сделаю легкую вещь, ниже, или just write a tiny spirit parser (int_parser<unsigned char, 10, 2, 2> twice) и построю ptime напрямую).

Live On Coliru

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

namespace dt = boost::gregorian; 

dt::date parse_date_mmdd(const std::string &msg) { 
    std::stringstream s("2000" + msg); 
    dt::date_input_facet *f = new dt::date_input_facet(); 
    f->format("%Y%m%d"); 

    std::locale l(std::locale(), f); 
    s.imbue(l); 
    dt::date result; 
    s >> result; 

    return result; 
} 

int main() { 
    const std::string v = "0229"; 
    auto p = parse_date_mmdd(v); 
    std::cout << p << std::endl; 
} 

Печать

2000-Feb-29 

¹ Ответ скорее сосредотачивается на "нет типа данных, связанных с DayOfYear" как DayOfMonth кортеж (для это в библиотеке обработки дат). Таким образом, вам всегда нужно будет выбрать контекстный год. Как и вы всегда должны решить, в какой временной зоне нужно интерпретировать время встречи. Или даже какую модель календаря использовать.

+1

Существует partial_date, но, к сожалению, он не соблюдает строчную строку, которую он использует. Если «2902» вместо «0229» будет работать, он может использовать [это] (http://coliru.stacked-crooked.com/a/8c53d94f3c5e1f44). – llonesmiz

+1

Хорошая находка, @cv_and_he. Интересно, насколько полезен «partial_date» для других задач (будет выглядеть в один прекрасный день). Вот [версия X3] (http://coliru.stacked-crooked.com/a/752c3ab1fdd5b4e3) для полноты – sehe

+0

Интересно. Конечно, у меня есть идея просто добавить год, но мне это не нравится, но, наверное, это лучше. И это очень интересное решение, используя partial_date. – ForEveR