title: WinAPI to format FILETIME as a localized string with date and/or time
body: <p>I'm looking for a low-level WinAPI to format date-time from <code>FILETIME</code> to a localized string with an output of a date, time, or date and time together.</p>
  
  <p>By reversing the MFC's <code>COleDateTime</code> I was able to find <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms221699(v=vs.85).aspx" rel="nofollow noreferrer"><code>VarBstrFromDate</code></a> function that "kinda" works. So I was trying to see if there's another more reliable API that can accomplish that.</p>
  
  <p>There are two issues with <code>VarBstrFromDate</code> that I could see:</p>
  
  <p><strong>1)</strong> It doesn't reliably report the date or time parts. For instance, if I call it as such for <code>midnight Dec. 31, 1899</code>:</p>
  
  <pre><code>BSTR bstr = NULL;
  HRESULT hr = ::VarBstrFromDate(1.0, LANG_USER_DEFAULT, VAR_FOURDIGITYEARS, &amp;bstr);
  ::SysFreeString(bstr);
  </code></pre>
  
  <p>it returns <code>"12/31/1899"</code> without the time part.</p>
  
  <p>Or, if I call it for, say, <code>noon Dec. 30, 1899</code>:</p>
  
  <pre><code>BSTR bstr = NULL;
  HRESULT hr = ::VarBstrFromDate(0.5, LANG_USER_DEFAULT, VAR_FOURDIGITYEARS, &amp;bstr);
  ::SysFreeString(bstr);
  </code></pre>
  
  <p>it returns <code>"12:00:00 PM"</code> without the date part.</p>
  
  <p><strong>2)</strong>  Additionally, conversion from <code>FILETIME</code> to <code>DATE</code> is somewhat tricky, especially for dates prior to Dec. 30, 1899. Again, by reversing MFC I was able to find that <a href="https://msdn.microsoft.com/es-es/library/windows/desktop/ms221646(v=vs.85).aspx" rel="nofollow noreferrer"><code>SystemTimeToVariantTime</code></a> can do it via the <code>SYSTEMTIME</code> struct. Kinda backwards, but OK. But then I saw this monstrosity in the <code>atlcore.h</code>:</p>
  
  <pre><code>inline BOOL AtlConvertSystemTimeToVariantTime(
      _In_ const SYSTEMTIME&amp; systimeSrc,
      _Out_ double* pVarDtTm)
  {
      ATLENSURE(pVarDtTm!=NULL);
      //Convert using ::SystemTimeToVariantTime and store the result in pVarDtTm then
      //convert variant time back to system time and compare to original system time.
      BOOL ok = ::SystemTimeToVariantTime(const_cast&lt;SYSTEMTIME*&gt;(&amp;systimeSrc), pVarDtTm);
      SYSTEMTIME sysTime;
      ::ZeroMemory(&amp;sysTime, sizeof(SYSTEMTIME));
  
      ok = ok &amp;&amp; ::VariantTimeToSystemTime(*pVarDtTm, &amp;sysTime);
      ok = ok &amp;&amp; (systimeSrc.wYear == sysTime.wYear &amp;&amp;
              systimeSrc.wMonth == sysTime.wMonth &amp;&amp;
              systimeSrc.wDay == sysTime.wDay &amp;&amp;
              systimeSrc.wHour == sysTime.wHour &amp;&amp;
              systimeSrc.wMinute == sysTime.wMinute &amp;&amp;
              systimeSrc.wSecond == sysTime.wSecond);
  
      return ok;
  }
  </code></pre>
  
  <p>Do you know why they're checking the result returned by <code>SystemTimeToVariantTime</code> by then passing it through <code>VariantTimeToSystemTime</code> in such an awkward way? Does it mean that <code>SystemTimeToVariantTime</code> may return an incorrect result, or what?</p>
  
  <p>Anyway, I was thinking to find another API that wouldn't rely on conversion to a floating-point <code>DATE</code>.</p>