【问题标题】:Relative date formatting always outputs "3 hours ago"相对日期格式始终输出“3 小时前”
【发布时间】:2011-06-28 06:51:27
【问题描述】:

我正在使用 php 计算指定日期和当前日期之间的日期间隔。我这样做是为了打印出社交友好的时间戳,例如 A few mins ago2 hours ago

当我谈到小时部分时,我在 php 中发现了一些非常有趣的东西。下面是完整的工作代码,但是当您用此代码替换 hours 部分时,它总是打印 3 小时。

定义常量DATE

// The current date timestamp
define('DATE', time());

这里有错误代码:

//Only the hours part that' doing something weird
case ($interval >= 3600 && $interval < 86400) :
            $return = ( date('H', $interval) < 2)
                ? (int)date('H', $interval) . ' hour ago'
                : (int)date('H', $interval) . ' hours ago';
            break;

当指定的日期中断时,假设在这种情况下,创建日期刚刚超过一个小时,因此导致间隔等于 3660 秒。看起来日期方法调用date('H', 3660) 的结果是 03。它不应该是 01 吗?毕竟才一个多小时。

这里的工作代码:

public static function getTimeInterval($date)
{
    $interval = DATE - $date;

    $return = '';

    switch ( $interval )
    {
        case ($interval <= 60) :
            $return = 'a few secs ago';
            break;

        case ($interval > 60 && $interval < 3600) :
            $return = (int)date('i', $interval) . ' mins ago';
            break;

        case ($interval >= 3600 && $interval < 86400) :
            $return = ( abs((date('G', DATE) - date('G', $date))) < 2)
                ? abs((date('G', DATE) - date('G', $date))) . ' hour ago'
                : abs((date('G', DATE) - date('G', $date))) . ' hours ago';
            break;

        case ($interval >= 86400 && $interval < 604800) :
            $return = ( (int)date('j', $interval) === 1)
                ? (int)date('j', $interval) . ' day ago'
                : (int)date('j', $interval) . ' days ago';
            break;

        case ($interval > 604800 && $interval <= 2592000) :
            $return = 'A few weeks ago';
            break;
        case ($interval > 2592000) :
            $return = date('n', $interval) . ' months ago';
            break;
        case ($interval > 31536000) :
            $return = 'Over a year ago';
            break;

    }

    return $return;

}

【问题讨论】:

  • 也许是个愚蠢的问题,但你为什么不使用简单的数学而不是 date() 函数呢?我猜你已经用数学来计算你的间隔了。
  • 我真的不知道,我想我喜欢date() 在格式化等方面为我工作。它也更容易维护。

标签: php date-formatting


【解决方案1】:

date() 的结果取决于您的时区。您可以通过 date_default_timezone_set() 手动设置时区来更改此行为

【讨论】:

  • 时区绝对有意义 =D,您会看到这是您在凌晨 3 点工作时发生的情况,我的时区是 GMT+2,所以我的输出是 03 而不是 01。非常感谢你。
【解决方案2】:

检查此代码,它运行良好:

function do_plurals($nb, $str)
{
    return $nb > 1 ? $str . 's' : $str;
}


function dates_interval_text(DateTime $start, DateTime $end)
{
    $interval = $end->diff($start);

    $format = array();
    if ($interval->y !== 0)
    {
        $format[] = "%y " . do_plurals($interval->y, "year");
    }
    if ($interval->m !== 0)
    {
        $format[] = "%m " . do_plurals($interval->m, "month");
    }
    if ($interval->d !== 0)
    {
        $format[] = "%d " . do_plurals($interval->d, "day");
    }
    if ($interval->h !== 0)
    {
        $format[] = "%h " . do_plurals($interval->h, "hour");
    }
    if ($interval->i !== 0)
    {
        $format[] = "%i " . do_plurals($interval->i, "minute");
    }
    if (!count($format))
    {
        return "less than a minute ago";
    }

    // We use the two biggest parts
    if (count($format) > 1)
    {
        $format = array_shift($format) . " and " . array_shift($format);
    }
    else
    {
        $format = array_pop($format);
    }

    // Prepend 'since ' or whatever you like
    return $interval->format($format) . ' ago';
}

它会产生类似2 hours and 3 minutes ago 的结果

