PHP: How do you get the current date and time?

Printing the current date is one line of code. As soon as you calculate with it or display it in another time zone, though, a few things come along that are worth knowing.

The quick way

<?php
  echo date('Y-m-d H:i:s');   // 2026-08-28 22:08:12
  echo date('d.m.Y');         // 28.08.2026
  echo date('Y');             // 2026
?>

date() formats the current time according to a pattern. If all you need is the year or the day, you are done here.

The time zone comes first

This is the most common reason for “the time is wrong”. PHP uses the time zone configured in php.ini, and that is often UTC. The same moment then looks like this:

12:00 in UTC        : 2026-08-28 12:00:00 UTC
derselbe Zeitpunkt  : 2026-08-28 14:00:00 CEST

The Unix timestamp is identical in both cases, only the display differs. You can set the time zone globally in php.ini:

date.timezone = Europe/Vienna

or at runtime:

<?php
  date_default_timezone_set('Europe/Vienna');
?>

If you store moments in a database, store them in UTC and convert only when displaying. Then you have no trouble with daylight saving time and none with users in other time zones.

The better way: DateTimeImmutable

As soon as you do more than display, use an object:

<?php
  $now = new DateTimeImmutable('now', new DateTimeZone('Europe/Vienna'));

  echo $now->format('d.m.Y');      // 28.08.2026
  echo $now->format(DATE_ATOM);    // 2026-08-28T22:08:12+02:00
  echo $now->getTimestamp();       // 1787947692
?>

DATE_ATOM is handy when the value leaves through an interface — the format is unambiguous and includes the time zone.

Why immutable?

There are two classes: DateTime and DateTimeImmutable. The difference is bigger than the name suggests:

<?php
  $a = new DateTimeImmutable('2026-08-28 10:00:00');
  $b = $a->modify('+1 day');

  $c = new DateTime('2026-08-28 10:00:00');
  $d = $c->modify('+1 day');
?>
DateTimeImmutable  $a : 2026-08-28    (unchanged)
                   $b : 2026-08-29

DateTime           $c : 2026-08-29    <- changed!
                   $d : 2026-08-29

With DateTime, modify() changes the object itself and returns it as well. Afterwards $c and $d are two names for the same object. Pass such an object to a function that calculates with it and you end up with a different date than before, without that being visible at the call site.

When in doubt, always use DateTimeImmutable.

Calculating with time

<?php
  $start = new DateTimeImmutable('2026-08-28 23:30:00');

  $end = $start->add(new DateInterval('PT2H'));   // +2 hours
  echo $end->format('Y-m-d H:i');                 // 2026-08-29 01:30

  echo $start->modify('+1 month')->format('Y-m-d'); // 2026-09-28
?>

DateInterval takes a specification in ISO 8601 format: P introduces the period, T separates off the time part. So PT2H is two hours, P1D one day, P1M one month.

The month trap

And now the place where many people are surprised:

31.01. + 1 month   =>   2026-03-03

Not 28 February, but 3 March. The reason is how it is calculated: PHP first increments the month number and normalises afterwards. So “31 February” becomes 3 March, because February 2026 only has 28 days.

That is documented behaviour and not a bug, but it surprises people reliably. If you want what is usually meant, say so explicitly:

<?php
  echo $jan31->modify('last day of next month')->format('Y-m-d');  // 2026-02-28
?>

strtotime understands text too

For quick cases strtotime() is very handy:

'now'                    => 2026-08-28
'tomorrow'               => 2026-08-29
'next monday'            => 2026-08-31
'+2 weeks'               => 2026-09-11
'last day of this month' => 2026-08-31

You can pass the same expressions to DateTimeImmutable and modify().

Invalid input

Here the two routes behave differently:

new DateTimeImmutable('kein datum') : DateMalformedStringException
strtotime('kein datum')             : false

Since PHP 8.3 there is a dedicated exception for this, DateMalformedStringException. strtotime() on the other hand only returns false — and because false counts as 0 in arithmetic, you end up at 1 January 1970 if you are not careful. So check the return value with ===.

Summary

  • Set the time zone, otherwise you are calculating in UTC without noticing.
  • date() for display, DateTimeImmutable for calculation.
  • DateTime modifies itself on modify(), DateTimeImmutable does not.
  • 31 Jan + 1 month is 3 March, not 28 February.
  • Store UTC in the database and convert only when displaying.

About Netcup (advertisement)

The German host Netcup offers, among other things, affordable and powerful web hosting packages, KVM-based root servers and dedicated servers. With our voucher codes you can save even more (6€ off your first order, 30% off all KVM-based root servers, ...).