如何以人类格式(时间以前......等)获得时差,但采用多语言风格

时间:2012-07-30 14:23:29

标签: php zend-framework

在zend中是否有任何视图帮助器或库,我可以通过它获得两个时间戳之间的差异,但是会自动将“y li a”放在前面。这是例如法国标准的时间段...

2 个答案:

答案 0 :(得分:1)

答案是否定的,但也许这会有所帮助:

<?php

/**
 * Return a human readable diff between two times (e.g. 3 years 4 months 8 days 3 hours)
 * This is locale aware and supports automatic translation
 *
 * @category   View Helpers
 * @author     Drew Phillips <drew [at] drew [.] co.il>
 * @copyright  None
 * @license    BSD License http://opensource.org/licenses/bsd-3-clause
 * @version    1.0
 * @link       http://drew.co.il
 */
class My_View_Helper_TimeDiff extends Zend_View_Helper_Abstract
{
    protected static $_locale       = null;
    protected static $_translations = null;

    /**
     * Return the diff between two times in human readable format
     * @param int    $timestamp    The timestamp of the time to diff
     * @param string $format       The format string used to control which date units are output (TODO: improve by incrementing lower values (i.e. add 12 to months if there is 1 year but years are not displayed))
     * @param int    $now          The timestamp used as the current time, if null, the current time is used
     * @return string              The human readable date diff in the language of the locale
     */
    public function timeDiff($timestamp, $format = null, $now = null)
    {
        if (null === $format) $format = '%y %m %d %h %i';
        if (null === $now)    $now    = time();

        if (!$this->isValidTimestamp($timestamp)) {
            throw new InvalidArgumentException('$timestamp parameter to timeDiff is not a valid timestamp');
        } else if (!$this->isValidTimestamp($now)) {
            throw new InvalidArgumentException('$now parameter to timeDiff is not a valid timestamp');
        } else if ($timestamp > $now) {
            throw new InvalidArgumentException('The value given for $timestamp cannot be greater than $now');
        }

        if (self::$_locale == null) {
            $locale = null;
            $list   = array();

            try {
                $locale = Zend_Registry::get('Zend_Locale');
            } catch (Zend_Exception $ex) {
                $default = Zend_Locale::getDefault(); // en if nothing set

                try {
                    $locale = new Zend_Locale();
                } catch (Zend_Locale_Exception $ex) {
                    $locale = new Zend_Locale($default);
                }
            }

            self::$_locale = $locale;
            self::$_translations = Zend_Locale::getTranslationList('unit', $locale);
        }

        $table    = self::$_translations;
        $past     = new DateTime(date('Y-m-d H:i:s', $timestamp));
        $current  = new DateTime(date('Y-m-d H:i:s', $now));
        $interval = $current->diff($past);

        $parts = $interval->format('%y %m %d %h %i %s %a');

        $weeks = 0;
        list($years, $months, $days, $hours, $minutes, $seconds, $total_days) = explode(' ', $parts);

        /* uncomment to handle weeks
        if ($days >= 7) {
            $weeks = (int)($days / 7);
            $days  %= 7;
        }
        */

        $diff = array();

        if (strpos($format, '%y') !== false && $years > 0) {
            $diff[] = str_replace('{0}', $years, $table['year'][($years != 1 || !isset($table['year']['one']) ? 'other' : 'one')]);
        }

        if (strpos($format, '%m') !== false && $months > 0) {
            $diff[] = str_replace('{0}', $months, $table['month'][($months != 1 || !isset($table['month']['one']) ? 'other' : 'one')]);
        }

        if (strpos($format, '%d') !== false && $days > 0) {
            $diff[] = str_replace('{0}', $days, $table['day'][($days != 1 || !isset($table['day']['one']) ? 'other' : 'one')]);
        }

        if (strpos($format, '%h') !== false && $hours > 0) {
            $diff[] = str_replace('{0}', $hours, $table['hour'][($hours != 1 || !isset($table['hour']['one']) ? 'other' : 'one')]);
        }

        if (strpos($format, '%i') !== false && $minutes > 0) {
            $diff[] = str_replace('{0}', $minutes, $table['minute'][($minutes != 1 || !isset($table['minute']['one']) ? 'other' : 'one')]);
        }

        return implode(' ', $diff);
    }

    protected function isValidTimestamp($timestamp)
    {
        $ts = (int)$timestamp;
        $d  = date('Y-m-d H:i:s', $ts);

        return strtotime($d) === $ts;
    }
}

注册后,请从您的视图中调用它:

<?php echo $this->timeDiff($object->pastTimestamp) ?> $this->_xlate('ago');

示例输出:

1 année 5 mois 15 jours 21 heures 56 minutes il ya
1 год 5 месяца 15 дня 22 часа 1 минута назад

请注意,帮助程序不处理“之前”部分,在某些语言(法语)中,这些部分位于差异之前,而在其他语言(英语)中则在最后。您还需要在自己的翻译文件中定义此翻译字符串,ZF没有翻译。理想情况下,逻辑将构建在帮助程序中,但我还没有这样做。

希望有所帮助。

答案 1 :(得分:0)

时间戳是一个数字,您可以简单地从结束时间中减去开始时间以获得差异。你可以这样做:

public function timeDiff($timestampFrom, $timestampTo) {

$timeDiff = new Zend_Date($timestampTo - $timestampFrom, Zend_Date::TIMESTAMP);

$output = "il y a ";

//Check the number of days:
if($timeDiff->getTimestamp > 60*60*24) $output .= $timeDiff->get(Zend_Date::DAY).' jours, ';
//Check the hours
if($timeDiff->getTimestamp > 60*60) $output .= $timeDiff->get(Zend_Date::HOUR).' heures, ';
//Check the minutes
if($timeDiff->getTimestamp > 60) $output .= $timeDiff->get(Zend_Date::MINUTE).' minutes et ';
//Check the seconds
$output .= $timeDiff->get(Zend_Date::SECOND)." secondes";

return $output;
}

Matthieu的评论是正确的,法语中没有'y li a'这样的东西。你可能意味着'il y a'。 ;)