/Drupal 8

public static function Datelist::processDatelist

public static Datelist::processDatelist(&$element, FormStateInterface $form_state, &$complete_form)

Expands a date element into an array of individual elements.

Required settings:

  • #default_value: A DrupalDateTime object, adjusted to the proper local timezone. Converting a date stored in the database from UTC to the local zone and converting it back to UTC before storing it is not handled here. This element accepts a date as the default value, and then converts the user input strings back into a new date object on submission. No timezone adjustment is performed.

Optional properties include:

  • #date_part_order: Array of date parts indicating the parts and order that should be used in the selector, optionally including 'ampm' for 12 hour time. Default is array('year', 'month', 'day', 'hour', 'minute').
  • #date_text_parts: Array of date parts that should be presented as text fields instead of drop-down selectors. Default is an empty array.
  • #date_date_callbacks: Array of optional callbacks for the date element.
  • #date_year_range: A description of the range of years to allow, like '1900:2050', '-3:+3' or '2000:+3', where the first value describes the earliest year and the second the latest year in the range. A year in either position means that specific year. A +/- value describes a dynamic value that is that many years earlier or later than the current year at the time the form is displayed. Defaults to '1900:2050'.
  • #date_increment: The increment to use for minutes and seconds, i.e. '15' would show only :00, :15, :30 and :45. Defaults to 1 to show every minute.
  • #date_timezone: The local timezone to use when creating dates. Generally this should be left empty and it will be set correctly for the user using the form. Useful if the default value is empty to designate a desired timezone for dates created in form processing. If a default date is provided, this value will be ignored, the timezone in the default date takes precedence. Defaults to the value returned by drupal_get_user_timezone().

Example usage:

  $form = array(
    '#type' => 'datelist',
    '#default_value' => new DrupalDateTime('2000-01-01 00:00:00'),
    '#date_part_order' => array('month', 'day', 'year', 'hour', 'minute', 'ampm'),
    '#date_text_parts' => array('year'),
    '#date_year_range' => '2010:2020',
    '#date_increment' => 15,


array $element: The form element whose value is being processed.

\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.

array $complete_form: The complete form structure.

Return value



core/lib/Drupal/Core/Datetime/Element/Datelist.php, line 179


Provides a datelist element.




public static function processDatelist(&$element, FormStateInterface $form_state, &$complete_form) {
  // Load translated date part labels from the appropriate calendar plugin.
  $date_helper = new DateHelper();

  // The value callback has populated the #value array.
  $date = !empty($element['#value']['object']) ? $element['#value']['object'] : NULL;

  // Set a fallback timezone.
  if ($date instanceof DrupalDateTime) {
    $element['#date_timezone'] = $date->getTimezone()->getName();
  elseif (!empty($element['#timezone'])) {
    $element['#date_timezone'] = $element['#date_timezone'];
  else {
    $element['#date_timezone'] = drupal_get_user_timezone();

  $element['#tree'] = TRUE;

  // Determine the order of the date elements.
  $order = !empty($element['#date_part_order']) ? $element['#date_part_order'] : array('year', 'month', 'day');
  $text_parts = !empty($element['#date_text_parts']) ? $element['#date_text_parts'] : array();

  // Output multi-selector for date.
  foreach ($order as $part) {
    switch ($part) {
      case 'day':
        $options = $date_helper->days($element['#required']);
        $format = 'j';
        $title = t('Day');

      case 'month':
        $options = $date_helper->monthNamesAbbr($element['#required']);
        $format = 'n';
        $title = t('Month');

      case 'year':
        $range = static::datetimeRangeYears($element['#date_year_range'], $date);
        $options = $date_helper->years($range[0], $range[1], $element['#required']);
        $format = 'Y';
        $title = t('Year');

      case 'hour':
        $format = in_array('ampm', $element['#date_part_order']) ? 'g' : 'G';
        $options = $date_helper->hours($format, $element['#required']);
        $title = t('Hour');

      case 'minute':
        $format = 'i';
        $options = $date_helper->minutes($format, $element['#required'], $element['#date_increment']);
        $title = t('Minute');

      case 'second':
        $format = 's';
        $options = $date_helper->seconds($format, $element['#required'], $element['#date_increment']);
        $title = t('Second');

      case 'ampm':
        $format = 'a';
        $options = $date_helper->ampm($element['#required']);
        $title = t('AM/PM');

        $format = '';
        $options = array();
        $title = '';

    $default = isset($element['#value'][$part]) && trim($element['#value'][$part]) != '' ? $element['#value'][$part] : '';
    $value = $date instanceof DrupalDateTime && !$date->hasErrors() ? $date->format($format) : $default;
    if (!empty($value) && $part != 'ampm') {
      $value = intval($value);

    $element['#attributes']['title'] = $title;
    $element[$part] = array(
      '#type' => in_array($part, $text_parts) ? 'textfield' : 'select',
      '#title' => $title,
      '#title_display' => 'invisible',
      '#value' => $value,
      '#attributes' => $element['#attributes'],
      '#options' => $options,
      '#required' => $element['#required'],
      '#error_no_message' => FALSE,
      '#empty_option' => $title,

  // Allows custom callbacks to alter the element.
  if (!empty($element['#date_date_callbacks'])) {
    foreach ($element['#date_date_callbacks'] as $callback) {
      if (function_exists($callback)) {
        $callback($element, $form_state, $date);

  return $element;

© 2001–2016 by the original authors
Licensed under the GNU General Public License, version 2 and later.
Drupal is a registered trademark of Dries Buytaert.