8

I already asked a question like this (Set date field in D8).

Ok duplicate entry? NO!

Now i have also to set a time and i'm using a array. My code looks like this.

$field_array = [
##begin of creating node
'uid' => $new_old_uid["new_uid"],
'type' => $content_type,
'langcode' => $lang,
'status' => (!empty($import_node->status)) ? $import_node->status : 0,

#### How to create date with times?
#Every Version causes that error -> Array to string conversion in ....
### Version 1
'field_event_date_start' => [[ "value"=> date('Y-m-d H:i:00',$imported_date) ]],
'field_event_date_end' => [[ "value"=> date('Y-m-d H:i:00',$imported_date) ]],
### Version 2
'field_event_date_start' => [ "value"=> date('Y-m-d H:i:00',$imported_date) ],
'field_event_date_end' => [ "value"=> date('Y-m-d H:i:00',$imported_date) ],


### How to add a url?
'field_event_url' => (!empty($import_node->field_event_url)) ? array('value'=> $imported_url) : null,
];

UPDATE: Another try for datetime field:

'field_event_date_start' => array(
    "value" => array(
        "date" => date('Y-m-d',$imported_date),
        "time" => date('H:i:00',$imported_date)
    ),
),

Now I'm getting following error: Placeholders must have a trailing [] if they are to be expanded with an array of values.

5 Answers 5

17

Datetime fields in Drupal 8 are stored as strings. So you need to convert it into string.

You can use the format method, e.g.

$formatted_date = $date->format('Y-m-d H:i:s');

Refer Inserting the value from Datetime field form

You can also use T as separator,

Like:

\DateTime::format("Y-m-d\TH:i:s"); //need a escape character in front of T.

Refer Why is my Datetime field not saved?

2
  • 1
    thx works like charm!
    – themca
    Sep 20, 2016 at 7:14
  • 1
    @DRUPWAY, do you want to update your answer to use the DateTimeItemInterface constants. Nov 10, 2021 at 22:21
9

If your date field is not a DATETIME but a DATE, use a different format. And a better solution would be to use the Datime object constant to get the format.

constant DATETIME_STORAGE_FORMAT :: string(12) "Y-m-d\TH:i:s"
constant DATE_STORAGE_FORMAT :: string(5) "Y-m-d"

Working example.

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

$dtime = DateTime::createFromFormat("m/d/Y - G:i", $row->Date); // not needed
$dtime->setTimezone(new \DateTimezone(DateTimeItemInterface::STORAGE_TIMEZONE));
$dtimeFormat = $dtime->format(DateTimeItemInterface::DATE_STORAGE_FORMAT);
    
$article->set('field_date', $dtimeFormat);
8

Since Drupal 8.5.x this works a little differently.

Firstly it's good practice to set the timezone explicitly so you know what is going on:

Set the timezone:

$timezone = new \DateTimeZone('UTC');
// Or
$timezone = new \DateTimeZone(date_default_timezone_get());
// Or 
$timezone = new \DateTimeZone(DateTimeItemInterface::STORAGE_TIMEZONE);

Then create the date object using the PHP DateTime class:

$date_time = new \DateTime('now', $timezone);
$drupal_date_time = DrupalDateTime::createFromDateTime($date_time);

Or the DrupalDateTime class:

$drupal_date_time = new DrupalDateTime('yesterday', $timezone);

I like to use DateTime (or DateTimeImmutable) and then pass into the DrupalDateTime wrapper. That way native methods are highlighted in the IDE and also date comparisons (e.g. $now > $somedatetime work reliably.

Prior to saving the date/time you must set the timezone to DateTimeItemInterface::STORAGE_TIMEZONE:

$drupal_date_time->setTimezone(new \DateTimeZone(DateTimeItemInterface::STORAGE_TIMEZONE))

You can then format the date for storage using the the DateTimeItemInterface::DATETIME_STORAGE_FORMAT constant:

$drupal_date_time->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT)

Here is an example usage:

$node = $this->entityTypeManager
    ->getStorage('node')
    ->create([
      'type' => 'article',
      'title' => 'test',
    ]);
// Get the default timezone
$default_timezone = new \DateTimeZone(date_default_timezone_get());
// Set some date/time objects
$now = new \DateTime('now', $default_timezone);
$yesterday = new \DateTime('yesterday', $default_timezone);

// Compare the dates
if($yesterday < $now){
  // Do some stuff
}

// Optionally convert to DrupalDateTime if you need the custom methods, etc
$now = DrupalDateTime::createFromDateTime($now);
$yesterday = DrupalDateTime::createFromDateTime($yesterday);

// Get the storage timezone
$storage_timezone = new \DateTimeZone(DateTimeItemInterface::STORAGE_TIMEZONE);

// Save the dates to the fields
$node->set(
    'field_date_now',
    $now
      ->setTimezone($storage_timezone)
      ->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT)
);
$node->set(
    'field_date_yesterday',
    $yesterday
      ->setTimezone($storage_timezone)
      ->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT)
);

$node->save();

A bonus example — find nodes with a date/time field value that matches a 24hr window:

$date = new \DateTimeImmutable('now - 1 month', new \DateTimeZone(date_default_timezone_get()));

$start_time = $date->modify('midnight');
$start_time = DrupalDateTime::createFromDateTime($start_time);
$end_time = $date->modify('+1 day midnight -1 second');
$end_time = DrupalDateTime::createFromDateTime($end_time);

// Find all NODES with date times that match the 24hr window
$query = \Drupal::entityQuery('node')
  //      ->condition('status', 1)
  ->condition('type', 'event')
  ->condition(
    'field_date',
    $start_time
      ->setTimezone(new \DateTimeZone(DateTimeItemInterface::STORAGE_TIMEZONE))
      ->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT),
    '>='
  )
  ->condition(
    'field_date',
    $end_time
      ->setTimezone(new \DateTimeZone(DateTimeItemInterface::STORAGE_TIMEZONE))
      ->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT),
    '<='
  )
2
5

This is what worked for me:

$timestamp = \Drupal::time()->getRequestTime();
$date = DrupalDateTime::createFromTimestamp($timestamp, 'UTC');
$entity->field_date = $date->format("Y-m-d\TH:i:s");
1
  • 1
    You are hardcoding the storage format and timezone. This will work for now, but it may break silently in future versions. You want this: $timestamp = \Drupal::time()->getRequestTime(); $date = DrupalDateTime::createFromTimestamp($timestamp, DateTimeItemInterface::STORAGE_TIMEZONE); $storableDate = $date->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT); $entity->set('field_date, $storableDate);
    – Jonathan
    Oct 15, 2022 at 19:07
2

This works great for date fields, as noted. However, if you need to update a timestamp based field use something like:

 $entityref->set('field_timestamp_field', $source_date->getTimestamp());

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.