Commit 4ba73b4b authored by alexpott's avatar alexpott
Browse files

Issue #2456521 by pjonckiere, mpdonadio, jhodgdon, rteijeiro, David_Rothstein,...

Issue #2456521 by pjonckiere, mpdonadio, jhodgdon, rteijeiro, David_Rothstein, xjm: Add DateFormatter::formatDiff() as a non-buggy alternative to DateFormatter::formatInterval() when the start and end of the interval are known
parent a2fc9850
......@@ -1143,7 +1143,7 @@ services:
arguments: ['@module_handler']
date.formatter:
class: Drupal\Core\Datetime\DateFormatter
arguments: ['@entity.manager', '@language_manager', '@string_translation', '@config.factory']
arguments: ['@entity.manager', '@language_manager', '@string_translation', '@config.factory', '@request_stack']
feed.bridge.reader:
class: Drupal\Component\Bridge\ZfExtensionManagerSfContainer
calls:
......
......@@ -15,6 +15,7 @@
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Symfony\Component\HttpFoundation\RequestStack;
/**
* Provides a service to handler various date related functionality.
......@@ -52,6 +53,13 @@ class DateFormatter {
*/
protected $configFactory;
/**
* The request stack.
*
* @var \Symfony\Component\HttpFoundation\RequestStack
*/
protected $requestStack;
protected $country = NULL;
protected $dateFormats = array();
......@@ -85,12 +93,15 @@ class DateFormatter {
* The string translation.
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
* The configuration factory.
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
* The request stack.
*/
public function __construct(EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager, TranslationInterface $translation, ConfigFactoryInterface $config_factory) {
public function __construct(EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager, TranslationInterface $translation, ConfigFactoryInterface $config_factory, RequestStack $request_stack) {
$this->dateFormatStorage = $entity_manager->getStorage('date_format');
$this->languageManager = $language_manager;
$this->stringTranslation = $translation;
$this->configFactory = $config_factory;
$this->requestStack = $request_stack;
}
/**
......@@ -111,13 +122,13 @@ public function __construct(EntityManagerInterface $entity_manager, LanguageMana
* (optional) If $type is 'custom', a PHP date format string suitable for
* input to date(). Use a backslash to escape ordinary text, so it does not
* get interpreted as date format characters.
* @param string $timezone
* @param string|null $timezone
* (optional) Time zone identifier, as described at
* http://php.net/manual/timezones.php Defaults to the time zone used to
* display the page.
* @param string $langcode
* (optional) Language code to translate to. Defaults to the language used to
* display the page.
* @param string|null $langcode
* (optional) Language code to translate to. NULL (default) means to use
* the user interface language for the page.
*
* @return string
* A translated date string in the requested format.
......@@ -163,17 +174,26 @@ public function format($timestamp, $type = 'medium', $format = '', $timezone = N
/**
* Formats a time interval with the requested granularity.
*
* Note that for intervals over 30 days, the output is approximate: a "month"
* is always exactly 30 days, and a "year" is always 365 days. It is not
* possible to make a more exact representation, given that there is only one
* input in seconds. If you are formatting an interval between two specific
* timestamps, use \Drupal\Core\Datetime\DateFormatter::formatDiff() instead.
*
* @param int $interval
* The length of the interval in seconds.
* @param int $granularity
* (optional) How many different units to display in the string (2 by
* default).
* @param string $langcode
* (optional) Language code to translate to a language other than what is
* used to display the page. Defaults to NULL.
* @param string|null $langcode
* (optional) langcode: The language code for the language used to format
* the date. Defaults to NULL, which results in the user interface language
* for the page being used.
*
* @return string
* A translated string representation of the interval.
*
* @see \Drupal\Core\Datetime\DateFormatter::formatDiff()
*/
public function formatInterval($interval, $granularity = 2, $langcode = NULL) {
$output = '';
......@@ -214,11 +234,185 @@ public function getSampleDateFormats($langcode = NULL, $timestamp = NULL, $timez
// All date format characters for the PHP date() function.
$date_chars = str_split('dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZcrU');
$date_elements = array_combine($date_chars, $date_chars);
return array_map(function($character) use ($timestamp, $timezone, $langcode) {
return array_map(function ($character) use ($timestamp, $timezone, $langcode) {
return $this->format($timestamp, 'custom', $character, $timezone, $langcode);
}, $date_elements);
}
/**
* Formats the time difference from the current request time to a timestamp.
*
* @param $timestamp
* A UNIX timestamp to compare against the current request time.
* @param array $options
* (optional) An associative array with additional options. The following
* keys can be used:
* - granularity: An integer value that signals how many different units to
* display in the string. Defaults to 2.
* - langcode: The language code for the language used to format the date.
* Defaults to NULL, which results in the user interface language for the
* page being used.
* - strict: A Boolean value indicating whether or not the timestamp can be
* before the current request time. If TRUE (default) and $timestamp is
* before the current request time, the result string will be "0 seconds".
* If FALSE and $timestamp is before the current request time, the result
* string will be the formatted time difference.
*
* @return string
* A translated string representation of the difference between the given
* timestamp and the current request time. This interval is always positive.
*
* @see \Drupal\Core\Datetime\DateFormatter::formatDiff()
* @see \Drupal\Core\Datetime\DateFormatter::formatTimeDiffSince()
*/
public function formatTimeDiffUntil($timestamp, $options = array()) {
$request_time = $this->requestStack->getCurrentRequest()->server->get('REQUEST_TIME');
return $this->formatDiff($request_time, $timestamp, $options);
}
/**
* Formats the time difference from a timestamp to the current request time.
*
* @param $timestamp
* A UNIX timestamp to compare against the current request time.
* @param array $options
* (optional) An associative array with additional options. The following
* keys can be used:
* - granularity: An integer value that signals how many different units to
* display in the string. Defaults to 2.
* - langcode: The language code for the language used to format the date.
* Defaults to NULL, which results in the user interface language for the
* page being used.
* - strict: A Boolean value indicating whether or not the timestamp can be
* after the current request time. If TRUE (default) and $timestamp is
* after the current request time, the result string will be "0 seconds".
* If FALSE and $timestamp is after the current request time, the result
* string will be the formatted time difference.
*
* @return string
* A translated string representation of the difference between the given
* timestamp and the current request time. This interval is always positive.
*
* @see \Drupal\Core\Datetime\DateFormatter::formatDiff()
* @see \Drupal\Core\Datetime\DateFormatter::formatTimeDiffUntil()
*/
public function formatTimeDiffSince($timestamp, $options = array()) {
$request_time = $this->requestStack->getCurrentRequest()->server->get('REQUEST_TIME');
return $this->formatDiff($timestamp, $request_time, $options);
}
/**
* Formats a time interval between two timestamps.
*
* @param int $from
* A UNIX timestamp, defining the from date and time.
* @param int $to
* A UNIX timestamp, defining the to date and time.
* @param array $options
* (optional) An associative array with additional options. The following
* keys can be used:
* - granularity: An integer value that signals how many different units to
* display in the string. Defaults to 2.
* - langcode: The language code for the language used to format the date.
* Defaults to NULL, which results in the user interface language for the
* page being used.
* - strict: A Boolean value indicating whether or not the $from timestamp
* can be after the $to timestamp. If TRUE (default) and $from is after
* $to, the result string will be "0 seconds". If FALSE and $from is
* after $to, the result string will be the formatted time difference.
*
* @return string
* A translated string representation of the interval. This interval is
* always positive.
*
* @see \Drupal\Core\Datetime\DateFormatter::formatInterval()
* @see \Drupal\Core\Datetime\DateFormatter::formatTimeDiffSince()
* @see \Drupal\Core\Datetime\DateFormatter::formatTimeDiffUntil()
*/
public function formatDiff($from, $to, $options = array()) {
$options += array(
'granularity' => 2,
'langcode' => NULL,
'strict' => TRUE,
);
if ($options['strict'] && $from > $to) {
return $this->t('0 seconds');
}
$date_time_from = new \DateTime();
$date_time_from->setTimestamp($from);
$date_time_to = new \DateTime();
$date_time_to->setTimestamp($to);
$interval = $date_time_to->diff($date_time_from);
$granularity = $options['granularity'];
$output = '';
// We loop over the keys provided by \DateInterval explicitly. Since we
// don't take the "invert" property into account, the resulting output value
// will always be positive.
foreach (array('y', 'm', 'd', 'h', 'i', 's') as $value) {
if ($interval->$value > 0) {
// Switch over the keys to call formatPlural() explicitly with literal
// strings for all different possibilities.
switch ($value) {
case 'y':
$interval_output = $this->formatPlural($interval->y, '1 year', '@count years', array(), array('langcode' => $options['langcode']));
break;
case 'm':
$interval_output = $this->formatPlural($interval->m, '1 month', '@count months', array(), array('langcode' => $options['langcode']));
break;
case 'd':
// \DateInterval doesn't support weeks, so we need to calculate them
// ourselves.
$interval_output = '';
$days = $interval->d;
if ($days >= 7) {
$weeks = floor($days / 7);
$interval_output .= $this->formatPlural($weeks, '1 week', '@count weeks', array(), array('langcode' => $options['langcode']));
$days -= $weeks * 7;
$granularity--;
}
if ($granularity > 0 && $days > 0) {
$interval_output .= ($interval_output ? ' ' : '') . $this->formatPlural($days, '1 day', '@count days', array(), array('langcode' => $options['langcode']));
}
break;
case 'h':
$interval_output = $this->formatPlural($interval->h, '1 hour', '@count hours', array(), array('langcode' => $options['langcode']));
break;
case 'i':
$interval_output = $this->formatPlural($interval->i, '1 minute', '@count minutes', array(), array('langcode' => $options['langcode']));
break;
case 's':
$interval_output = $this->formatPlural($interval->s, '1 second', '@count seconds', array(), array('langcode' => $options['langcode']));
break;
}
$output .= ($output ? ' ' : '') . $interval_output;
$granularity--;
}
if ($granularity == 0) {
break;
}
}
if (empty($output)) {
$output = $this->t('0 seconds');
}
return $output;
}
/**
* Loads the given format pattern for the given langcode.
*
......
......@@ -87,7 +87,7 @@ public function viewElements(FieldItemListInterface $items) {
foreach ($items as $delta => $item) {
if ($item->value) {
$updated = $this->t('@time ago', array('@time' => $this->dateFormatter->formatInterval(REQUEST_TIME - $item->value)));
$updated = $this->t('@time ago', array('@time' => $this->dateFormatter->formatTimeDiffSince($item->value)));
}
else {
$updated = $this->t('never');
......
......@@ -127,8 +127,8 @@ public function adminOverview() {
$row[] = $this->formatPlural($entity_manager->getStorage('aggregator_item')->getItemCount($feed), '1 item', '@count items');
$last_checked = $feed->getLastCheckedTime();
$refresh_rate = $feed->getRefreshRate();
$row[] = ($last_checked ? $this->t('@time ago', array('@time' => $this->dateFormatter->formatInterval(REQUEST_TIME - $last_checked))) : $this->t('never'));
$row[] = ($last_checked && $refresh_rate ? $this->t('%time left', array('%time' => $this->dateFormatter->formatInterval($last_checked + $refresh_rate - REQUEST_TIME))) : $this->t('never'));
$row[] = ($last_checked ? $this->t('@time ago', array('@time' => $this->dateFormatter->formatTimeDiffSince($last_checked))) : $this->t('never'));
$row[] = ($last_checked && $refresh_rate ? $this->t('@time left', array('@time' => $this->dateFormatter->formatTimeDiffUntil($last_checked + $refresh_rate))) : $this->t('never'));
$links['edit'] = [
'title' => $this->t('Edit'),
'url' => Url::fromRoute('entity.aggregator_feed.edit_form', ['aggregator_feed' => $feed->id()]),
......
......@@ -60,8 +60,8 @@ function testCommentTokenReplacement() {
$tests['[comment:langcode]'] = SafeMarkup::checkPlain($comment->language()->getId());
$tests['[comment:url]'] = $comment->url('canonical', $url_options + array('fragment' => 'comment-' . $comment->id()));
$tests['[comment:edit-url]'] = $comment->url('edit-form', $url_options);
$tests['[comment:created:since]'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $comment->getCreatedTime(), 2, $language_interface->getId());
$tests['[comment:changed:since]'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $comment->getChangedTimeAcrossTranslations(), 2, $language_interface->getId());
$tests['[comment:created:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($comment->getCreatedTime(), array('langcode' => $language_interface->getId()));
$tests['[comment:changed:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($comment->getChangedTimeAcrossTranslations(), array('langcode' => $language_interface->getId()));
$tests['[comment:parent:cid]'] = $comment->hasParentComment() ? $comment->getParentComment()->id() : NULL;
$tests['[comment:parent:title]'] = SafeMarkup::checkPlain($parent_comment->getSubject());
$tests['[comment:entity]'] = SafeMarkup::checkPlain($node->getTitle());
......
......@@ -231,7 +231,7 @@ function testSiteWideContact() {
}
// Submit contact form one over limit.
$this->submitContact($this->randomMachineName(16), $recipients[0], $this->randomMachineName(16), $id, $this->randomMachineName(64));
$this->assertRaw(t('You cannot send more than %number messages in @interval. Try again later.', array('%number' => $this->config('contact.settings')->get('flood.limit'), '@interval' => \Drupal::service('date.formatter')->formatInterval(600))));
$this->assertRaw(t('You cannot send more than %number messages in 10 min. Try again later.', array('%number' => $this->config('contact.settings')->get('flood.limit'))));
// Test listing controller.
$this->drupalLogin($admin_user);
......
......@@ -633,5 +633,5 @@ function template_preprocess_forum_submitted(&$variables) {
$username = array('#theme' => 'username', '#account' => User::load($variables['topic']->uid));
$variables['author'] = drupal_render($username);
}
$variables['time'] = isset($variables['topic']->created) ? \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $variables['topic']->created) : '';
$variables['time'] = isset($variables['topic']->created) ? \Drupal::service('date.formatter')->formatTimeDiffSince($variables['topic']->created) : '';
}
......@@ -119,6 +119,6 @@ function template_preprocess_locale_translation_update_info(array &$variables) {
function template_preprocess_locale_translation_last_check(array &$variables) {
$last = $variables['last'];
$variables['last_checked'] = ($last != NULL);
$variables['time'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $last);
$variables['time'] = \Drupal::service('date.formatter')->formatTimeDiffSince($last);
$variables['link'] = \Drupal::l(t('Check manually'), new Url('locale.check_translation', array(), array('query' => \Drupal::destination()->getAsArray())));
}
......@@ -73,8 +73,8 @@ function testNodeTokenReplacement() {
$tests['[node:author]'] = SafeMarkup::checkPlain($account->getUsername());
$tests['[node:author:uid]'] = $node->getOwnerId();
$tests['[node:author:name]'] = SafeMarkup::checkPlain($account->getUsername());
$tests['[node:created:since]'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $node->getCreatedTime(), 2, $this->interfaceLanguage->getId());
$tests['[node:changed:since]'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $node->getChangedTime(), 2, $this->interfaceLanguage->getId());
$tests['[node:created:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($node->getCreatedTime(), array('langcode' => $this->interfaceLanguage->getId()));
$tests['[node:changed:since]'] = \Drupal::service('date.formatter')->formatTimeDiffSince($node->getChangedTime(), array('langcode' => $this->interfaceLanguage->getId()));
// Test to make sure that we generated something for each token.
$this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.');
......
......@@ -761,7 +761,7 @@ function hook_requirements($phase) {
$cron_last = \Drupal::state()->get('system.cron_last');
if (is_numeric($cron_last)) {
$requirements['cron']['value'] = t('Last run !time ago', array('!time' => \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $cron_last)));
$requirements['cron']['value'] = t('Last run !time ago', array('!time' => \Drupal::service('date.formatter')->formatTimeDiffSince($cron_last)));
}
else {
$requirements['cron'] = array(
......
......@@ -101,8 +101,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
'#value' => t('Run cron'),
'#submit' => array('::submitCron'),
);
$status = '<p>' . t('Last run: %cron-last ago.', array('%cron-last' => $this->dateFormatter->formatInterval(REQUEST_TIME - $this->state->get('system.cron_last')))) . '</p>';
$status = '<p>' . $this->t('Last run: %time ago.', array('%time' => $this->dateFormatter->formatTimeDiffSince($this->state->get('system.cron_last')))) . '</p>';
$form['status'] = array(
'#markup' => $status,
);
......
......@@ -154,7 +154,7 @@ public function testSystemDateTokenReplacement() {
$tests['[date:medium]'] = $date_formatter->format($date, 'medium', '', NULL, $this->interfaceLanguage->getId());
$tests['[date:long]'] = $date_formatter->format($date, 'long', '', NULL, $this->interfaceLanguage->getId());
$tests['[date:custom:m/j/Y]'] = $date_formatter->format($date, 'custom', 'm/j/Y', NULL, $this->interfaceLanguage->getId());
$tests['[date:since]'] = $date_formatter->formatInterval(REQUEST_TIME - $date, 2, $this->interfaceLanguage->getId());
$tests['[date:since]'] = $date_formatter->formatTimeDiffSince($date, array('langcode' => $this->interfaceLanguage->getId()));
$tests['[date:raw]'] = Xss::filter($date);
// Test to make sure that we generated something for each token.
......
......@@ -359,7 +359,7 @@ function system_requirements($phase) {
}
// Set summary and description based on values determined above.
$summary = t('Last run !time ago', array('!time' => \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $cron_last)));
$summary = t('Last run !time ago', array('!time' => \Drupal::service('date.formatter')->formatTimeDiffSince($cron_last)));
$description = '';
if ($severity != REQUIREMENT_INFO) {
$description = t('Cron has not run recently.') . ' ' . $help;
......
......@@ -68,7 +68,7 @@ function system_token_info() {
);
$date['since'] = array(
'name' => t("Time-since"),
'description' => t("A date in 'time-since' format. (%date)", array('%date' => \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - 360, 2))),
'description' => t("A date in 'time-since' format. (%date)", array('%date' => \Drupal::service('date.formatter')->formatTimeDiffSince(REQUEST_TIME - 360))),
);
$date['raw'] = array(
'name' => t("Raw timestamp"),
......@@ -157,7 +157,7 @@ function system_tokens($type, $tokens, array $data = array(), array $options = a
break;
case 'since':
$replacements[$original] = \Drupal::service('date.formatter')->formatInterval((REQUEST_TIME - $date), 2, $langcode);
$replacements[$original] = \Drupal::service('date.formatter')->formatTimeDiffSince($date, array('langcode' => $langcode));
break;
case 'raw':
......
......@@ -91,7 +91,7 @@ function testTrackerAll() {
$this->drupalGet('activity');
$this->assertText($node->label(), 'Published node shows up in the tracker listing.');
$this->assertText(\Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $node->getChangedTime()), 'The changed time was displayed on the tracker listing.');
$this->assertText(\Drupal::service('date.formatter')->formatTimeDiffSince($node->getChangedTime()), 'The changed time was displayed on the tracker listing.');
}
/**
......
......@@ -114,7 +114,7 @@ function tracker_page($account = NULL) {
),
'last updated' => array(
'data' => t('!time ago', array(
'!time' => \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $node->last_activity),
'!time' => \Drupal::service('date.formatter')->formatTimeDiffSince($node->last_activity),
)),
),
);
......
......@@ -574,7 +574,7 @@ function _update_project_status_sort($a, $b) {
* @see theme_update_report()
*/
function template_preprocess_update_last_check(&$variables) {
$variables['time'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $variables['last']);
$variables['time'] = \Drupal::service('date.formatter')->formatTimeDiffSince($variables['last']);
$variables['link'] = \Drupal::l(t('Check manually'), new Url('update.manual_status', array(), array('query' => \Drupal::destination()->getAsArray())));
}
......
......@@ -91,7 +91,7 @@ public function testUserListing() {
$expected_roles = array('custom_role_1', 'custom_role_2');
$this->assertEqual($result_accounts[$role_account_name]['roles'], $expected_roles, 'Ensure roles are listed properly.');
$this->assertEqual($result_accounts[$timestamp_user]['member_for'], \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $accounts[$timestamp_user]->created->value), 'Ensure the right member time is displayed.');
$this->assertEqual($result_accounts[$timestamp_user]['member_for'], \Drupal::service('date.formatter')->formatTimeDiffSince($accounts[$timestamp_user]->created->value), 'Ensure the right member time is displayed.');
}
}
......@@ -151,10 +151,8 @@ public function buildRow(EntityInterface $entity) {
'#theme' => 'item_list',
'#items' => $users_roles,
);
$row['member_for'] = $this->dateFormatter->formatInterval(REQUEST_TIME - $entity->getCreatedTime());
$row['access'] = $entity->access ? $this->t('@time ago', array(
'@time' => $this->dateFormatter->formatInterval(REQUEST_TIME - $entity->getLastAccessedTime()),
)) : t('never');
$row['member_for'] = $this->dateFormatter->formatTimeDiffSince($entity->getCreatedTime());
$row['access'] = $entity->access ? $this->t('@time ago', array('@time' => $this->dateFormatter->formatTimeDiffSince($entity->getLastAccessedTime()))) : t('never');
return $row + parent::buildRow($entity);
}
......
......@@ -370,7 +370,7 @@ function user_user_view(array &$build, UserInterface $account, EntityViewDisplay
if ($display->getComponent('member_for')) {
$build['member_for'] = array(
'#type' => 'item',
'#markup' => '<h4 class="label">' . t('Member for') . '</h4> ' . \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $account->getCreatedTime()),
'#markup' => '<h4 class="label">' . t('Member for') . '</h4> ' . \Drupal::service('date.formatter')->formatTimeDiffSince($account->getCreatedTime()),
);
}
}
......
......@@ -151,24 +151,33 @@ public function render(ResultRow $values) {
$time_diff = REQUEST_TIME - $value; // will be positive for a datetime in the past (ago), and negative for a datetime in the future (hence)
switch ($format) {
case 'raw time ago':
return $this->dateFormatter->formatInterval($time_diff, is_numeric($custom_format) ? $custom_format : 2);
return $this->dateFormatter->formatTimeDiffSince($value, array('granularity' => is_numeric($custom_format) ? $custom_format : 2));
case 'time ago':
return $this->t('%time ago', array('%time' => $this->dateFormatter->formatInterval($time_diff, is_numeric($custom_format) ? $custom_format : 2)));
return $this->t('%time ago', array('%time' => $this->dateFormatter->formatTimeDiffSince($value, array('granularity' => is_numeric($custom_format) ? $custom_format : 2))));
case 'raw time hence':
return $this->dateFormatter->formatInterval(-$time_diff, is_numeric($custom_format) ? $custom_format : 2);
return $this->dateFormatter->formatTimeDiffUntil($value, array('granularity' => is_numeric($custom_format) ? $custom_format : 2));
case 'time hence':
return $this->t('%time hence', array('%time' => $this->dateFormatter->formatInterval(-$time_diff, is_numeric($custom_format) ? $custom_format : 2)));
return $this->t('%time hence', array('%time' => $this->dateFormatter->formatTimeDiffUntil($value, array('granularity' => is_numeric($custom_format) ? $custom_format : 2))));
case 'raw time span':
return ($time_diff < 0 ? '-' : '') . $this->dateFormatter->formatInterval(abs($time_diff), is_numeric($custom_format) ? $custom_format : 2);
return ($time_diff < 0 ? '-' : '') . $this->dateFormatter->formatTimeDiffSince($value, array('strict' => FALSE, 'granularity' => is_numeric($custom_format) ? $custom_format : 2));
case 'inverse time span':
return ($time_diff > 0 ? '-' : '') . $this->dateFormatter->formatInterval(abs($time_diff), is_numeric($custom_format) ? $custom_format : 2);
return ($time_diff > 0 ? '-' : '') . $this->dateFormatter->formatTimeDiffSince($value, array('strict' => FALSE, 'granularity' => is_numeric($custom_format) ? $custom_format : 2));
case 'time span':
return $this->t(($time_diff < 0 ? '%time hence' : '%time ago'), array('%time' => $this->dateFormatter->formatInterval(abs($time_diff), is_numeric($custom_format) ? $custom_format : 2)));
$time = $this->dateFormatter->formatTimeDiffSince($value, array('strict' => FALSE, 'granularity' => is_numeric($custom_format) ? $custom_format : 2));
return ($time_diff < 0) ? $this->t('%time hence', array('%time' => $time)) : $this->t('%time ago', array('%time' => $time));
case 'custom':
if ($custom_format == 'r') {
return format_date($value, $format, $custom_format, $timezone, 'en');
}
return format_date($value, $format, $custom_format, $timezone);
default:
return format_date($value, $format, '', $timezone);
}
......
......@@ -121,19 +121,19 @@ public function testFieldDate() {
}
// Check times in the past.
$test = $this->container->get('date.formatter')->formatInterval(REQUEST_TIME - $time, 2);
$time_since = $this->container->get('date.formatter')->formatTimeDiffSince($time);
$intervals = array(
'raw time ago' => $test,
'time ago' => t('%time ago', array('%time' => $test)),
'raw time span' => $test,
'inverse time span' => -$test,
'time span' => t('%time ago', array('%time' => $test)),
'raw time ago' => $time_since,
'time ago' => t('%time ago', array('%time' => $time_since)),
'raw time span' => $time_since,
'inverse time span' => -$time_since,
'time span' => t('%time ago', array('%time' => $time_since)),
);
$this->assertRenderedDatesEqual($view, $intervals);
// Check times in the future.
$time = gmmktime(0, 0, 0, 1, 1, 2050);
$formatted = $this->container->get('date.formatter')->formatInterval($time - REQUEST_TIME, 2);
$formatted = $this->container->get('date.formatter')->formatTimeDiffUntil($time);
$intervals = array(
'raw time span' => -$formatted,
'time span' => t('%time hence', array(
......
......@@ -147,7 +147,7 @@ public function form(array $form, FormStateInterface $form_state) {
);
$lock_message_substitutions = array(
'!user' => drupal_render($username),
'!age' => $this->dateFormatter->formatInterval(REQUEST_TIME - $view->lock->updated),
'!age' => $this->dateFormatter->formatTimeDiffSince($view->lock->updated),
'@url' => $view->url('break-lock-form'),
);
$form['locked'] = array(
......
......@@ -10,6 +10,7 @@
use Drupal\Core\Datetime\DateFormatter;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Tests\UnitTestCase;