How do I parse a string into a FILETIME?


Public Service Announcement: Daylight Saving Time ends in most parts of the United States this weekend. Other parts of the world may change on a different day from the United States.

The NLS functions in Win32 provide functions to convert a SYSTEMTIME into a string, but it does not provide any functions to perform the reverse conversion. Here are few things you can try:

The OLE automation VarDateFromStr conversion function converts a string into a DATE. From there, you can convert it to some other format.

BOOL SystemTimeFromStr(__in LPCWSTR psz, LCID lcid, __out LPSYSTEMTIME pst)
{
  DATE date;
  return SUCCEEDED(VarDateFromStr(psz, lcid, 0, &date)) &&
         VariantTimeToSystemTime(date, pst);
}

BOOL FileTimeFromStr(__in LPCWSTR psz, LCID lcid, __out LPFILETIME pft)
{
  SYSTEMTIME st;
  return SystemTimeFromStr(psz, lcid, &st) &&
         SystemTimeToFileTime(&st, pft);
}

If you have something in which parses CIM datetime format (which The Scripting Guys liken to Klingon) you can use the SWbemDateTime object. Since this is a scripting object, using it from C++ is rather cumbersome.

BOOL FileTimeFromCIMDateTime(__in LPCWSTR psz, __out LPFILETIME pft)
{
 BOOL fSuccess = FALSE;
 ISWbemDateTime *pDateTime;
 HRESULT hr = CoCreateInstance(__uuidof(SWbemDateTime), 0,
                 CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDateTime));
 if (SUCCEEDED(hr)) {
  BSTR bstr = SysAllocString(psz);
  if (bstr) {
   hr = pDateTime->put_Value(bstr);
   if (SUCCEEDED(hr)) {
    BSTR bstrFT;
    hr = pDateTime->GetFileTime(VARIANT_FALSE, &bstrFT);
    if (SUCCEEDED(hr)) {
     __int64 i64FT = _wtoi64(bstrFT);
     pft->dwLowDateTime = LODWORD(i64FT);
     pft->dwHighDateTime = HIDWORD(i64FT);
     fSuccess = TRUE;
     SysFreeString(bstrFT);
    }
   }
   SysFreeString(bstr);
  }
  pDateTime->Release();
 }
 return fSuccess;
}

From the managed side, you have Date­Time.Try­Parse and Date­Time.Parse­Exact methods.

I leave you to investigate the time zone and locale issues associated with these techniques. (Because I can't be bothered.)

Comments (5)
  1. pcooper says:

    Sadly, probably most people doing this also can't be bothered to investigate time zone and locale issues.

  2. RobertWrayUK says:

    And because for everything else there's MasterC… Er, MichKap?:)

  3. Adam Rosenfield says:

    On POSIX systems, use strptime (though of course that will give you a struct tm object, since POSIX doesn't use the FILETIME structure).

  4. Neil says:

    Simply convert all possible SYSTEMTIME values to string and find out which one matches.

    Or at least, that would have been the solution had this been a Daily WTF coding challenge.

  5. cheong00 says:

    //sigh

    A few months earlier, we have bug report because someone forgotten to take care of locale issue… the "dd-MMM-yyyy" formatting produce something like "01-十一月-2011" and when we read the data back, error is thrown.

Comments are closed.