我的想法是使用STL并将PWCHAR时间戳转换为wstring,将其加载到流中并使用>> operator将给定的拆分分配给SYSTEMTIME结构的相应成员,并使用Win32函数将其转换为FILETIME结构。
VOID StringToFileTime(const PWCHAR timeString, FILETIME &ft) {
if(NULL == timeString)
return;
wstring time(L"2013-May-14 20:33:13.132814");
std::wistringstream stream(time);
SYSTEMTIME st = {0};
stream >> st.wYear;
stream.ignore(1, '-');
stream >> st.wMonth;
stream.ignore(1, '-');
stream >> st.wDay;
stream.ignore(1, ' ');
stream >> st.wHour;
stream.ignore(1, ':');
stream >> st.wMinute;
stream.ignore(1, ':');
stream >> st.wSecond;
stream.ignore(1, '.');
stream >> st.wMilliseconds;
SystemTimeToFileTime(&st, &ft);
}
我遇到的问题是在st.wYear之后没有填写SYSTEMTIME结构。因此,这一年将设定为2013年,但之后的成员为0。 看看变量内容我会更加困惑。硬编码时间戳未出现在调试器变量视图的wstring时间变量中。而是为时间变量列出了nPOS编号和错误。
如何将字符串转换为FILETIME结构?
我在Windows 10上使用Visual Studio 2013 Update 3.
答案 0 :(得分:1)
问题是stream >> st.wMonth
失败了,因为它试图将字符串值May
读入数字WORD
,这不是受支持的转换。您没有重置stream
错误状态,因此>>
和ignore()
的后续使用也会失败,因此在SYSTEMTIME
之后wYear
无法填写。
如果您有C ++ 11编译器,则可以使用std::get_time()
来解析timeString
:
#include <sstream>
#include <iomanip>
bool StringToFileTime(LPCWSTR timeString, FILETIME &ft)
{
SYSTEMTIME st = {0};
std::wistringstream stream(timeString);
std::tm tmb;
// std::get_time() does not support reading milliseconds...
if (!(stream >> std::get_time(&tmb, L"%Y-%b-%d %H:%M:%S")))
return false;
st.wYear = 1900 + tmb.tm_year;
st.wMonth = tmb.tm_mon + 1;
st.wDayOfWeek = tmb.tm_wday;
st.wDay = tmb.tm_mday;
st.wHour = tmb.tm_hour;
st.wMinute = tmb.tm_min;
st.wSecond = tmb.tm_sec;
if (!stream.eof())
{
stream.ignore(1, L'.');
// st.wMilliseconds is a 16bit WORD, so it can only go up to 65535.
// There are only 1000 ms in a second, so 132814 is clearly not
// expressed in milliseconds. Is it nanoseconds? 100-nanoseconds?
// Whatever it is, convert it to st.wMilliseconds as needed...
int iValue;
if (!(stream >> iValue))
return false;
st.wMilliseconds = ...;
}
return SystemTimeToFileTime(&st, &ft);
}
如果你没有C ++ 11编译器,你仍然可以使用std::wistringstream
,你只需要手动提取值:
#include <sstream>
bool StringToFileTime(LPCWSTR timeString, FILETIME &ft)
{
SYSTEMTIME st = {0};
std::wistringstream stream(timeString);
std::string sMonth;
if (!(stream >> st.wYear)) return false;
if (!stream.ignore(1, L'-')) return false;
// st.wMonth is a 16bit WORD, but a month name is given instead.
// parse it into st.wMonth as needed...
if (!std::getline(stream, sMonth, L'-')) return false;
st.wMonth = ...;
if (!stream.ignore(1, L'-')) return false;
if (!(stream >> st.wDay)) return false;
if (!stream.ignore(1, L' ')) return false;
if (!(stream >> st.wHour)) return false;
if (!stream.ignore(1, L':')) return false;
if (!(stream >> st.wMinute)) return false;
if (!stream.ignore(1, L':')) return false;
if (!(stream >> st.wSecond)) return false;
if (!stream.eof())
{
stream.ignore(1, L'.');
// convert to st.wMilliseconds as needed...
int iValue;
if (!(stream >> iValue))
return false;
st.wMilliseconds = ...;
}
return SystemTimeToFileTime(&st, &ft);
}
或者,您可以使用swscanf()
代替std::wistringstream
:
bool StringToFileTime(LPCWSTR timeString, FILETIME &ft)
{
SYSTEMTIME st = {0};
WCHAR szMonth[12];
int iValue = 0;
int numRead = swscanf(timeString, L"%hu-%[^-]-%hu &hu:&hu:&hu.%d", &st.wYear, szMonth, &st.wDay, &st.wHour, &st.wMinute, st.wSecond, &iValue);
if (numRead < 6) return false;
// parse szMonth into st.wMonth as needed...
if (numRead == 7)
{
// convert iValue into st.wMilliseconds as needed...
}
return SystemTimeToFileTime(&st, &ft);
}