Datetime overview

Last updated on
1 July 2025

About

The Datetime module provides three fields that stores dates and times.

  • Date - a varchar(20) field that'll store the date as UTC in the format 'Y-m-d\TH:i:s'
  • Daterange - Same as date, but with an added end value.
  • Timestamp - a large integer.

The Datetime module  also provides the Form API elements datetime and datelist which other modules can make use of. See the Field module documentation and the Field UI module documentation pages for general information on fields and how to create and manage them.  For how to make use of the Form API elements in modules you program yourself, see the Form API documentation and the Form and render elements API reference documentation.

Uses

Managing and displaying date fields

The settings and the display of the Date field can be configured separately. See the Field UI module documentation for more information on how to manage fields and their display.

Displaying dates

Dates can be displayed using either the Plain or Default formatter. The Plain formatter displays the date in the ISO 8601 format. If you choose the Default formatter, you can choose a format from a predefined list that can be managed on the Date and time formats page.

Adjust datetime formats at Manage > Configuration > Regional and language > Date and time formats (path: /admin/config/regional/date-time).

For more information, see Working With Content Types and Fields. For a list of the functions and their descriptions see the API documentation.

Formatting dates programmatically

The Datetime module provides a DateFormatter service that can be used to format timestamps.

use Drupal\Core\Datetime\DrupalDateTime;

/** @var Drupal\Core\Datetime\DateFormatterInterface $date_formatter */
$date_formatter = \Drupal::service('date.formatter');

// Get saved timestamp from a DateTimeFieldItemList field.
$date_value = $node->field_date->value;
$date_time = new DrupalDateTime($date_value, new \DateTimeZone('UTC'));
$timestamp = $date_time->getTimestamp();

// All other arguments are optional:
// See DateFormatterInterface for built-in options, or use machine name of a date format in config.
$type = 'medium';
// Custom PHP date format if $type="custom".
$format = '';
// Timezone cannot be NULL otherwise it will default to the user's own
// timezone. That is why it should be set explicitly.
$timezone = 'UTC';
$langcode = NULL;

$formatted = $date_formatter->format($timestamp, $type, $format, $timezone, $langcode);

An everyday approach to formatting dates programmatically looks like this:

// Show a date stored in a node in format medium.
\Drupal::service('date.formatter')->format(strtotime($order_node->field_order_date->value), 'medium')

/*
Worth noting:

1. By summoning \Drupal::service('date.formatter') directly, you do not need a use statement to that effect in your code.
2. the first argument MUST be a timestamp. As you'll probably mostly store dates in the Drupal date format, you need to do a strtotime.
3. The type "medium" is a built-in core time format. You will find all your valid date formats at /admin/config/regional/date-time - but you'll have to edit them in order to learn their machine names. You MUST use the machine names when formatting dates programmatically.
4. If you supply a type other than "custom", you can leave format blank, ''.
5. As no timezone is set, a user with timezone "Europe/Copenhagen" will see something quite unlike the user with the timezone set to "Europe/Dublin". This is often not something you want.
6. As no language code is set, a user with langcode "da" will see something quite unlike a user with the language code "en". This is often something you want. But do test.

*/

Saving dates

Saving dates using the node forms and user forms is straightforward. The date is saved in the UTC timezone and the site will display the date using the sitewide timezone or the timezone of the individual users. This is all managed at the Regional settings page (/admin/config/regional/settings). Most sites will do well setting a default country and a default timezone. If it's a big country or a global site, you may wish to check Users may set their own time zone.

Saving dates programmatically

In Drupal dates are saved in varchar(20) fields in the database. An example: "2024-10-29T04:45:58".

The format is 'Y-m-d\TH:i:s' and the timezone is always 'UTC'. You cannot save a date like "2024-10-29T04:45:58 +0200".

Same goes for Dateranges. They're just Dates with a value and and end_value.

Timestamps are integers. UTC as well.

# Saving current time to a date field in a node
$now = (new \Drupal\Core\Datetime\DrupalDateTime('now', new \DateTimeZone('UTC')))->format('Y-m-d\TH:i:s');
$order_node->set('field_order_paid_date', $now); // You need to save the $order_node to make the date stick

# Saving a few dates (and times) to a daterange field in a node
$now = \Drupal::service('date.formatter')->format(time(), 'custom', 'Y-m-d\TH:i:s', 'UTC');
$an_hour_later = \Drupal::service('date.formatter')->format(time()+3600, 'custom', 'Y-m-d\TH:i:s', 'UTC');
$appointment_node->set('field_appointment', ['value' => $now, 'end_value' => $an_hour_later]); // The value set is an array of two values. Remember to save the $appointment_node

# Saving a timestamp
$now = (new \Drupal\Core\Datetime\DrupalDateTime('now', new \DateTimeZone('UTC')))->format('Y-m-d\TH:i:s');
$timestamp = strtotime($now);
$order_node->set('field_timestamp', $timestamp); // Remember to save

# Saving a timestamp tweaked to reflect the timezone of the site
$config_timezone = \Drupal::config('system.date')->get('timezone.default');
$now = new DrupalDateTime('now', new \DateTimeZone($config_timezone));
$timestamp = strtotime($now->format('Y-m-d\TH:i:s'));
$order_node->set('field_timestamp', $timestamp); // Remember to save

# Saving current time to a date field in a node - alternative version
$now = \Drupal::service('date.formatter')->format(time(), 'custom', 'Y-m-d\TH:i:s', 'UTC');
$order_node->set('field_order_paid_date', $now); // You need to save the $order_node to make the date stick

# Saving current date - and just the date - to a date field in a node. Fiddling with the datetime fields in content types and user accounts, you can set the field to solely store the date. Then you feed it a string:
$utc_date = \Drupal::service('date.formatter')->format(time(), 'custom', 'Y-m-d', 'UTC');
$user->set('field_membership_start', $utc_date); // You need to save the $user to make the date stick

# If you place a "use Drupal\Core\Datetime\DrupalDateTime;" at the top of your module, controller, block or form, you can cut the very complicated time fetching down to
$now = (new DrupalDateTime('now', new \DateTimeZone('UTC')))->format('Y-m-d\TH:i:s'); // slightly shorter but no less complicated.

# In all the above examples we expect the server to provide us with a UTC time. Check that this is correct whenever you install a new Drupal site!

Help improve this page

Page status: No known problems

You can: