DEV Community

Philip Birk-Jensen
Philip Birk-Jensen

Posted on • Originally published at blog.birk-jensen.dk on

Drupal: Setting the 'Date' field value

Snippet

use Drupal\Core\Datetime\DrupalDateTime;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;

// ...

// Use the DrupalDateTime object to modify (or parse) datetimes.
$datetime = new DrupalDateTime('now');
// Set the timezone to UTC (the stored timezone).
$datetime->setTimezone(new \DateTimeZone(DateTimeItemInterface::STORAGE_TIMEZONE);

// Date and time.
$entity->field_dateandtime = $datetime->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT);
// Or date only.
$entity->field_dateonly = $datetime->format(DateTimeItemInterface::DATE_STORAGE_FORMAT);
Enter fullscreen mode Exit fullscreen mode

The DrupalDateTime extends the DateTimePlus (with drupal specific functionalities), which wraps the regular PHP DateTime object (adding extra functionality and error handling).

The datetime field always saves with the STORAGE_TIMEZONE (UTC) timezone, so use the setTimezone function with a given DateTimeZone to make sure of this.

Use the correct storage format depending on the datetime_type field settings. DATETIME_STORAGE_FORMAT for Date and time or DATE_STORAGE_FORMAT for Date only.

Automatically determine date and time or date only.

For a more generic version, use the field storage settings to determine what format to save as.

use Drupal\datetime\Plugin\Field\FieldType\DateTimeItem;

// ...

// Get the setting from the field settings.
$datetime_type = $entity->field_datetime->getFieldDefinition()->getFieldStorageDefinition()->getSetting('datetime_type');

// Determine the format.
$format = match ($datetime_type) {
    DateTimeItem::DATETIME_TYPE_DATE => DateTimeItemInterface::DATE_STORAGE_FORMAT,
    DateTimeItem::DATETIME_TYPE_DATETIME => DateTimeItemInterface::DATETIME_STORAGE_FORMAT,
};

// Set using the correct format.
$entity->field_datetime = $datetime->format($format);
Enter fullscreen mode Exit fullscreen mode

What is up with timezones

Set the timezone of the input time when creating the DrupalDateTime, and set the timezone to the STORAGE_TIMEZONE format before setting the datetime field value.

// Set the timezone of the input time.
$datetime = new DrupalDateTime($time, $time_timezone);

// Set the timezone to the storage format, and set the value.
$datetime->setTimezone(new \DateTimeZone(DateTimeItemInterface::STORAGE_TIMEZONE);
$entity->field_datetime = $datetime->format($format);
Enter fullscreen mode Exit fullscreen mode

Setting field value is always the same, but it's important to know what timezone your data comes from to instantiate it with the correct zone.

Creating the DrupalDateTime object.

The DrupalDateTime defaults the timezone to the date_default_timezone_get(), but it takes a $timezone parameter (second parameter) which is the timezone of the input time (first argument).

The timezone is passed directly the DateTimeZone constructor, so it supports the following:

One of the supported timezone names, an offset value (+0200), or a timezone abbreviation (BST).

You can get a list of timezone names or abbreviation by using the static DateTimeZone::listIdentifiers() or DateTimeZone::listAbbreviations() functions.

If the input time is a timestamp or has specified a timezone, it will ignore the $timezone parameter.

// This will ignore the 'UTC' parameter.
$datetime = new DrupalDateTime('2022-05-28T12:00:00+02:00', 'UTC');
echo $datetime->format(\DateTime::ISO8601, ['timezone' => 'UTC']);
// 2022-05-28T10:00:00+0000 (notice it says 10 and not 12).

// Without the timezone it uses UTC.
$datetime = new DrupalDateTime('2022-05-28T12:00:00', 'UTC');
$datetime->format(\DateTime::ISO8601, ['timezone' => 'UTC'])
// 2022-05-28T12:00:00+0000 (stays 12, because it's in the same zone).
Enter fullscreen mode Exit fullscreen mode

If lucky the DrupalDateTime will simply read the time given, and return an object with the correct date and time. Check out the Supported Date and Time Formats in the PHP manual.

But if the input date and time format isn't parsable, the DateTimePlus (which DrupalDateTime inherits from) has some static helpers. Look for functions prefixed with createFrom and find the one suited for the current date time input.

Top comments (0)