11

I have created field type "Timestamp" in my Drupal 8 node. Field is not required. In field settings default value, there is HTML 5 datetime picker, in which you can select default date/time or leave values as on picture:

enter image description here

But the Drupal behavior seem to be little bit strange - when you select default date, this value is set on node save (this is correct). When you leave field blank (values as on picture) it saves field with time of form submission (it is stated in field comment, so it is not a bug)... But how to disable default value, when you just want to leave field blank as it is possible with all other fields (e.g. text, number, ...)? I do not see any settings for this in this field configuration. Also this is not logical, beucase when you leave other fields blank, they are really blank. When you leave this field type blank, it still saves value (some additional checkbox will be more logical)?

Thanks

0

3 Answers 3

12

There is backstory to this that is a little complicated.

The Timestamp field type was added back into Drupal 8.2.0 core as a "UI Field". The field type had always been there, just as a behind-the-scenes field, and used as the base field for CreatedItem and ChangedItem for entity timestamps (which are both non-UI field types).

If this field is rendered out on with the proper widget on the edit page (see bug), then you end up using TimestampDatetimeWidget. This widget has a ::massageFormValues() method, which enforces the current time being used (at save) as the field value if the element is empty.

So, the behavior you are seeing is by-design. The widget was initially intended for entity edit pages, where created and changed timestamps never have empty values after the entity is saved. When this field was added as a UI field, it inherited the widget and its behavior.

If you really want a timestamp and don't want this behavior, you need to make a custom module and make your own widget. You should just be able to copy TimestampDatetimeWidget into the module, rename it, update the annotation, and update the ::massageFormValues() method:

  • remove the else branch containing $date = new DrupalDateTime(); - this won't set the default datetime
  • handle unset $date variable, example: $item['value'] = !empty($date) ? $date->getTimestamp() : NULL;

That should allow you to have empty timestamps.

Personally, I would not use Timestamp fields, though. I would use Date fields, which can have empty values or default values, and better widgets and formatters in general.

6
  • This sounds like the default MySQL behavior for any timestamp field in a table. So I can understand what's going on here -- if not documented in the Field UI. Subtle changes like this, and like the Views mini pager [drupal.org/node/2798521] giving bad result counts, or missing tokens drupal.org/node/2821810, are examples where Drupal 8's current status seemed to have either accrued regression bugs not present in D7, or not have been properly thought out for a project now 1 year old :D
    – tenken
    Nov 21, 2016 at 15:51
  • @tenken TimestampItem are just plain ints, not timestamps. The various date/time formats are not really portable across different databases, so DB specific functions and behaviors for them are avoided as much as possible. Default values are handled by the Field API. Timestamps don't have them, but CreatedItem and ChangedItem do, but those two aren't available from the UI. I have manually tested this can cannot reproduce the OP's problem, but the bug I mention will prevent this field from being used properly (the linked issue has a patch on it). [edit, this comment is partially incorrect].
    – mpdonadio
    Nov 21, 2016 at 23:03
  • I updated the answer to this to be more correct, and to reflect the proper history.
    – mpdonadio
    Nov 22, 2016 at 20:59
  • Thank you, I will check it. Personally, I am using timestamp field because I want to store only timestamps, not full dates with timezones and other information. I wanted to simplify it this way :) Nov 23, 2016 at 8:18
  • @mpdonadio I have tester it little deeper, and there is problem with saving the field when it has value if you delete whole ::massageFormValues() method. You only need to comment else, where default date is setting up $date = new DrupalDateTime(); and treat the date variable when it will be non-existent $item['value'] = $date->getTimestamp();. Please update your answer to reflect these "bugs". Thanks. Dec 8, 2016 at 9:14
0

Here is the quick solution: instead of timestamp use date field with datetime widget and convert the datetime to timestamp with strtotime() function.

Example:

$datetime = $node->get('field_date')->getValue()[0]['value'];
$timestamp = strtotime($datetime);
0

The below solution that worked for me as of drupal 10.

use case: I needed it for event time addition and I also needed both date & time fields.

//logic

Checked the last node updated time vs actual user time added. If the user time is same as last node updated time , then the field must be empty.(ignored some extreme cases where , both of them will be same since in my case most events will be some time in future not immediate)

//code

function __get_validated_timestamp_value($timestamp_field_name, $entity) {
    if($entity->get($timestamp_field_name)->getValue()) {
        $actual_value = $entity->$timestamp_field_name->getValue()[0]['value'];
        $node_submitted_time = $entity->getChangedTime();
        
        $field_item = $entity->get($timestamp_field_name);
        if ($field_item->isEmpty()) {
            return null;
        }
        if($actual_value == $form_submiited_time) {
            return null;
        }
        return $actual_value;
    }
    return null;
}

invoked and used like below

if($node->get('field_event_start_time')) {
 $start_timestamp = __get_validated_timestamp_value('field_event_start_time', $node);
}

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.