Re: Add ISO 8601 date format constant with millisecond precision

From: Date: Sat, 29 Aug 2026 16:19:09 +0000
Subject: Re: Add ISO 8601 date format constant with millisecond precision
References: 1 2 3  Groups: php.internals 
Request: Send a blank email to internals+get-132386@lists.php.net to get a copy of this message
Hey Théo On 29.08.26 18:04, Théo Attali wrote:
Hi Andreas, Thank you for your feedback. I agree that a format constant containing a literal Z is not ideal because the format string cannot enforce UTC. A userland formatter is safer because it can normalize the value before formatting it. After considering this, I think an instance method may be a better fit than a new format constant:
     $date->toISOString();
The method could normalize the instant to UTC and return exactly:
     1970-01-01T00:00:00.000Z
It would not modify the original object, which is particularly important for DateTimeImmutable. I also found that Carbon provides:
     $date->toIso8601ZuluString('millisecond');
However, that requires an external dependency. My motivation is to provide a dependency-free way to produce a common ISO 8601 UTC representation used when exchanging timestamps between PHP, JavaScript, Java, Go, and other ecosystems. I searched for an existing PHP issue or RFC proposing this exact method but found only the older, inactive DateTime::__toString() RFC, which addressed a different problem. Would you consider a UTC-normalizing instance method a more appropriate direction for this issue than adding a format constant?
Well... PHP already *has* a dependency-free way to format any datetime-object into an ISO string: echo $anyDateTimeImmutable
    ->setTimezone(new DateTimeZone('UTC'))
    ->format('Y-m-d\\TH:i:s.vP');
If you want to avoid having to write that string all the time, feel free to do something like Interface IsoDateTime {
    const WITH_MILLISECONDS = 'Y-m-d\\TH:i:s.vP';
    const JUST_SECONDS = 'Y-m-d\\TH:i:sP';
} and then call echo $anyDateTimeImmutable
    ->setTimezone(new DateTimeZone('UTC'))
    ->format(IsoDateTimeInterface::WITH_MILLISECONDS);
That works since PHP5.3 Anything else is adding convenience at a cost. And for me (but I am just one person here on the list) that cost (limited availability to older versions, increasingly polluted constants, very specific use-case, possibly broken output due to wrong timezone) outweighs the benfits. Just my 0.02€ Cheers Andreas
Best regards, Théo Attali El sáb, 29 ago 2026 a las 12:36, Andreas Heigl (<andreas@heigl.org>) escribió:
Hey Théo On 29.08.26 11:47, Théo Attali wrote:
Hi ! Sorry derick for the duplicated email but I was not registered. This is my first contribution, so I would appreciate any help on the proposal and on following the project's contribution process. I opened issue #23491 for a possible addition to ext/date:
      https://github.com/php/php-src/issues/23491
I would appreciate feedback before preparing an implementation. PHP currently provides DATE_RFC3339_EXTENDED, which includes millisecond precision. For a UTC DateTime, it produces:
      1970-01-01T00:00:00.000+00:00
Some applications need the equivalent representation with the ISO 8601
UTC
designator Z:
      1970-01-01T00:00:00.000Z
This is also the format produced by JavaScript's Date.prototype.toISOString():
      new Date(0).toISOString();
      // "1970-01-01T00:00:00.000Z"
Would a predefined format for this representation be appropriate for ext/date? One possible API would be:
      DATE_ISO8601_MILLISECONDS_UTC
      DateTimeInterface::ISO8601_MILLISECONDS_UTC
with the format string:
      "Y-m-d\\TH:i:s.v\\Z"
For example:
      $date = new DateTimeImmutable('@0');
      echo $date->setTimezone(new DateTimeZone('UTC'))
          ->format(DATE_ISO8601_MILLISECONDS_UTC);
      // 1970-01-01T00:00:00.000Z
The name and API shape are open for discussion. Another option would be
an
offset-preserving format:
      DATE_ISO8601_MILLISECONDS
      DateTimeInterface::ISO8601_MILLISECONDS
using:
      "Y-m-d\\TH:i:s.vP"
I understand that date format constants only define formatting; they do
not
change the timezone of the DateTime object. A format containing a literal Z would therefore require the caller to normalize the object to UTC first. For context, issue #14593 discusses the interpretation of the Z suffix
when
parsing DateTime values:
      https://github.com/php/php-src/issues/14593
That issue concerns parsing and timezone representation, whereas this proposal concerns predefined formatting constants. I would appreciate feedback on: 1. Whether a millisecond-precision format is useful in addition to
     DATE_RFC3339_EXTENDED.
2. Whether an offset-preserving format or a UTC-suffix format is
preferable.
3. Whether the proposed names follow the preferred ext/date convention. 4. Whether an RFC is required before implementation. Thank you, Théo Attali
I see some serious issues with the idea of adding the format with the \\Z at the end as you already described. It would require a prerequisite that can'T be enforced and that will therefore cause a lot of confusion. To ease that confusion I would recommend anyone that has that explicit requirement to create a Formatter - perhaps tehr eeven is one already available that in essence just does something like this: class Formatter {
      public static function formatIso(DateTimeImmutable $date): string
      {
         return $date->setTimezone(new
DateTimeZone('UTC'))->format('Y-m-d\\TH:i:s.vP');
      }
} Maintaining such a set of Formatters in Userland seems to be much easier than adding that in the PHP-Src. It would also make the formatter available to ALL PHP-Versions that have a DateTimeImmutable object and not only PHP8.6/8.7 onwards. From my side I would by now not add any more constants to the PHP-Source as they will not be available to earler versions. And I say that as the person that added the _EXTENDED constants... By now I would create a formatter in userland and promote that for usage as it's a small library that can be used by *any* PHP-Version that needs it. My 0.02€ Cheers Andreas --
                                                                ,,,
                                                               (o o)
+---------------------------------------------------------ooO-(_)-Ooo-+
| Andreas Heigl                                                       |
| mailto:andreas@heigl.org                  N 50°22'59.5" E 08°23'58" |
| https://andreas.heigl.org                                           |
+---------------------------------------------------------------------+
| https://hei.gl/appointmentwithandreas                               |
+---------------------------------------------------------------------+
| GPG-Key: https://hei.gl/keyandreasheiglorg                          |
+---------------------------------------------------------------------+
-- ,,, (o o) +---------------------------------------------------------ooO-(_)-Ooo-+ | Andreas Heigl | | mailto:andreas@heigl.org N 50°22'59.5" E 08°23'58" | | https://andreas.heigl.org | +---------------------------------------------------------------------+ | https://hei.gl/appointmentwithandreas | +---------------------------------------------------------------------+ | GPG-Key: https://hei.gl/keyandreasheiglorg | +---------------------------------------------------------------------+

« previous php.internals (#132386) next »