~ / topics / Languages
$man lang-php

PHP

In brief: PHP's integer is as wide as the machine it was built for. On 64-bit PHP, timestamps are fine for billions of years. On 32-bit PHP, every function that works with Unix timestamps (time(), mktime(), strtotime(), date()) stops working on 19 January 2038, and date calculations that reach past 2038 already fail today. The fix is to run 64-bit PHP and to use the DateTimeImmutable classes instead of raw timestamps.

Risk level High on 32-bit builds. Low on 64-bit builds
Status No fix planned for 32-bit timestamps. 64-bit builds (PHP_INT_SIZE === 8) are safe. 64-bit Windows builds use 64-bit integers since PHP 7.0
Last reviewed 2026-10-21

2038 status at a glance

Not affected or different deadline (1), and why
  • Not affectedPHP 7+ 64-bit buildsPHP_INT_SIZE is 8, so timestamps are effectively unlimited.Do: Still check database columns and pack() formats.

Overview

PHP has one integer type, int, and its size "is platform-dependent… 64-bit platforms usually have a maximum value of about 9E18". You can check it at run time with PHP_INT_SIZE (4 or 8) and PHP_INT_MAX [1]. When an integer operation overflows, PHP "will return a float instead" rather than wrapping [1].

Unix-timestamp functions take and return int, so on a 32-bit build the PHP manual says: "The valid range of a timestamp is typically from Fri, 13 Dec 1901 20:45:54 UTC to Tue, 19 Jan 2038 03:14:07 UTC… For 64-bit versions of PHP, the valid range of a timestamp is effectively infinite" [2].

Before PHP 7.0, Windows x64 builds also had 32-bit integers, because PHP's integer was a C long, which is 32 bits on Windows. Derick Rethans, the author of PHP's date extension, noted this "got resolved with PHP 7.0, which now uses an int64_t-like type" [3]. A 64-bit Windows server running PHP 5.x is therefore effectively a 32-bit-timestamp system.

Technical details

How the timestamp functions fail on 32-bit

Function Behaviour with a post-2038 date on 32-bit PHP
mktime() Returns false "if the timestamp doesn't fit in a PHP integer" [4]
strtotime() Returns false [2]
date('Y', $ts) Can't receive a post-2038 value, because $timestamp is typed int [6]
time() Wraps or fails after 2038-01-19 03:14:07 UTC
DateTime::getTimestamp() Throws ValueError: Epoch doesn't fit in a PHP integer (PHP 8) [5]
<?php
// BUG on 32-bit PHP: false, then date() renders 1970-01-01
$ts = mktime(0, 0, 0, 1, 1, 2040);
echo date('Y-m-d', $ts);          // "1970-01-01" because false is cast to 0

// BUG: arithmetic on timestamps; 25-year expiry is already past 2038
$expires = time() + 25 * 365 * 86400;   // becomes float on 32-bit, then truncated when stored

// Always check the return value strictly
if ($ts === false) { throw new RuntimeException('date out of range'); }

false turning into 0 (1970-01-01) is the typical symptom: silent wrong dates, not crashes.

The fix: DateTime / DateTimeImmutable

The DateTime* classes are built on the timelib library and don't depend on PHP's int for their internal value. Reports from 32-bit users show format('U') returning correct values past the 32-bit range [7], so calendar arithmetic should work past 2038 even on 32-bit builds, provided you never convert to an int timestamp. (Internal representation not verified against timelib source; test on your build.)

<?php
$tz  = new DateTimeZone('UTC');
$d   = new DateTimeImmutable('2038-01-19 03:14:07', $tz);
$d2  = $d->modify('+1 second');
echo $d2->format('Y-m-d H:i:s');   // 2038-01-19 03:14:08
echo $d2->format('U');             // "2147483648" as a *string*; safe to store
// $d2->getTimestamp();            // 32-bit: ValueError; 64-bit: 2147483648

The manual itself recommends DateTimeImmutable over strtotime() for calculations, and DateTime::add()/sub() for arithmetic [2][6]. On 32-bit builds, format('U') is the reported workaround for getting the epoch value as a string. A Drupal issue notes that feeding it back through setTimestamp() still fails, so keep values as DateTime objects or strings end to end [7].

Detecting a 32-bit build

<?php
if (PHP_INT_SIZE < 8) {
    trigger_error('32-bit PHP: Unix timestamps fail after 2038-01-19', E_USER_WARNING);
}
var_dump(PHP_INT_MAX + 1);   // 32-bit: float(2147483648)  64-bit: float(9.2233720368548E+18)

Other PHP-specific pitfalls

Will 32-bit PHP be fixed?

In January 2021, Tyson Andre asked on the php-internals list whether PHP should drop or deprecate 32-bit builds before 2038. He noted that (new DateTime())->getTimestamp() would start throwing ValueError on 32-bit after the rollover. He also rejected widening zend_long to 64 bits on 32-bit platforms and returning int|float. Nikita Popov replied that usage data was lacking [5]. As of 2026-10-21 we found no adopted RFC that changes 32-bit timestamp behaviour (no RFC located). Assume 32-bit PHP will not be fixed.

Affected versions / products

PHP build PHP_INT_SIZE Timestamp range 2038 exposure
Any version, 32-bit OS/build 4 1901-12-13 to 2038-01-19 High
PHP 5.x on Windows x64 4 1901–2038 High
PHP 7.0+ on Windows x64 8 effectively unlimited Low
PHP on 64-bit Linux/BSD/macOS 8 effectively unlimited Low (watch DB columns and pack())
Bundled dev stacks shipping 32-bit PHP (some "starter kits") 4 1901–2038 High in dev/test [3]

Risk & compliance notes

Detection & mitigation

  1. Fail the deploy if PHP_INT_SIZE !== 8.
  2. Replace timestamp arithmetic with DateTimeImmutable and DateInterval. Store dates as DATETIME or ISO 8601 strings.
  3. Add unit tests with dates such as 2038-01-19 03:14:08 UTC and 2040-01-01, and run them in a 32-bit container (i386/php) if you still support one.
  4. Static analysis: PHPStan and Psalm can flag unchecked int|false returns from mktime()/strtotime() at stricter levels.
  5. See Testing-and-Detection and Remediation-Guide.

See also

References

  1. Integers — PHP Manual — platform-dependent size, PHP_INT_SIZE/PHP_INT_MAX, overflow to float.
  2. strtotime — PHP Manual — valid range 1901-12-13 to 2038-01-19 on 32-bit, "effectively infinite" on 64-bit; recommends DateTimeImmutable.
  3. Re: [tz] The Y2038 problem — Matthew Donadio quoting Derick Rethans, tz mailing list, 2018-01-19 — Windows long was int32; resolved in PHP 7.0; 32-bit starter kits.
  4. mktime — PHP Manual — returns false if the timestamp doesn't fit; year range 1901–2038 with 32-bit time_t; two-digit year mapping.
  5. php-internals thread on 32-bit builds and 2038 — Tyson Andre, via externals.io, 2021-01-08 — getTimestamp() ValueError on 32-bit; reply by Nikita Popov.
  6. date — PHP Manual — $timestamp is an int; recommends DateTimeImmutable.
  7. Drupal issue #2795489 — drupal.org — format('U') workaround on 32-bit; setTimestamp() round-trip problem.
  8. Date and Time Functions — MySQL 8.0 Reference Manual — UNIX_TIMESTAMP() range 2038 before 8.0.28 and on 32-bit.