考虑这是this question的后续行动。从本质上讲,C ++日期/时间格式化设施似乎无可救药地被打破 - 以至于为了做一些简单的事情,如将日期/时间字符串转换为对象,你真的不得不求助于Boost.Datetime或者旧的C strftime
/ strptime
设施。
问题是这些解决方案都不能直接使用嵌入特定iostream对象的C ++语言环境设置。 C工具使用全局C / POSIX语言环境设置,而Boost.Datetime中的I / O工具似乎完全绕过iostream语言环境设置,允许用户直接设置月份,工作日等的名称,而不管语言环境如何。
所以,我想要一些能够尊重特定I / O流上的语言环境设置的东西,这些设置允许我将字符串转换为struct tm
。这似乎很容易,但我遇到了各个角落的障碍。起初,我注意到STL的一些实现提供了非标准的std::time_get::get
函数,所以我决定实现类似的东西。基本上,我只是迭代格式字符串,每当我点击格式标志时,我会使用time_get工具之一(如get_monthname,get_weekday,get_year等)将输入字符串转换为struct tm
。这似乎很容易,除了这些函数中的每一个都需要精确的迭代器范围。您无法转换"Monday,"
,它必须完全为"Monday"
,否则转换将失败。由于迭代器必须是istreambuf_iterator
,因此您不能简单地向前扫描,因为每个增量都会更改流缓冲区中的获取位置。所以,基本上你必须首先迭代流,将每个字符复制到另一个 streambuffer,然后当你点击分隔符(如空格或逗号)时,使用第二个streambuffer和time_get工具。实际上,就好像C ++设计师竭尽全力使其尽可能烦人一样。
那么,有更简单的解决方案吗?大多数C ++程序员在需要将日期/时间字符串转换为对象时会做什么?我们是否只需要使用C设施,并且失去了在不同的iostream对象上出现的不同语言环境设置带来的好处?
答案 0 :(得分:2)
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
答案 1 :(得分:0)
为什么不使用C
库?它几乎可以在您的实现中使用,并且经过了很好的调试和测试。
如果它缺少某些功能,那么制作包装功能肯定会更容易,这会使你想要的时区工作。
答案 2 :(得分:0)
我总是尝试使用与语言环境无关的字符串来序列化数据。让生活更轻松。