Как отформатировать объект boost::date_time в соответствии с RFC 3339

Я хочу использовать библиотеку date_time в boost для представления времени в моем приложении. Это приложение будет генерировать фиды Atom, которые, в свою очередь, требуют отметок времени в формате, указанном в RFC 3339, например "1990-12-31T23:59:60Z" или "1990-12-31T15:59:60-08:00".

Итак, как мне отформатировать время в соответствии с этим RFC?

Я прочитал документацию по вводу/выводу даты и времени весь день, и я не могу понять, как поставить Z в конце, когда мне это нужно. Кроме того, RFC поддерживает необязательную долю секунды, но только одну ее цифру (например, «1990-12-31T23:59:60.5Z») (*). Я тоже не могу понять, как это сделать.

Я всегда мог бы написать свою собственную процедуру форматирования, которая считывает различные необходимые поля, но мне кажется, что это работает против сути библиотеки date_time.

Есть ли опыт написания средств форматирования для этой библиотеки? Или я делаю не так?

(*): Мне кажется, что ABNF, приведенный в RFC, допускает только однозначные дробные секунды, но примеры в том же RFC имеют двузначные дробные секунды. Что это должно значить?


person Magnus Hoff    schedule 29.01.2009    source источник
comment
вы пробовали это с помощью фасетов? они кажутся довольно мощными и могут делать то, что вы хотите (я не знаю). посмотрите здесь: stackoverflow.com/questions/327673/   -  person Johannes Schaub - litb    schedule 29.01.2009
comment
Да, я использую фасеты. И я хочу использовать фасеты. Но мне они кажутся недостаточно мощными. Но, как вы говорите, я не знаю :)   -  person Magnus Hoff    schedule 29.01.2009


Ответы (1)


  1. ABNF из RFC говорит, что после точки должна быть хотя бы одна цифра, максимум не определен.

  2. Нет реальной необходимости в Z, вместо этого вы можете использовать 00:00, и это возможно с фасетами.

  3. В некоторых редких случаях date_time будет генерировать "Z". См. снимок кода из boost (local_date_time.hpp), который предполагает, что это ниже:


    std::string zone_name(bool as_offset=false) const
    {
      if(zone_ == boost::shared_ptr()) {
        if(as_offset) {
          return std::string("Z");
        }
        else {
          return std::string("Coordinated Universal Time");
        }
    ...

Аналогично, если в функции zone_abbrev...

И пример использования этого

slimak@daradei:~/store/kodowanie/moje/test$ cat boost_date_time.cpp
#include "boost/date_time.hpp"
#include "boost/date_time/local_time/local_time.hpp"

using namespace boost::posix_time;
using namespace boost::local_time;

int main()
{
        local_date_time t = local_sec_clock::local_time(time_zone_ptr());
        local_time_facet* lf(new local_time_facet("%Y-%m-%dT%H:%M:%S%F%Q"));
        std::cout.imbue(std::locale(std::cout.getloc(), lf));
        std::cout << t << std::endl;
        return 0;
}
slimak@daradei:~/store/kodowanie/moje/test$ g++ boost_date_time.cpp && ./a.out
2009-01-30T12:15:56Z
slimak@daradei:~/store/kodowanie/moje/test$

person Slimak    schedule 30.01.2009
comment
Ах. Спасибо. Хороший. Я никогда не понимал, что такое часовой пояс. Может быть, мне стоит попытаться изучить библиотеку сначала? :) - person Magnus Hoff; 30.01.2009
comment
Кстати, вы можете использовать time_zone_ptr-typedef, а не boost::shared_ptr<posix_time_zone>. - person Magnus Hoff; 30.01.2009
comment
Птр поправил. Кстати, я не использую эту библиотеку в настоящее время --- я рассматривал возможность перехода на нее с даты и времени wxWidgets, которые использовались в одном проекте некоторое время назад, и, кстати, немного изучил ее. А освежить память было приятной паузой во время подготовки плана тестирования :). - person Slimak; 31.01.2009
comment
фасеты очень медленные и должны использоваться только один раз в голубую луну - если вообще. - person ; 19.01.2011