# Add ISO 8601 date format constant with millisecond precision

- Thread: https://externals.io/message/132380
- Original archive: https://news-web.php.net/php.internals/132380
- Started by theoattali@gmail.com on 2026-08-29T09:47:49+00:00
- Messages: 6
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #132380 — theoattali@gmail.com — 2026-08-29T09:47:49+00:00

URL: https://externals.io/message/132380#132380

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

---

## #132381 — Andreas Heigl — 2026-08-29T10:36:29+00:00

URL: https://externals.io/message/132380#132381 · In reply to: #132380

Hey Théo


> 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                          |
+---------------------------------------------------------------------+

---

## #132385 — theoattali@gmail.com — 2026-08-29T16:04:21+00:00

URL: https://externals.io/message/132380#132385 · In reply to: #132381

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?

Best regards,

Théo Attali

El sáb, 29 ago 2026 a las 12:36, Andreas Heigl (<andreas@heigl.org>)
escribió:

> Hey Théo
>
> 
> > […]
> UTC
> > […]
> an
> > […]
> not
> > […]
> when
> > […]
> preferable.
> > […]
> 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                          |
> +---------------------------------------------------------------------+

---

## #132386 — Andreas Heigl — 2026-08-29T16:19:09+00:00

URL: https://externals.io/message/132380#132386 · In reply to: #132385

Hey Théo


> 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ó:
> 
> > […]
> 

-- 
                                                               ,,,
                                                              (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                          |
+---------------------------------------------------------------------+

---

## #132395 — tim@bastelstu.be — 2026-08-31T08:56:42+00:00

URL: https://externals.io/message/132380#132395 · In reply to: #132380

Hi


> 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.

There are some long-standing plans to introduce a new date and time API 
and with PHP 8.6 the first part of it will ship: 
https://wiki.php.net/rfc/duration_class. I believe at this point it may 
be more useful to focus on continuing shipping a new API than to add 
even more stuff to the existing API. As an example, the proposed 
Time\Instant is intentionally timezone-less and an ISO 8601 string with 
the Z timezone would be an obvious method to add there.

Best regards
Tim Düsterhus

---

## #132589 — tim@bastelstu.be — 2026-09-22T14:28:53+00:00

URL: https://externals.io/message/132380#132589 · In reply to: #132395

Hi


> There are some long-standing plans to introduce a new date and time API 
> and with PHP 8.6 the first part of it will ship: 
> https://wiki.php.net/rfc/duration_class. I believe at this point it may 
> be more useful to focus on continuing shipping a new API than to add 
> even more stuff to the existing API. As an example, the proposed 
> Time\Instant is intentionally timezone-less and an ISO 8601 string with 
> the Z timezone would be an obvious method to add there.

Discussion for Time\Instant is now open: 
https://news-web.php.net/php.internals/132588

Best regards
Tim Düsterhus
