CCK: Defines a date/time field type for the content module and a date API. Note: Requires content.module.');
break;
case 'admin/help#date':
$output = t('
Date Module
The date module defines a highly configurable date/time field type for the content module and a date API that can be used by other applications.
Dates can use GMT, the site\'s timezone or a date-specific timezone and are converted to GMT and stored as either a Date (ISO 8601 YYYY-MM-DDTHH:MM:SS) or a Datestamp (a unix timestamp). When displayed, they are converted back to the desired timezone value and displayed using the desired display format.
Display formats include numerous combinations of date parts, sequences, and separators, to accomodate international date formatting needs.
Date Field Types
You have a choice of creating an ISO date or a unix timestamp. If you are porting information from another application you may want to create a field using a type that matches the source data. Some advantages and disadvantages of each include:
- Unix Timestamp
- Stores the date as an integer.
- Takes up less room in the database because it\'s smaller.
- Often easier to use for date calculations because you can increase or decrease it just by adding or subtracting seconds.
- It is the format used by php date functions.
- It must be filled with a complete date -- year, month, day, hour, minute, second, so you sometimes have to arbitrarily set some of these values even if they are not applicable.
- ISO Date
- Stores the date in an ISO format (YYYY-MM-DDTHH:MM:SS).
- The data is in a human-readable form.
- You can use it for incomplete dates, i.e. only a year or only a year and a month, and pad the other values with zeros, so it does not appear to be any more precise than it really is.
- It is a format that is internationally-recognized, and it is used as-is on many web sites and in many applications.
Date Widgets
There are several widgets to choose from to control how users can enter data for this field.
- Text Field
- The Text Field date widget uses the strtotime function to construct a date and will accept input allowed by the php strtotime function. This allows the user to type a date in in many natural formats, like March 31, 1980 or 3/10/1980 or in numeric formats like YYYY-MM-DD.
The strtotime function will assume date shortcuts are in American format (MM/DD/YY), and it will not work for dates prior to 1970.
- Select List
- The Select List date widget presents users with a drop-down list or textfield for each part of the date (year, month, day, hour, etc.). The whole selector is collapsed onto a single line using css (except for the timezone selector, if date-specific timezones are collected). The selector is highly configurable and will even handle years prior to 1900.
- Javascript Pop-up Calendar
- The Javascript Pop-up Calendar is offered as an input alternative if the jscalendar module is installed. This widget can handle dates as early as 1900.
');
if (module_exists('views')) {
$output .= date_views_help();
}
return $output;
break;
}
}
/**
* Implementation of hook_field_info().
*/
function date_field_info() {
return array(
'date' => array('label' => 'Date'),
'datestamp' => array('label' => 'Datestamp'),
);
}
/**
* Implementation of hook_field_settings().
*/
function date_field_settings($op, $field) {
include_once(drupal_get_path('module', 'date') .'/date.inc');
switch ($op) {
case 'form':
if (!module_exists('event')) {
include_once(drupal_get_path('module', 'date') .'/date_timezones.inc');
} else {
include_once(drupal_get_path('module', 'event') .'/event_timezones.inc');
}
$form = array();
$tz_handling = $field['tz_handling'] ? $field['tz_handling'] : 'site';
$form['input'] = array(
'#type' => 'fieldset',
'#title' => t('Input options'),
);
$options = array(
'Y' => t('Year'),
'M' => t('Month'),
'D' => t('Day'),
'H' => t('Hour'),
'N' => t('Minute'),
'S' => t('Second'),
//'T' => t('Timezone'),
);
$form['input']['granularity'] = array(
'#type' => 'select',
'#title' => t('Granularity'),
'#default_value' => $field['granularity'] ? $field['granularity'] : array('Y', 'M', 'D'),
'#options' => $options,
'#multiple' => TRUE,
'#size' => min(count($options), 6),
'#description' => t('Set the date elements to be collected on input (at least a year is required).'),
);
$form['input']['todate'] = array(
'#type' => 'select',
'#title' => t('To Date'),
'#options' => array('' => t('Never'), 'optional' => t('Optional'), 'required' => t('Required')),
'#description' => t('Display a matching second date field as a \'To\' date. If marked \'Optional\' field will be presented but not required. If marked \'Required\' the \'To\' date will be required if the \'From\' date is required or filled in.'),
'#default_value' => $field['todate'] ? $field['todate'] : '',
);
$form['input']['advanced'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced input options'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['input']['advanced']['input_format'] = array(
'#type' => 'select',
'#title' => t('Input format'),
'#default_value' => $field['input_format'] ? $field['input_format'] : 'site_format',
'#options' => date_input_options(),
'#description' => t('The specified format will be adapted to the chosen granularity. The \'default\' value uses the \'short date format\' defined in !settings', array('!settings' => l("admin/settings", "admin/settings"))),
);
$form['input']['advanced']['input_format_custom'] = array(
'#type' => 'textfield',
'#title' => t('Custom input format'),
'#default_value' => $field['input_format_custom'] ? $field['input_format_custom'] : '',
'#description' => t('The custom format, if provided, will override the input format selected above. See more about custom date formats below.'),
);
$form['output'] = array(
'#type' => 'fieldset',
'#title' => t('Display Options'),
'#description' => t('Choose the way the date should be displayed.'),
);
$default_formatter = date_formatter_setup_form($field, 0);
$form['output'][] = $default_formatter;
$form['output']['advanced'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced display options'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#description' => t('Define alternate formatting for the date display. Options other than the default are made available to views and themes. Possible formats are default, long, medium, and short.'),
);
for ($i = 1; $i <= 3; $i++) {
$form['output']['advanced'][$i] = date_formatter_setup_form($field, $i);
}
$form['timezone'] = array(
'#type' => 'fieldset',
'#title' => t('Timezone options'),
);
$form['timezone']['tz_handling'] = array(
'#type' => 'select',
'#title' => t('Time zone handling'),
'#default_value' => $tz_handling,
'#options' => date_timezone_handling_options(),
'#description' => t('Select the timezone handling method to be used for this date field'),
);
$form['timezone']['advanced'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced timezone options'),
'#collapsible' => TRUE,
'#collapsed' => (date_get_site_timezone() ? TRUE : FALSE),
);
// need a way to identify the correct system timezone from an array of timezones with the same offset
// save it as a system variable so it will default to the correct value after the first time it is set
// aligns with system setting 'date_default_timezone'
$form['timezone']['advanced']['field_timezone'] = array(
'#type' => 'select',
'#title' => t('Site timezone'),
'#default_value' => date_get_site_timezone(),
'#options' => drupal_map_assoc(date_timezone_options(variable_get('date_default_timezone', 'GMT'))),
'#description' => t('Select the timezone to be used as the site\'s timezone for all date fields in every content type in which they appear. List includes GMT and all timezones with the same GMT offset as the site timezone setting.'),
);
$form['#suffix'] = t('');
return $form;
case 'validate':
date_set_site_timezone($field['field_timezone']);
if (!in_array('Y', $field['granularity'])) {
form_set_error($field['field_name'], t('Input granularity must include a year.'));
}
break;
case 'save':
$options = array('granularity', 'field_timezone', 'tz_handling', 'input_format', 'input_format_custom', 'todate');
for ($i = 0; $i <= 3; $i++) {
switch ($i) {
case (1):
$name = 'long';
break;
case (2):
$name = 'medium';
break;
case (3):
$name = 'short';
break;
default:
$name = 'default';
}
$append = ($i > 0 ? '_'. $name : '');
$options[] = 'output_format_date'. $append;
$options[] = 'output_format_zone'. $append;
$options[] = 'output_format_custom'. $append;
}
return $options;
case 'database columns':
return date_columns($field);
case 'filters':
return date_views_filters($field);
}
}
/**
* A form to create a date formatter option
*/
function date_formatter_setup_form($field, $delta) {
switch ($delta) {
case (1):
$name = 'long';
$label = t('Long');
$default = variable_get('date_format_long', 'l, F j, Y - H:i');
break;
case (2):
$name = 'medium';
$label = t('Medium');
$default = variable_get('date_format_medium', 'D, m/d/Y - H:i');
break;
case (3):
$name = 'short';
$label = t('Short');
$default = variable_get('date_format_short', 'm/d/Y - H:i');
break;
default:
$name = 'default';
$label = t('Default');
$default = variable_get('date_format_short', 'm/d/Y - H:i');
}
$append = ($delta > 0 ? '_'. $name : '');
$form = array(
'#type' => 'fieldset',
'#title' => $label,
);
$form['output_format_date' . $append] = array(
'#type' => 'select',
'#title' => t('Date display'),
'#default_value' => $field['output_format_date'. $append] ? $field['output_format_date'. $append] : $default,
'#options' => date_output_options($tz_handling),
'#multiple' => false,
);
$form['output_format_zone' . $append] = array(
'#type' => 'select',
'#title' => t('Zone display'),
'#default_value' => $field['format_zone'. $append] ? $field['format_zone'. $append] : '',
'#options' => date_append_zone_options(),
);
$form['output_format_custom' . $append] = array(
'#type' => 'textfield',
'#title' => t('*Custom date format'),
'#default_value' => $field['output_format_custom' . $append] ? $field['output_format_custom'. $append] : '',
);
return $form;
}
/**
* Implementation of hook_field().
*
*/
function date_field($op, &$node, $field, &$items, $teaser, $page) {
if ($field['todate']) {
$process = array('value', 'value2');
}
else {
$process = array('value');
}
include_once(drupal_get_path('module', 'date') .'/date.inc');
switch ($op) {
case 'validate':
$formats = date_get_formats($field);
foreach ($items as $delta => $item) {
// if multiple dates are allowed, need to adjust validation criteria on extra fields
// must allow for way to omit unused date fields, so dates with an empty 'year' field will not be validated or saved
$params['required'] = ($field['required'] && $delta == 0) ? 1 : 0;
if ($delta > 0) $params['opt_fields'] = array('year', 'month', 'day');
$params['granularity'] = date_granularity_array($field);
foreach ($process as $processed) {
$error_field = $field['field_name'] .']['. $delta .']['. $processed;
$error = date_text_validate(trim($item[$processed]), $error_field, $field['type'], $formats['input']['text'], $params['required'], date_granularity_array($field));
if ($processed == 'value' && $field['todate'] && !$item['value']['year'] && $items[$delta]['value2']['year']) {
form_set_error($error_field, t("A 'From' date is required for the %delta value of %field", array('%delta', intval($delta + 1), '%field', $field['field_name'])));
}
if ($processed == 'value2' && $field['todate'] == 'required' && ($field['required'] || $items[$delta]['value']['year']) && !$item['value2']['year'] ) {
form_set_error($error_field, t("A 'To' date is required for the %delta value of %field", array('%delta', intval($delta + 1), '%field', $field['field_name'])));
}
}
}
return;
}
}
/**
* Implementation of hook_widget_info().
*/
function date_widget_info() {
$info = array(
'date_select' => array(
'label' => t('Select List'),
'field types' => array('date', 'datestamp'),
),
'date_text' => array(
'label' => t('Text Field with strtotime validation'),
'field types' => array('date', 'datestamp'),
),
);
if (module_exists('jscalendar')) {
$info['date_js'] = array(
'label' => t('Text Field with javascript pop-up calendar'),
'field types' => array('date', 'datestamp'),
);
}
return $info;
}
/**
* Implementation of hook_widget_settings().
*/
function date_widget_settings($op, $widget) {
include_once(drupal_get_path('module', 'date') .'/date.inc');
switch ($op) {
case 'callbacks':
return array('default_value' => TRUE);
case 'form':
$form = array();
if ($widget['type'] == 'date_select') {
$form['input']['advanced'] = array(
'#type' => 'fieldset',
'#title' => t('Advanced select options'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['input']['advanced']['select_day'] = array(
'#type' => 'select',
'#title' => t('Days'),
'#default_value' => isset($widget['select_day']) ? $widget['select_day'] : 1,
'#options' => array(0 => t('text field'), 1 => t('select list')),
'#description' => t('Type of form to use for day selection.'),
);
$form['input']['advanced']['select_month'] = array(
'#type' => 'select',
'#title' => t('Months'),
'#default_value' => isset($widget['select_month']) ? $widget['select_month'] : 1,
'#options' => array(0 => t('text field'), 1 => t('select list')),
'#description' => t('Type of form to use for month selection.'),
);
$form['input']['advanced']['select_year'] = array(
'#type' => 'select',
'#title' => t('Years'),
'#default_value' => isset($widget['select_year']) ? $widget['select_year'] : 1,
'#options' => array(0 => t('text field'), 1 => t('select list')),
'#description' => t('Type of form to use for year selection.'),
);
$form['input']['advanced']['years_back'] = array(
'#type' => 'textfield',
'#title' => t('Years back'),
'#default_value' => $widget['years_back'] ? $widget['years_back'] : 3,
'#size' => 2,
'#maxsize' => 2,
'#description' => t('Number of years to go back when using a selection list.'),
);
$form['input']['advanced']['years_forward'] = array(
'#type' => 'textfield',
'#title' => t('Years forward'),
'#default_value' => $widget['years_forward'] ? $widget['years_forward'] : 3,
'#size' => 2,
'#maxsize' => 2,
'#description' => t('Number of years to go forward when using a selection list.'),
);
$form['input']['advanced']['increment'] = array(
'#type' => 'select',
'#title' => t('Time increment'),
'#default_value' => $widget['increment'] ? $widget['increment'] : 1,
'#options' => array(1 => 1, 5 => 5, 10 => 10, 15 => 15, 30 => 30),
'#description' => t('Increment the minute and second fields by this amount.'),
);
}
return $form;
case 'save':
cache_clear_all('date_formats:'. $widget['field_name'] .':'.$widget['type_name'], 'cache');
return array('increment', 'select_day', 'select_month', 'select_year', 'years_back', 'years_forward');
}
}
/**
* Implementation of hook_widget().
*/
function date_widget($op, &$node, $field, &$items, $delta = NULL) {
include_once(drupal_get_path('module', 'date') .'/date.inc');
if ($field['todate']) {
$process = array('value', 'value2');
}
else {
$process = array('value');
}
$max = $field['multiple'] ? 2 + sizeof($items) : 0;
switch ($op) {
case 'default value':
return date_default_value($node, $field, $items, $delta);
case 'form':
$form = array();
$form[$field['field_name']]['#tree'] = TRUE;
$form[$field['field_name']]['#theme'] = 'date_form_fieldgroup';
// Multiple value and from/to fields need a field title at the top of the form.
if ($field['multiple'] || $field['fromto']) {
$form[$field['field_name']]['#title'] = $field['widget']['label'];
}
$tz_handling = $field['tz_handling'] ? $field['tz_handling'] : 'site';
$function = 'date_widget_' . $field['widget']['type'];
foreach (range(0, $max) as $delta) {
$granularity = date_granularity_array($field);
if ($tz_handling == 'date') array_push($granularity, 'T');
$timezone = date_get_timezone($tz_handling, $items[$delta]['timezone']);
$params = array(
'label' => $field['widget']['label'],
'value' => $items[$delta]['value'],
'weight' => $field['widget']['weight'],
'delta' => $delta,
'granularity' => $granularity,
'format' => $field['type'],
'timezone_out' => ($items[$delta]['value'] && $field['required'] ? $timezone : ''),
'timezone_in' => ($items[$delta]['value'] && $field['required'] ? 'GMT' : ''),
'description' => $field['widget']['description'],
'select_day' => $field['widget']['select_day'],
'select_month' => $field['widget']['select_month'],
'select_year' => $field['widget']['select_year'],
'years_back' => $field['widget']['years_back'],
'years_forward' => $field['widget']['years_forward'],
);
$params['required'] = ($field['required'] && $delta == 0) ? 1 : 0;
$params['formats'] = date_get_formats($field);
switch ($field['widget']['type']) {
case ('date_select'):
if ($delta > 0) $params['opt_fields'] = array('year', 'month', 'day');
if ($delta > 0 || (!$params['required'] && $params['value'] == '')) $params['blank_default'] = 1;
$params['increment'] = $field['widget']['increment'];
// use the api date selector form from date.inc to create the date selector form
if (!$field['todate']) {
$form[$field['field_name']][$delta]['value'] = date_select_input($params);
$form[$field['field_name']][$delta]['#empty'] = empty($items[$delta]['value']['year']) ? TRUE : FALSE;
}
else {
$params['label'] = t('From:');
$form[$field['field_name']][$delta]['value'] = date_select_input($params);
$params['label'] = t('To:');
$params['value'] = $items[$delta]['value2'];
$params['required'] = $field['todate'] == 'required' && ($field['value'] || $field['required']) ? TRUE : FALSE;
$form[$field['field_name']][$delta]['value2'] = date_select_input($params);
$form[$field['field_name']][$delta]['value2']['#weight'] += .1;
$form[$field['field_name']][$delta]['#empty'] = empty($items[$delta]['value']['year']) && empty($items[$delta]['value2']['year']) ? TRUE : FALSE;
}
break;
default:
// use the api text input form from date.inc
if ($delta > 0) $params['blank_default'] = 1;
$params['jscalendar'] = $field['widget']['type'] == 'date_js' ? 1 : 0;
if ($delta > 0 || (!$params['required'] && $params['value'] == '')) $params['blank_default'] = 1;
if (!$field['todate']) {
$form[$field['field_name']][$delta] = date_text_input($params);
$form[$field['field_name']][$delta]['#empty'] = empty($items[$delta]['value']) ? TRUE : FALSE;
}
else {
$params['label'] = t('From:');
$params['field_name'] = 'value';
$form[$field['field_name']][$delta] = date_text_input($params);
$params['label'] = t('To:');
$params['field_name'] = 'value2';
$params['required'] = $field['todate'] == 'required' && ($field['value'] || $field['required']) ? TRUE : FALSE;
$form[$field['field_name']][$delta] += date_text_input($params);
$form[$field['field_name']][$delta]['value2']['#weight'] += .1;
$form[$field['field_name']][$delta]['#empty'] = empty($items[$delta]['value']) && empty($items[$delta]['value2']) ? TRUE : FALSE;
}
}
// Group from/to items together.
if ($field['todate']) {
$form[$field['field_name']][$delta]['#theme'] = 'date_form_combination';
}
// Add other info to the form that the themes will need.
$form[$field['field_name']][$delta]['#title'] = $field['widget']['label'];
$form[$field['field_name']][$delta]['#delta'] = $delta;
}
$form += date_timezone_input($params);
return $form;
case 'process form values':
/**
* Rebuild $items with converted dates and timezones
*
* input text field dates will hold an array like:
* [0] => Array (
* [value] => 2006-04-06T02:00:00
* [timezone] => US/Central
* input date selector dates will hold an array like:
* [0] => Array (
* [value] => Array (
* [month] => 4
* [day] => 05
* [year] => 2006
* [hour] => 1
* [minute] => 12
* [timezone] => US/Central
*/
$formats = date_get_formats($field);
$add = array();
// Don't save empty fields.
if ($field['multiple']) {
foreach ($items as $delta => $item) {
if ((!$item['value'] && !$item['value']['year']) && ($delta > 0 || !$field['required'])) {
unset($items[$delta]);
}
}
}
foreach ($items as $delta => $item) {
if ($items[$delta]) {
foreach ($process as $processed) {
$timezone = date_get_timezone($field['tz_handling'], $item['timezone']);
switch ($field['widget']['type']) {
case ('date_select'):
$date = date_selector_make_dbdate($item[$processed], $field['type'], $timezone, date_granularity_array($field));
break;
case ('date_js'):
$date = date_jscalendar_make_dbdate(trim($item[$processed]), $field['type'], $formats['input']['text'], $timezone, date_granularity_array($field));
break;
default:
$date = date_text_make_dbdate(trim($item[$processed]), $field['type'], $formats['input']['text'], $timezone, date_granularity_array($field));
break;
}
// replace $items values with the converted date, timezone, and offset values
$add[$delta][$processed] = date_show_value($date, 'db', $field['type']);
}
if ($field['tz_handling'] == 'date') {
$add[$delta]['timezone'] = ($add[$delta]['value'] || $field['required']) ? $timezone : NULL;
$add[$delta]['offset'] = ($add[$delta]['value'] || $field['required']) ? $date->local->offset : NULL;
}
}
}
if ($add) $items = $add;
return;
}
}
/**
* Set the date default values.
*
* @todo expand on this in the future
*/
function date_default_value($node, $field, $items, $delta) {
include_once(drupal_get_path('module', 'date') .'/date.inc');
if ($field['required']) {
$default_date = $field['type'] == 'datestamp' ? time() : date_unix2iso(time());
}
else {
$default_date = NULL;
}
return array(0 => array('value' => $default_date, 'value2' => $default_date));
}
/**
* Implementation of hook_field_formatter_info().
*/
function date_field_formatter_info() {
return array(
'default' => array(
'label' => t('Default'),
'field types' => array('date', 'datestamp'),
),
'long' => array(
'label' => t('Long'),
'field types' => array('date', 'datestamp'),
),
'medium' => array(
'label' => t('Medium'),
'field types' => array('date', 'datestamp'),
),
'short' => array(
'label' => t('Short'),
'field types' => array('date', 'datestamp'),
),
'iso' => array(
'label' => t('ISO'),
'field types' => array('date', 'datestamp'),
),
'feed' => array(
'label' => t('Feed'),
'field types' => array('date', 'datestamp'),
),
'ical' => array(
'label' => t('iCal'),
'field types' => array('date', 'datestamp'),
),
);
}
/**
* Implementation of hook_field_formatter().
*/
function date_field_formatter($field, $item, $formatter, $node) {
drupal_add_css(drupal_get_path('module', 'date') .'/date.css');
if (empty($item['value'])) {
return '';
}
if ($field['todate']) {
$process = array('value', 'value2');
}
else {
$process = array('value');
}
include_once(drupal_get_path('module', 'date') .'/date.inc');
$format_db_type = 'local';
switch (strtolower($formatter)) {
case ('long'):
$format = $field['output_format_custom_long'] > '' ? $field['output_format_custom_long'] : ($field['output_format_date_long'] ? $field['output_format_date_long'] : variable_get('date_format_long', 'l, F j, Y - H:i'));
$format_zone = $field['output_format_zone_long'];
break;
case ('medium'):
$format = $field['output_format_custom_medium'] > '' ? $field['output_format_custom_medium'] : ($field['output_format_date_medium'] ? $field['output_format_date_medium'] : variable_get('date_format_medium', 'D, m/d/Y - H:i'));
$format_zone = $field['output_format_zone_medium'];
break;
case ('short'):
$format = $field['output_format_custom_short'] > '' ? $field['output_format_custom_short'] : ($field['output_format_date_short'] ? $field['output_format_date_short'] : variable_get('date_format_short', 'm/d/Y - H:i'));
$format_zone = $field['output_format_zone_short'];
break;
case ('iso'):
$format = DATE_STRING_ISO;
$format_zone = '00:00';
break;
case ('feed'):
$format = 'D, j M Y H:i:s';
$format_zone = '0000';
break;
case ('ical'):
// for ical, send the db value with Z appended to indicate it is the gmt value
$format = 'Ymd\THis';
$format_zone = '';
$append = 'Z';
$format_db_type = 'db';
break;
default:
$format = $field['output_format_custom'] > '' ? $field['output_format_custom'] : ($field['output_format_date'] ? $field['output_format_date'] : variable_get('date_format_short', 'm/d/Y - H:i'));
$format_zone = $field['output_format_zone'];
break;
}
$dates = array();
foreach ($process as $processed) {
if ($field['tz_handling'] == 'none') {
// if no timezone handling was elected, create a date object with the database value
$date = date_make_date(trim($item[$processed]), 'none', 'local', $field['type']);
} else {
// create a date object with a gmt timezone from the database value
$date = date_make_date(trim($item[$processed]), 'GMT', 'db', $field['type']);
// convert the date object to the proper timezone, depending on the field's tz_handling value
date_convert_timezone($date, 'GMT', date_get_timezone($field['tz_handling'], $item['timezone']), 'local');
}
// display the date using the selected format
$dates[] = date_show_date($date, $format, $format_db_type, $format_zone) . $append;
$db_info = content_database_info($field);
}
return theme('date_display_combination', $field, $dates[0], $dates[1]);
}
/**
* $field['granularity'] will contain an array like ('H' => 'H', 'M' => 0)
* where the values turned on return their own names and the values turned off return a zero
* need to reconfigure this into a simple array of the turned on values
*/
function date_granularity_array($field) {
if (!is_array($field) || !is_array($field['granularity'])) {
$field['granularity'] = drupal_map_assoc(array('Y', 'M', 'D'));
}
return array_values(array_filter($field['granularity']));
}
function date_get_formats($field) {
if ($cached = cache_get('date_formats:'. $field['field_name'] .':'.$field['type_name'], 'cache')) {
$formats = unserialize($cached->data);
// are we up-to-date with current site-wide format ?
if ($field['input_format'] != 'site-wide' || $formats['input']['site-wide'] == variable_get('date_format_short', 'm/d/Y - H:i')) {
return $formats;
}
}
// if we get there, it means we have to (re)generate the formats
return date_set_formats($field);
}
function date_set_formats($field) {
if (!empty($field['input_format_custom'])) {
$format = $field['input_format_custom'];
}
else {
$format = ($field['input_format'] == 'site-wide') ? variable_get('date_format_short', 'm/d/Y - H:i') : $field['input_format'];
}
$granularity = date_granularity_array($field);
$formats = date_formats($format, $granularity);
cache_set('date_formats:'. $field['field_name'] .':'.$field['type_name'], 'cache', serialize($formats), CACHE_PERMANENT);
return $formats;
}
/**
* Return the database column structure.
*/
function date_columns($field) {
if ($field['type'] == 'date') {
$db_columns['value'] = array('type' => 'varchar', 'length' => 20, 'not null' => FALSE, 'default' => NULL, 'sortable' => TRUE);
} elseif ($field['type'] == 'datestamp') {
$db_columns['value'] = array('type' => 'integer', 'length' => 11, 'not null' => FALSE, 'default' => NULL, 'sortable' => TRUE);
}
// If a second date is needed for 'To' date, just make a copy of the first one.
if ($field['todate']) {
$db_columns['value2'] = $db_columns['value'];
}
// timezone and offset columns are used only if date-specific dates are chosen.
if ($field['tz_handling'] == 'date' && ($field['type'] == 'date' || $field['type'] == 'datestamp')) {
$db_columns['timezone'] = array('type' => 'varchar', 'length' => 50, 'not null' => FALSE, 'default' => NULL, 'sortable' => TRUE);
$db_columns['offset'] = array('type' => 'integer', 'length' => 10, 'not null' => FALSE, 'default' => NULL, 'sortable' => TRUE);
}
return $db_columns;
}
/**
* Themes for date input and display
*/
/**
* Theme entire date field form.
*
* Display the first item and any other non-empty items,
* then groups others into an 'additional' theme.
*/
function theme_date_form_fieldgroup($form) {
foreach ($form as $delta => $item) {
if ((!$item['#empty'] || $item['#delta'] == 0) && is_numeric($delta)) {
$output .= drupal_render($form[$delta]);
}
elseif (is_numeric($delta)) {
$additional .= drupal_render($form[$delta]);
$title = $form['#title'];
}
}
$output .= theme('date_form_empty', $additional, $title);
$output .= drupal_render($form);
return $output;
}
/**
* Theme empty date form fields.
*
* Put them into a collapsed fieldset.
*/
function theme_date_form_empty($contents, $title) {
if (empty($contents)) return '';
$fieldset = array(
'#title' => t('More'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#weight' => 10,
'#value' => $contents,
);
$output = theme('fieldset', $fieldset);
return $output;
}
/**
* Theme from/to date combination on form.
*/
function theme_date_form_combination($form) {
$fieldset = array(
'#title' => $form['#title'] . ' '. intval($form['#delta'] + 1),
'#value' => drupal_render($form),
);
$output = theme('fieldset', $fieldset);
return $output;
}
/**
* Theme from/to date combination in the view,
*/
function theme_date_display_combination($field, $date1, $date2 = NULL) {
if ($date1 == $date2 || empty($date2)) {
return ''. $date1 .'';
}
else {
return ''. $date1 .' - '. $date2 .'';
}
}