DateObject can't be formated with dates year zero

Created on 9 May 2023, over 1 year ago

Problem/Motivation

Function date_formatter_process can't format dates of year zero

Steps to reproduce

Either use a date field and format it in some way using a date inside and then outside year zero, or try inside the function date_formatter_process the following lines:

      $a = new DateObject("0001-02-17T00:00:00", $timezone_db, $db_format);
      dpm($a->format(DATE_FORMAT_DATETIME), 'test');

This prints the correct date

      $a = new DateObject("0000-02-17T00:00:00", $timezone_db, $db_format);
      dpm($a->format(DATE_FORMAT_DATETIME), 'test');

This prints the current date (now) instead of the given date

Proposed resolution

A temporary solution in my use case was to create a DateTime Object in date_formatter_process function and replace the original DateObject in the date_format and date_format_date calls.
Inside date_formatter_process and around line 257 of date.module

[...]
      // Check to see if this date was already created by date_field_load().
      if (isset($item['db'][$processed])) {
        $date = $item['db'][$processed];
      }
      else {
        $date = new DateObject($item[$processed], $timezone_db, $db_format);
        $date->limitGranularity($field['settings']['granularity']);
      }
      
      $datetime = new DateTime($item[$processed], new DateTimeZone($timezone));
      $datetime->granularity = $date->granularity;

      $dates[$processed]['db']['object'] = $date;
      //$dates[$processed]['db']['datetime'] = date_format($date, DATE_FORMAT_DATETIME);
      $dates[$processed]['db']['datetime'] = date_format($datetime, DATE_FORMAT_DATETIME);

      date_timezone_set($date, timezone_open($timezone));
      $dates[$processed]['local']['object'] = $date;
      //$dates[$processed]['local']['datetime'] = date_format($date, DATE_FORMAT_DATETIME);
      $dates[$processed]['local']['datetime'] = date_format($datetime, DATE_FORMAT_DATETIME);
      $dates[$processed]['local']['timezone'] = $timezone;
      $dates[$processed]['local']['offset'] = date_offset_get($date);

      // Format the date, special casing the 'interval' format which doesn't
      // need to be processed.
      $dates[$processed]['formatted'] = '';
      //$dates[$processed]['formatted_iso'] = date_format_date($date, 'custom', 'c');
      $dates[$processed]['formatted_iso'] = date_format_date($datetime, 'custom', 'c');
      if (is_object($date)) {
        if ($format == 'format_interval') {
          //$dates[$processed]['interval'] = date_format_interval($date);
          $dates[$processed]['interval'] = date_format_interval($datetime);
        }
        elseif ($format == 'format_calendar_day') {
          //$dates[$processed]['calendar_day'] = date_format_calendar_day($date);
          $dates[$processed]['calendar_day'] = date_format_calendar_day($datetime);
        }
        elseif ($format == 'U' || $format == 'r' || $format == 'c') {
          //$dates[$processed]['formatted'] = date_format_date($date, 'custom', $format);
          //$dates[$processed]['formatted_date'] = date_format_date($date, 'custom', $format);
          $dates[$processed]['formatted'] = date_format_date($datetime, 'custom', $format);
          $dates[$processed]['formatted_date'] = date_format_date($datetime, 'custom', $format);
          $dates[$processed]['formatted_time'] = '';
          $dates[$processed]['formatted_timezone'] = '';
        }
        elseif (!empty($format)) {
          //$formats = _get_custom_date_format($date, $format);
          $formats = _get_custom_date_format($datetime, $format);
          $dates[$processed]['formatted'] = $formats['formatted'];
          $dates[$processed]['formatted_date'] = $formats['date'];
          $dates[$processed]['formatted_time'] = $formats['time'];
          $dates[$processed]['formatted_timezone'] = $formats['zone'];
        }
      }
[...]

I think a better solution could reside inside the date_api __construct function. something is wrong there probably in the segment below but I can't figure what.

    // The parse function will also set errors on the date parts.
    if (!empty($format)) {
      $arg = self::$allgranularity;
      $element = array_pop($arg);
      while (!$this->parse($time, $tz, $format) && $element != 'year') {
        $element = array_pop($arg);
        $format = date_limit_format($format, $arg);
      }
      if ($element == 'year') {
        return FALSE;
      }
    }

Remaining tasks

User interface changes

API changes

Data model changes

🐛 Bug report
Status

Active

Version

2.14

Component

Code

Created by

🇫🇷France erwangel

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Production build 0.71.5 2024