~ / topics / Operating Systems
$man os-windows

Windows

In brief: Windows itself does not count time the Unix way. Its native clock is a 64-bit count of 100-nanosecond steps since 1601, which will not overflow for tens of thousands of years. Microsoft's C compiler has also used 64-bit time_t by default since Visual Studio 2005. Problems on Windows come from programs that deliberately chose 32-bit time, from old file formats and network structures, and from third-party code that stores dates in 32-bit integers. Microsoft's own "Y2K22" Exchange outage in 2022 shows how that last category fails.

Risk level Low (OS) · Medium (legacy applications, formats and third-party code)
Status OS time APIs not affected. MSVC CRT time_t 64-bit by default since VS2005. Legacy 32-bit uses remain in applications and formats
Last reviewed 2026-10-21

2038 status at a glance

Not affected or different deadline (2), and why

Overview

Windows NT and its successors keep system time as FILETIME: "a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC)" [1]. The core Win32 time APIs use this representation or the SYSTEMTIME calendar struct, among them GetSystemTimeAsFileTime, GetFileTime/SetFileTime and FileTimeToSystemTime. NTFS stores file timestamps in the same format, in UTC [1]. A 64-bit count of 100 ns ticks lasts until roughly the year 30,828, so the Windows kernel and file system are not affected by 2038 [2].

The 2038 problem reaches Windows through the C runtime library (CRT), which provides the POSIX-style time_t, time(), localtime() and so on, and through any software that copied the Unix convention.

Technical details

The MSVC CRT and time_t

Places where 32-bit time is still used on Windows

Location Representation Limit Notes
Code compiled with _USE_32BIT_TIME_T (32-bit targets only) 32-bit signed time_t 2038-01-19 Discouraged by Microsoft [3]
_time32, _mktime32, _stat32, __time32_t fields 32-bit signed 2038-01-19 Explicit opt-in [3]
PE/COFF TimeDateStamp in every EXE/DLL/OBJ "The low 32 bits of the number of seconds since 00:00 January 1, 1970 (a C run-time time_t value)" 2038 if read as signed, 2106 as unsigned Many PE parsing and forensic tools treat it as signed. Reproducible builds store a hash here, not a time [7]
Winsock struct timeval long tv_sec; long tv_usec;, and long is 32-bit on Windows even on x64 Used for intervals (for example the select timeout), so 2038 is not a direct problem Portable code that puts absolute epoch time into a timeval on Windows truncates it [8]
FAT/exFAT timestamps Year stored as an offset from 1980 in 7 bits 2107 "the year 1980 with the value 0 and the year 2107 with the value 127" [9]
Third-party formats and databases Varies Varies See File-Formats-and-Protocols and Databases
Application code storing dates in int/DWORD/LONG 32-bit Varies The Y2K22 class of bugs (below)

Other runtimes on Windows (.NET DateTime, Java, Python and others) have their own representations. See Lang-DotNet and Programming-Languages.

Contrast: the Exchange "Y2K22" bug (2022-01-01)

On 2022-01-01 at 00:00 UTC, on-premises Exchange Server 2016 and 2019 stopped delivering mail. The FIP-FS anti-malware engine loaded signature updates whose version string encoded the date as YYMMDDHHMM. The first update of 2022 had the version 2201010001. Exchange parsed that into a signed 32-bit integer, whose maximum is 2,147,483,647, so the conversion failed with event ID 1106: "Can't convert "2201010001" to long." The scan engine did not load and messages piled up in transport queues [10]. Microsoft said it was "not an issue with malware scanning or the malware engine, and it is not a security-related issue" and released a fix that admins could apply manually or with an automated PowerShell script [11]. Until it was applied, the common stopgap was to disable FIP-FS scanning, which left mail unscanned [10].

The bug is not a time_t overflow. It is the same class of failure, though: a date squeezed into a signed 32-bit integer, failing on a predictable date that nobody tested. The same YYMMDDHHMM scheme would have hit the limit at 2021-12-31 23:59, just as an epoch-seconds value hits it at 2038-01-19. Testing with clocks and data set forward would have caught it. See Related-Date-Bugs and Known-2038-Incidents.

Affected versions / products

Product Status
Windows NT kernel, NTFS, Win32 FILETIME/SYSTEMTIME APIs Not affected (to ~30,828) [1][2]
MSVC CRT ≥ VS2005 (msvcr80 → UCRT), default build time_t 64-bit; safe to 3000-12-31 [3]
MSVC CRT ≤ VS2003 (msvcr71 and earlier) 32-bit time_t — affected [4]
Any 32-bit binary built with _USE_32BIT_TIME_T Affected [3]
Code using _time32/__time32_t or storing time_t in long/int Affected
FAT32/exFAT volumes Limited to 2107 [9]
Exchange 2016/2019 FIP-FS (before the January 2022 fix) Y2K22 failure [10]

Risk & compliance notes

Detection & mitigation

# find the legacy macro and explicit 32-bit time functions in a source tree
Select-String -Path .\src\* -Recurse -Pattern '_USE_32BIT_TIME_T|_time32|__time32_t|_mktime32|_gmtime32'

See also

References

  1. FILETIME structure (minwinbase.h) — Microsoft Learn. 64-bit count of 100 ns intervals since 1601-01-01 UTC. NTFS stores UTC.
  2. Year 2038 problem — Wikipedia. Secondary source: the Windows API is unaffected until about the year 30,828. VC++ 64-bit time_t since 2005.
  3. time, _time32, _time64 — Microsoft Learn (C runtime reference). Default 64-bit, year-3000 limit, _USE_32BIT_TIME_T guidance.
  4. [Patches] python-Patches-1437769: Size of time_t changed to 64 bits in MSVC++ 2005 CRT — python.org mailing list, 2006-03. Quotes Microsoft's VS2005 breaking-change note (seen in search results).
  5. Bug #39802: On Windows, 32-bit time_t should be enforced — MySQL Bugs. Binary incompatibility caused by the VS2005 change (seen in search results).
  6. MinGW ticket #37938 — OSDN. _USE_32BIT_TIME_T handling in MinGW (seen in search results).
  7. PE Format — Microsoft Learn. COFF header TimeDateStamp: "The low 32 bits of the number of seconds since 00:00 January 1, 1970".
  8. TIMEVAL structure (winsock.h) — Microsoft Learn. long tv_sec; long tv_usec;, used to specify a time interval.
  9. exFAT file system specification §7.4.8.6 — Microsoft Learn. Year field covers 1980–2107.
  10. Microsoft Exchange year 2022 bug in FIP-FS breaks email delivery — BleepingComputer, 2022-01-01. Value 2,201,010,001 versus the signed int32 maximum; Microsoft statement.
  11. Microsoft releases fix for disruptive Exchange Y2K22 bug — Computing, 2022-01. Fix released as a script (seen in search results).