function DateFormatter::formatDiff

Same name in other branches
  1. 8.9.x core/lib/Drupal/Core/Datetime/DateFormatter.php \Drupal\Core\Datetime\DateFormatter::formatDiff()
  2. 10 core/lib/Drupal/Core/Datetime/DateFormatter.php \Drupal\Core\Datetime\DateFormatter::formatDiff()
  3. 11.x core/lib/Drupal/Core/Datetime/DateFormatter.php \Drupal\Core\Datetime\DateFormatter::formatDiff()

Overrides DateFormatterInterface::formatDiff

2 calls to DateFormatter::formatDiff()
DateFormatter::formatTimeDiffSince in core/lib/Drupal/Core/Datetime/DateFormatter.php
Formats the time difference from a timestamp to the current request time.
DateFormatter::formatTimeDiffUntil in core/lib/Drupal/Core/Datetime/DateFormatter.php
Formats the time difference from the current request time to a timestamp.

File

core/lib/Drupal/Core/Datetime/DateFormatter.php, line 202

Class

DateFormatter
Provides a service to handle various date related functionality.

Namespace

Drupal\Core\Datetime

Code

public function formatDiff($from, $to, $options = []) {
    $options += [
        'granularity' => 2,
        'langcode' => NULL,
        'strict' => TRUE,
        'return_as_object' => FALSE,
    ];
    if ($options['strict'] && $from > $to) {
        $string = $this->t('0 seconds');
        if ($options['return_as_object']) {
            return new FormattedDateDiff($string, 0);
        }
        return $string;
    }
    $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.
    $max_age = 1.0E+99;
    foreach ([
        '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', [], [
                        'langcode' => $options['langcode'],
                    ]);
                    $max_age = min($max_age, 365 * 86400);
                    break;
                case 'm':
                    $interval_output = $this->formatPlural($interval->m, '1 month', '@count months', [], [
                        'langcode' => $options['langcode'],
                    ]);
                    $max_age = min($max_age, 30 * 86400);
                    break;
                case 'd':
                    // \DateInterval doesn't support weeks, so we need to calculate them
                    // ourselves.
                    $interval_output = '';
                    $days = $interval->d;
                    $weeks = floor($days / 7);
                    if ($weeks) {
                        $interval_output .= $this->formatPlural($weeks, '1 week', '@count weeks', [], [
                            'langcode' => $options['langcode'],
                        ]);
                        $days -= $weeks * 7;
                        $granularity--;
                        $max_age = min($max_age, 7 * 86400);
                    }
                    if ((!$output || $weeks > 0) && $granularity > 0 && $days > 0) {
                        $interval_output .= ($interval_output ? ' ' : '') . $this->formatPlural($days, '1 day', '@count days', [], [
                            'langcode' => $options['langcode'],
                        ]);
                        $max_age = min($max_age, 86400);
                    }
                    else {
                        // If we did not output days, set the granularity to 0 so that we
                        // will not output hours and get things like "1 week 1 hour".
                        $granularity = 0;
                    }
                    break;
                case 'h':
                    $interval_output = $this->formatPlural($interval->h, '1 hour', '@count hours', [], [
                        'langcode' => $options['langcode'],
                    ]);
                    $max_age = min($max_age, 3600);
                    break;
                case 'i':
                    $interval_output = $this->formatPlural($interval->i, '1 minute', '@count minutes', [], [
                        'langcode' => $options['langcode'],
                    ]);
                    $max_age = min($max_age, 60);
                    break;
                case 's':
                    $interval_output = $this->formatPlural($interval->s, '1 second', '@count seconds', [], [
                        'langcode' => $options['langcode'],
                    ]);
                    $max_age = min($max_age, 1);
                    break;
            }
            $output .= ($output && $interval_output ? ' ' : '') . $interval_output;
            $granularity--;
        }
        elseif ($output) {
            // Break if there was previous output but not any output at this level,
            // to avoid skipping levels and getting output like "1 year 1 second".
            break;
        }
        if ($granularity <= 0) {
            break;
        }
    }
    if (empty($output)) {
        $output = $this->t('0 seconds');
        $max_age = 0;
    }
    if ($options['return_as_object']) {
        return new FormattedDateDiff($output, $max_age);
    }
    return $output;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.