【讨论】:

  • 您应该注意您的代码使用了native DateTime class
  • 是的,我知道。原生 DateTime 类包含在 PHP 5.2.0 中,所以我认为这不是问题。
  • 是的,但是第一眼我有点不确定,只是看到一堆类引用。只是 dates_interval_text() 参数规范泄露了它。
【解决方案3】:

date('H', 3660) 对我来说是 01。也许正在应用您所在的时区。这可能是在本地级别(应用程序)或全局级别(php 配置)。甚至可能是您的操作系统。很抱歉,对于要查找的 PHP 设置等等,我无法提供更多帮助。

【讨论】:

  • 我确实想到了这一点并检查了一下,我的时区一切正常。谢谢
  • “你的时区没问题”意味着应用的时区是你当前的时区吗?或者意味着 PHP 使用的是 UTC?它确实应该使用 UTC 进行计算,如 Victor 所说,与date('Z') 核对。
【解决方案4】:

date 的第二个参数不是持续时间,而是一个时间戳date 回答问题“UTC 时间 1970 年 1 月 1 日 00:00 后 N 秒,现在几点?” 在您的时区给出了这个问题的答案,因此您的时区偏移量被添加到答案中。

使用date('Z') 查找您的时区偏移量,以秒为单位。或者,更好的是,使用floor($time/3600) 来计算小时数。

【讨论】:

    【解决方案5】:

    您的代码运行良好。 您调用它的方式有误。 当 $date 作为 unix 时间戳传递时,它运行得很好 例如 $date = time() - 1*60*60(1 小时前)。

    http://codepad.org/HS25qThK

    $aboutHourAgo = time() - 2.5*60*60;   // 2 and half hours ago
    var_dump(getTimeInterval($aboutHourAgo));
    

    【讨论】:

      【解决方案6】:

      我的第一个问题是,您从哪里获得时间/时间戳/日期时间?

      在我们公司,我们在德国运行了几台服务器,其上托管的应用程序用于巴基斯坦 (GMT+5)。我们使用这个函数,它需要一个 Unix 时间戳来返回一个“人类可读”的日期时间:-

      /**
       * @desc Converts UNIX Time into human readable time like '1 hour', 3 weeks', etc.
       * @param number $timestamp
       * @return string
       */
      function readable_time($timestamp, $num_times = 2)  {
          // this returns human readable time when it was uploaded
          $times = array (
          31536000 => 'year', 2592000 => 'month',
          604800 => 'week', 86400 => 'day',
          3600 => 'hour', 60 => 'minute', 1 => 'second'
          );
          $now = time ();
          $secs = $now - $timestamp;
          // Fix so that something is always displayed
          if ($secs == 0) $secs = 1;
          $count = 0; $time = '';
          foreach ( $times as $key => $value )    {
              if ($secs >= $key)  {
                  // time found
                  $s = '';
                  $time .= floor ( $secs / $key );
                  if ((floor ( $secs / $key ) != 1))  $s = 's';
                  $time .= ' ' . $value . $s;
                  $count ++;
                  $secs = $secs % $key;
                  if ($count > $num_times - 1 || $secs == 0) break;
                  else $time .= ', ';
              }
          }
          return ($time != "") ? $time." ago" : "now";
      }
      

      通过修改$num_times 变量,我们可以得到类似“4 个月、3 天、2 小时、3 分钟、15 秒前”的信息(在本例中将变量设置为 5)。

      从逻辑上讲,时间戳来自数据库——在我们的例子中是 MySQL——所以我们使用另一个函数来获取 MySQL 时间戳并将其转换为 Unix 时间戳:-

      /**
       * @desc Converts UNIX Time into human readable time like '1 hour', 3 weeks', etc.
       * @param number $timestamp
       * @return string
       */
      function RelativeTime($timestamp)   {
          $difference = time() - $timestamp;
          $periods = array("sec", "min", "hour", "day", "week", "month", "years", "decade");
          $lengths = array("60", "60", "24", "7", "4.35", "12", "10");
          if ($difference > 0)    { // this was in the past
              $ending = "ago";
          }   else    { // this was in the future
              $difference = -$difference;
              $ending = "to go";
          }
          for($j = 0; $difference >= $lengths[$j]; $j++) $difference /= $lengths[$j];
          $difference = round($difference);
          if($difference != 1) $periods[$j].= "s";
          $text = "$difference $periods[$j] $ending";
          return $text;
      }
      

      祝你好运!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多