1

I followed a very helpful article by Antonio Benitez that gave some example code showing how to create a custom date formatter for date fields (How To Create a Custom Format for a Date Field). The code adds an additional format option in the manage display settings page. This works great for date fields I have created (such as an event date for an event content type) but it is not applying to the existing date fields such as the node posted date. How can I make this custom formatter apply to system date fields such as the posted date, so that it appears as an option on the manage display page as well?

I am reproducing the code Antonio posted in his article here:

/**
 * Implements hook_field_formatter_info().
 */
function custom_module_field_formatter_info() {
  return array(
    'custom_date_format' => array(
      'label' => t('Custom date format'),
      'field types' => array('date', 'datestamp', 'datetime'),
      'multiple values' => FIELD_BEHAVIOR_DEFAULT,
    ),
  );
}

/**
 * Implements hook_field_formatter_view().
 */
function custom_module_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $elements = array();
  foreach ($items as $delta => $item) {
    $element = array(
      'element' => $item,
      'field' => $instance,
      'display' => $display
    );
    $elements[$delta] = array(
      '#theme' => 'custom_module_formatter_' . $display['type'],
      '#element' => $element,
      '#field' => $field,
    );
  }

  return $elements;
}

/**
 * Implements hook_theme().
 */
function custom_module_theme() {
  $themes = array(
    'custom_module_formatter_custom_date_format' => array(
      'variables' => array(
        'element' => NULL,
        'field' => NULL,
      ),
    ),
  );
  return $themes;
}

/**
 * Implements theme function
 */
function theme_custom_module_formatter_custom_date_format($vars) {
  $element = $vars['element'];
  $field = $vars['field'];

  // Configure custom date
  $format_date = 'd M';
  $timezone_bd = date_get_timezone_db($field['settings']['tz_handling']);
  $publish_date = DateTime::createFromFormat('Y-m-d H:i:s', $element['element']['value'], new DateTimeZone($timezone_bd));
  $date = format_date($publish_date->getTimestamp(), 'custom', $format_date);
  $date = explode(' ', $date);

  // Declare array for render content with custom format and tags
  $render_array = array(
    'date' => array(
      'date-day' => array(
        '#prefix' =>'<span class="date-day">',
        '#markup' => $date[0],
        '#suffix' => '</span>'
      ),
      'date-month' => array(
        '#prefix' =>'<span class="date-month">',
        '#markup' => $date[1],
        '#suffix' => '</span>'
      ),
    ),
    '#theme_wrapper' => array('container'),
  );

  return render($render_array['date']);
}
3
  • 2
    The created value isn't a field as such it's a property on the node so that will be why you can't use your code. You'd probably need to create a new date format under "configuration > regional and language > date and time > formats" that matched the format you want. Then that will be available as an option to use in views/drupal date formatting functions
    – Leigh
    Mar 1, 2019 at 13:46
  • Thanks Leigh for your comment. Creating a new format from the date and time configuration page doesn't work for me as I want to split the date up into seperate parts divided by <span> tags. This is because I want to target the day and month and year seperately using css. I guess I could use Javascript as an alternative to add in the <span> tags.
    – Ben
    Mar 1, 2019 at 13:56
  • I forgot to say that creating new date and time formats on the configuration page doesn't allow adding in html tags.
    – Ben
    Mar 1, 2019 at 13:57

1 Answer 1

1

In Drupal 7, the created and updated "fields" on nodes (and other entities) are properties and not proper fields. The display values for these are created in the default template_preprocess_node() provided by core, which some theme and modules may override.

Note these lines:

$variables['date'] = format_date($node->created);
...
// Display post information only on certain node types.
if (variable_get('node_submitted_' . $node->type, TRUE)) {
  $variables['display_submitted'] = TRUE;
  $variables['submitted'] = t('Submitted by !username on !datetime', array(
    '!username' => $variables['name'],
    '!datetime' => $variables['date'],
  ));
  ...
}

So, if you want to change how this is displayed, you need to implement your own template_preprocess_node() (you can do this in a theme or module), and provide your own logic. You can either update the existing variables, which will allow the existing templates to be used, or you can add new variables and also provide your own node templates. Typically, I do the later.

3
  • Thanks very much mpdonadio. That is really helpful. I forgot to mention I am using Display Suite to add in the Date Posted field in the display. Display Suite allows me to select a format for the Date Posted field but the custom format generated by the code above does not appear in the options list, as it does for the event date format options. Apologies for not including this information in my question.
    – Ben
    Mar 1, 2019 at 15:04
  • @Ben I don't have a site with DS handy now, but I believe you need to add the custom format in admin/config/regional/date-time/formats and then it will appear in that list. In general, using defined formats is best instead of custom options in formatters.
    – mpdonadio
    Mar 1, 2019 at 17:37
  • Thanks for your comment. I would have used the admin date-time formats only I wanted to add span tags between the day, month and year so I could target them separately using CSS, and using the admin formats do not allow tags in the date format. Thank you for your help.
    – Ben
    Mar 2, 2019 at 8:37

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.