如何从stringparsingdate/时间?
input :带date和可选时间的string。 不同的表示会很好,但是必要的。 这些string是用户提供的,可能会格式错误。 例子:
-
"2004-03-21 12:45:33"
(我认为这是默认布局) -
"2004/03/21 12:45:33"
(可选布局) -
"23.09.2004 04:12:21"
(德文格式,可选) -
"2003-02-11"
(时间可能会丢失)
需要输出 :自大纪元(1970/01/01 00:00:00)或其他一些固定点以来的秒数。
奖励 :另外,读取本地系统时间的UTC偏移量会很好。
input被认为是相关机器上的当地时间。 输出需要是UTC。 系统只有Linux(需要Debian Lenny和Ubuntu)。
我曾尝试使用boost/date_time
,但必须承认,我无法将头围绕在文档中。 以下工作没有从系统本地时间到UTC所需的转换:
std::string date = "2000-01-01"; boost::posix_time::ptime ptimedate = boost::posix_time::time_from_string(date); ptimedate += boost::posix_time::hours(Hardcoded_UTC_Offset);// where to get from? struct tm = boost::posix_time::to_tm(ptimedate); int64_t ticks = mktime(&mTmTime);
我认为boost::date_time
可以提供所需的UTC抵消,但我不知道如何。
虽然我不知道如何格式化一位数的月份input,但我可以在两位数的编辑之后完成:
#include <iostream> #include <boost/date_time.hpp> namespace bt = boost::posix_time; const std::locale formats[] = { std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d %H:%M:%S")), std::locale(std::locale::classic(),new bt::time_input_facet("%Y/%m/%d %H:%M:%S")), std::locale(std::locale::classic(),new bt::time_input_facet("%d.%m.%Y %H:%M:%S")), std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d"))}; const size_t formats_n = sizeof(formats)/sizeof(formats[0]); std::time_t pt_to_time_t(const bt::ptime& pt) { bt::ptime timet_start(boost::gregorian::date(1970,1,1)); bt::time_duration diff = pt - timet_start; return diff.ticks()/bt::time_duration::rep_type::ticks_per_second; } void seconds_from_epoch(const std::string& s) { bt::ptime pt; for(size_t i=0; i<formats_n; ++i) { std::istringstream is(s); is.imbue(formats[i]); is >> pt; if(pt != bt::ptime()) break; } std::cout << " ptime is " << pt << '\n'; std::cout << " seconds from epoch are " << pt_to_time_t(pt) << '\n'; } int main() { seconds_from_epoch("2004-03-21 12:45:33"); seconds_from_epoch("2004/03/21 12:45:33"); seconds_from_epoch("23.09.2004 04:12:21"); seconds_from_epoch("2003-02-11"); }
请注意,从纪元输出秒将假设date在UTC:
~ $ ./test | head -2 ptime is 2004-Mar-21 12:45:33 seconds from epoch are 1079873133 ~ $ date -d @1079873133 Sun Mar 21 07:45:33 EST 2004
你可以使用#include <boost/date_time/c_time.hpp>
boost::posix_time::c_time::localtime()
来完成这个转换,假设input在当前时区,但是它是相当不一致的:for例如,我今天和下个月夏令时结束时,结果会有所不同。
boost::gregorian
有一些你需要的东西,而不需要你做更多的工作:
using namespace boost::gregorian; { // The following date is in ISO 8601 extended format (CCYY-MM-DD) std::string s("2000-01-01"); date d(from_simple_string(s)); std::cout << to_simple_string(d) << std::endl; }
这里有一个关于如何在boost::posix_time
使用UTC偏移量的例子。
您可以使用date_input_facet
和time_input_facet
从自定义inputstring格式提供date和时间的生成。 在这个页面上有一个I / O教程,可以帮助你开始。
如果c样式是可以接受的: strptime ()是要走的路,因为您可以指定格式,并且可以考虑locale:
tm brokenTime; strptime(str.c_str(), "%Y-%m-%d %T", &brokenTime); time_t sinceEpoch = timegm(brokenTime);
不同的布局必须用返回值检查(如果可能的话)。 时区必须通过检查系统时钟(localtime_r()with time(),tm_zone)来添加,
最简单的便携式解决scheme是使用scanf
:
int year, month, day, hour, minute, second = 0; int r = 0; r = scanf ("%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second); if (r == 6) { printf ("%d-%d-%d %d:%d:%d\n", year, month, day, hour, minute, second); } else { r = scanf ("%d/%d/%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second); // and so on ...
使用int
值初始化一个struct tm
,并将其传递给mktime
以获得一个日历时间time_t
。 有关时区转换的信息 ,请参阅 gmtime
。