C ++: преобразовать строку даты / времени в структуру tm - PullRequest
5 голосов
/ 05 октября 2010

Считайте это чем-то вроде продолжения до этого вопроса . По сути, средства форматирования даты / времени в C ++ кажутся безнадежно сломанными - настолько, что для того, чтобы сделать что-то столь же простое, как преобразование строки даты / времени в объект, вам действительно нужно прибегнуть либо к Boost.Datetime, либо к старому доброму C strftime / strptime объектов.

Проблема заключается в том, что ни одно из этих решений не работает напрямую с настройками языкового стандарта C ++, вставленными в конкретный объект iostream. Средства C используют глобальные настройки языкового стандарта C / POSIX, тогда как средства ввода-вывода в Boost.Datetime, похоже, полностью игнорируют настройки языкового стандарта iostream, позволяя пользователю напрямую задавать названия месяцев, дней недели и т. Д. Независимо от языкового стандарта.

Итак, я хотел что-то, что соответствовало бы настройкам локали, вставленной в определенный поток ввода / вывода, что позволило бы мне преобразовать строку в struct tm. Это казалось достаточно легким, но я сталкивался с препятствиями на каждом углу. Сначала я заметил, что некоторые реализации STL предоставляют нестандартную функцию std::time_get::get, поэтому я решил реализовать нечто подобное. По сути, я просто перебрал бы строку формата и всякий раз, когда я нажимал на флаг формата, я использовал одно из средств time_get (например, get_monthname, get_weekday, get_year и т. Д.) Для преобразования входной строки в struct tm. Это кажется достаточно простым, за исключением того, что каждая из этих функций требует точного диапазона итератора. Вы не можете конвертировать "Monday,", это должно быть точно "Monday", иначе конвертация не удалась. Поскольку итераторы должны быть istreambuf_iterator, вы не можете просто сканировать заранее, потому что каждый шаг меняет позицию получения в буфере потока. Таким образом, в основном вы должны сначала выполнить итерацию по потоку, копируя каждый символ в другой потоковый буфер, а затем, когда вы нажимаете разделитель (например, пробел или запятую), используйте второй потоковый буфер со средствами time_get. Буквально, как будто дизайнеры C ++ старались изо всех сил сделать это настолько раздражающим, насколько это возможно.

Итак, есть ли более простое решение? Что делает большинство программистов на C ++, когда им нужно преобразовать строку даты / времени в объект? Должны ли мы просто использовать средства C и потерять преимущества, которые приходят вместе с различными настройками локали, наделенными различными объектами iostream?

Ответы [ 3 ]

2 голосов
/ 28 октября 2010

Boost использует стандартную локаль (ы) по умолчанию; вам не нужно ничего обходить:

#include "boost/date_time/gregorian/gregorian.hpp"
#include <iostream>
#include <sstream>
#include <ctime>

int main(){
  using namespace boost::gregorian;

  std::locale::global(std::locale(""));
  std::locale german("German_Germany");
  std::locale french("French_France");

  date d1(day_clock::local_day());
  date d2;
  std::stringstream ss("2002-May-01");

  std::cout << "Mine: " << d1 << " | ";
  ss >> d2;
  std::cout << d2 << '\n';

  std::cout.imbue(german);
  std::cout << "Germany: " << d1 << " | ";
  ss.imbue(german);
  ss << "2002-Mai-01";
  ss >> d2;
  std::cout << d2 << '\n';

  std::cout.imbue(french);
  std::cout << "France: " << d1 << " | " << d2 << '\n';

  std::tm t = to_tm(d1);
  std::cout << "tm: " << asctime(&t);
}

(Конечно, эти имена локалей относятся к Windows). Вывод:

Mine: 2010-Oct-28 | 2002-May-01
Germany: 2010-Okt-28 | 2002-Mai-01
France: 2010-oct.-28 | 2002-mai-01
tm: Thu Oct 28 00:00:00 2010
0 голосов
/ 12 октября 2010

Я всегда стараюсь использовать независимые от локали строки для сериализации данных. Делает жизнь намного проще.

0 голосов
/ 05 октября 2010

Почему бы не использовать библиотеку C?Он почти наверняка доступен в вашей реализации, хорошо отлажен и протестирован.

Если ему не хватает какой-либо функции, наверняка проще создать функцию-обертку, которая будет работать с нужным вам часовым поясом.

...