Advertising sustains the DA. Ads are hidden for members. Join today

Example - Theme all-day events without a time.

Last updated on
30 April 2025

Here's an example of how to apply the theme_date_display_combination override.
In this example, we want to:

  • Theme "all-day events" so the time is not shown (users set time to 0:00 to indicate all day*)
  • Theme "multi-day all-day events" so they show, for example, Jan. 1 - 5, 2008 or Jan. 28 - Feb. 2, 2008
  • Theme "single-day, multi-time events" so they show, for example, Tues. Jan. 1 - 11:00 am - 2:30 pm

(* From a usability perspective, it would be better to add a CCK checkbox field for all-day events, and then utilize that here - this can be done fairly easily and is left as an exercise...)

The primary difficulty here is that the dates are already formatted when we get them. A more elegant solution could be achieved by overriding the theme_date_formatter() function - but that is beyond the scope of this tutorial, which provides a simpler (but slightly "hack'ish") approach.
To this end, I need to make 2 assumptions (be sure they apply to you!):

  1. All date formats used will specify a dash, - , to separate the time from the date. Most date formats do this, but not all. Check the comments in the code for the places this is important.
  2. For "multi-day all-day events" you never want to show the Day name. Thus, the format for this type of date is fixed in the code - the admin settings for date formats are totally ignored for these types of events.

The original idea for this example came from: http://drupal.org/node/211668
This code goes into your template.php file.

function phptemplate_date_display_combination($field, $dates, $node = NULL) {

   // If there is no From date - get out...
  if (empty($dates['value']['formatted'])) {  
    return;
  }

  $date1 = $dates['value']['object']->db;  // the "From" date
  $date2 = $dates['value2']['object']->db; // the "To" date

  // Same From and To Date and Time, don't consider the To date...
  if ($date1->timestamp == $date2->timestamp) {
    unset($date2);
  }
  
  $sameDay = $date1->parts['year'] == $date2->parts['year'] &&
             $date1->parts['yday'] == $date2->parts['yday'];
  
  $sameTime = $date1->parts['hours'] == $date2->parts['hours'] &&
              $date1->parts['minutes'] == $date2->parts['minutes'];  // to the nearest  minute
  
  // All day events have only a from date with a time of 0:00
  $allDay = (empty($date2) && !_isTimeSet($date1));

  // All day, multi-day events have both times set to 0:00
  $multiDay = !_isTimeSet($date1) && !empty($date2) && !_isTimeSet($date2);
  
  $sameMonth = $date1->parts['mon'] == $date2->parts['mon'];
  
  if ($allDay) { //this is an all day, single-day event
    // Assumption 1:  stripping time off formatted date based on location of dash!
    $dashPos = strpos($dates['value']['formatted'],'-');  // find start of time portion
    $formattedDate= substr($dates['value']['formatted'],0,$dashPos);  // strip off time
       // Here is an alternate that hard-codes the date format (Jan. 1, 2008)  
       // $formattedDate = date('F j, Y', $date1->timestamp);
    return '<span class="date-display-single">'. $formattedDate .'</span>';
  }
  elseif ($multiDay) { //this is an all day, multi-day event
    // Assumption 2:  The date formats here are hard-coded....
    $startDate = date('F j', $date1->timestamp);
    $endFormat = ($sameMonth?'j, Y':'F j, Y');
    $endDate = date($endFormat, $date2->timestamp);
    return _theme_date_range($startDate, $endDate);
  }
  elseif ($sameDay && !$sameTime) {  //this is a single day, multi-time event
    $startDate = $dates['value']['formatted'];
    $date = $dates['value2']['formatted'];
    $dashPos = strpos($date,'-');  // find start of time portion
    $endDate= substr($date, $dashPos+2, strlen($date));  // grab just the time
       // Here is an alternate that hard-codes the end time format (2:30pm)  
       // $endDate = date('g:ia', $date2->timestamp);
    return _theme_date_range($startDate, $endDate);
  }
  else { //single day/time event or multi-day/multi time event - let default themer do it
    return theme_date_display_combination($field, $dates, $node);
  }
}

/**
 * Helper to determine if the time for a given date is set to 0:00
 * Returns true if a 'valid' time is set,  false if time is 0:00
 */
function _isTimeSet($date) {
  return $date->parts['hours']!=0 || $date->parts['minutes']!=0;  // to nearest minute only
}

/**
 * Helper function to theme a pair of dates as:  StartDate - EndDate
 * Note extra class added : date-display-short-end
 * This can be used to override the default CSS, which puts a line-break between dates.
 */
function _theme_date_range($startDate, $endDate) {
  return '<span class="date-display-start">'. $startDate .
  '</span><span class="date-display-separator"> - </span><span class="date-display-end date-display-short-end">'.
  $endDate .'</span>';  
}

Help improve this page

Page status: Not set

You can: