您必须将字符串解析为单独的时间分量,将它们转换为整数并将它们传递给适当的CTime 构造函数。
解析的方法有很多,其中一种最直接且易于维护的方法是使用regular expressions(一旦你习惯了语法):
#include <iostream>
#include <regex>
void test( std::wstring const& s, std::wregex const& r );
int main()
{
std::wregex const r{
LR"(.*?)" // any characters (none or more)
LR"((\d+))" // match[1] = day
LR"(\s*)" // whitespace (none or more)
LR"((Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))" // match[2] = month
LR"(\s*)" // whitespace (none or more)
LR"((\d+))" // match[3] = year
LR"(\s+)" // whitespace (1 or more)
LR"((\d+))" // match[4] = hour
LR"(\s*:\s*)" // whitespace (none ore more), colon (1), whitespace (none ore more)
LR"((\d+))" // match[5] = minute
LR"((?:\s*:\s*(\d+))?)" // match[6] = second (none or more)
LR"(.*)" // any characters (none or more)
, std::regex_constants::icase };
test( L"Sat, 13 Jan 2018 07:54:39 -0500 (EST)", r );
test( L"Wed, 10 jan2018 18:30 +0100", r );
test( L"10Jan 2018 18 :30 : 00 + 0100", r );
}
void test( std::wstring const& s, std::wregex const& r )
{
std::wsmatch m;
if( regex_match( s, m, r ) )
{
std::wcout
<< L"Day : " << m[ 1 ] << L'\n'
<< L"Month : " << m[ 2 ] << L'\n'
<< L"Year : " << m[ 3 ] << L'\n'
<< L"Hour : " << m[ 4 ] << L'\n'
<< L"Minute : " << m[ 5 ] << L'\n'
<< L"Second : " << m[ 6 ] << L'\n';
}
else
{
std::wcout << "no match" << '\n';
}
std::wcout << std::endl;
}
Live demo.
您指定将每个组件括在括号中的模式(r 变量)。调用regex_match 后,结果存储在变量m 中,您可以通过下标运算符访问每个组件(也称为子匹配)。这些也是std::wstrings。
如有必要,捕获正则表达式库以及std::stoi 可能引发的异常。为简洁起见,我省略了这段代码。
编辑:
在 OP 评论说需要更强大的解析之后,我相应地修改了正则表达式。
从对test() 函数的调用中可以看出,现在对空格的要求更加宽松。此外,时间戳的 seconds 部分现在是可选的。这是使用以(?: 引入并以) 结尾的非捕获组来实现的。通过在该组之后放置 ?,整个组(包括空格、: 和数字)可以不出现或出现一次,但只会捕获数字。
注意: LR"()" 指定raw string literal 以使正则表达式更具可读性(它避免转义反斜杠)。所以外括号不是实际正则表达式的一部分!
对于手动解析,可以使用std::wstringstream。在我看来,相对于正则表达式的唯一优势可能是更好的性能。否则,这个解决方案就很难维护,例如,如果将来必须更改时间格式。
#include <iostream>
#include <sstream>
#include <array>
#include <string>
int month_to_int( std::wstring const& m )
{
std::array<wchar_t const*, 12> names{ L"Jan", L"Feb", L"Mar", L"Apr", L"May", L"Jun", L"Jul", L"Aug", L"Sep", L"Oct", L"Nov", L"Dec" };
for( std::size_t i = 0; i < names.size(); ++i )
{
if( names[ i ] == m )
return i + 1;
}
return 0;
}
int main()
{
std::wstringstream s{ L"Sat, 13 Jan 2018 07:54:39 -0500 (EST)" };
std::wstring temp;
int day, month, year, hour, minute, second;
// operator >> reads until whitespace delimiter
s >> temp;
s >> day;
s >> temp; month = month_to_int( temp );
s >> year;
// use getline to explicitly specify the delimiter
std::getline( s, temp, L':' ); hour = std::stoi( temp );
std::getline( s, temp, L':' ); minute = std::stoi( temp );
// last token separated by whitespace again
s >> second;
std::cout
<< "Day : " << day << '\n'
<< "Month : " << month << '\n'
<< "Year : " << year << '\n'
<< "Hour : " << hour << '\n'
<< "Minute : " << minute << '\n'
<< "Second : " << second << '\n';
}
Live demo.
再次,为简洁起见,这里没有错误处理。您应该在每次输入操作后检查流状态或在构造后调用std::wstringstream::exceptions() 以启用异常并处理它们。