【发布时间】:2012-12-15 11:47:52
【问题描述】:
我想将int 日期转换为:
20111201
致string:
2011 年 12 月 1 日
C++ 中是否有内置的快速日期格式转换(或者我可以执行的 bash 系统命令)来执行此操作,或者我是否在所有月份都无法进行切换?
【问题讨论】:
标签: c++ date format data-conversion
我想将int 日期转换为:
20111201
致string:
2011 年 12 月 1 日
C++ 中是否有内置的快速日期格式转换(或者我可以执行的 bash 系统命令)来执行此操作,或者我是否在所有月份都无法进行切换?
【问题讨论】:
标签: c++ date format data-conversion
您可以使用 strptime 将字符串转换为 struct tm,然后使用 strftime 重新格式化:
#include <ctime>
#include <iostream>
#include <sstream>
int main()
{
std::ostringstream date1;
date1 << 20111201;
struct tm tm;
strptime(date1.str().c_str(), "%Y%m%d", &tm);
char date2[10];
strftime(date2, sizeof(date2), "%d%b%Y", &tm);
std::cout << date1.str() << " -> " << date2 << std::endl;
}
输出是:
20111201 -> 01Dec2011
如果需要,只需将 Dec 转换为大写即可。
【讨论】:
strptime 不是标准函数。
man strptime 声称“符合 SUSv2,POSIX.1-2001”,并且问题指定使用 bash 作为解决方案运行系统命令,所以...
不要在这里使用 bash。可行的方法是在 C++ 中使用 Boost 的原因比我在这里列出的时间要多,但最终它将与您遇到的大多数其他解决方案一样快,除非您的功能绝对是时间关键的,否则它不会反正不会有很大的不同。
此外,它比您经常遇到的那些糟糕的、硬编码的小日期转换例程更加灵活和可维护。
下面的代码会做你想做的事。
#include <iostream>
#include <sstream>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <boost/algorithm/string.hpp>
using namespace boost::gregorian;
using namespace std;
int main(int argc, char **argv)
{
int dateIn = 20111201;
// Read the date in from ISO format as an int.
ostringstream ss;
ss << dateIn;
date d(from_undelimited_string( ss.str() ));
// Set the output format
date_facet *fct = new date_facet("%d%b%Y"); // [1]
locale loc = locale(locale::classic(), fct);
// Render the date as a string;
ss.str("");
ss.imbue(loc);
ss << d;
string dateOut( ss.str() );
boost::to_upper( dateOut );
cout << dateOut << endl;
}
这给出了以下输出:
01DEC2011
只需在 ref [1] 处更改格式字符串 "%d%b%Y" 将更改为不同的输出格式,但请记住我也已将其转换为大写。
【讨论】:
没有直接内置的,因为这种日期格式
比较少见。这里最简单的解决方案是
使用% 和/ 将日期分解为年月日
运算符(例如月份是value / 100 % 100),然后格式化
通常使用三个值,使用std::ostream,并查找
表中的日期。 (这显然需要一些错误
检查,因为并非所有整数值都会产生有效日期。)
【讨论】:
旧问题的新答案。此答案通过 C++11/14 <chrono> 库而不是 C 的 tm 或 boost::date_time 传输。否则,它与现有答案非常相似。它需要这个free, open-source library 进行解析和格式化。
#include "tz.h"
#include <iostream>
#include <locale>
#include <sstream>
int
main()
{
auto date1 = 20111201;
std::stringstream stream;
stream.exceptions(std::ios::failbit);
stream << date1;
std::chrono::system_clock::time_point tp;
date::parse(stream, "%Y%m%d", tp);
auto str = date::format("%d%b%Y", tp);
auto& ct = std::use_facet<std::ctype<char>>(std::locale::classic());
ct.toupper(&str.front(), &str.back()+1);
std::cout << str << '\n';
}
我已包含 stream.exceptions(std::ios::failbit); 以嘈杂地检测无效的“整数日期”。我已经包含了旧的 C++98 代码来将字符串转换为大写(最后是 locale 舞蹈)。
01DEC2011
使用现代 C++ 日期/时间库的优点之一是可以轻松进行更改。例如,如果现在您需要解析时间戳而不是天精度,而是毫秒精度怎么办?以下是可能的做法:
auto date1 = 20111201093357.275L;
std::stringstream stream;
stream.exceptions(std::ios::failbit);
stream << std::fixed << date1;
std::chrono::system_clock::time_point tp;
date::parse(stream, "%Y%m%d%H%M%S", tp);
auto str = date::format("%d%b%Y %T", tp);
auto& ct = std::use_facet<std::ctype<char>>(std::locale::classic());
ct.toupper(&str.front(), &str.back()+1);
std::cout << str << '\n';
哪个输出:
01DEC2011 09:33:57.275000
或者这些时间戳可能已知来自Chatham Island off the coast of New Zealand,而您需要它们的UTC。只需在parse 后面加一行:
tp = date::locate_zone("Pacific/Chatham")->to_sys(tp);
现在输出是:
30NOV2011 19:48:57.275000
考虑到任意时区和亚秒级精度目前超出了所有其他 C++ 库的能力。
【讨论】: