相对日期格式始终输出“3 小时前”

发布于 2024-11-17 20:12:38 字数 2179 浏览 2 评论 0原文

我正在使用 php.ini 计算指定日期和当前日期之间的日期间隔。我这样做是为了打印出社交友好的时间戳,例如 几分钟前2 小时前

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

这里定义了常量 DATE

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

Buggy 代码:

//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;

}

I am calculating the date interval between a specified date and the current date using php. I do this so I can print out social friendly timestamps like A few mins ago and 2 hours ago

When I come to the hours part I get something behaving real funny in php. Below is the full working code but when you replace the hours part with this code it always prints out 3 hours.

Defined constant DATE

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

Buggy code here:

//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;

It breaks when the specified date, lets say in this case, create date is just over an hour ago thus resulting in an interval equal to 3660 seconds. It seems like the date method call date('H', 3660) results in 03. Shouldn't it result in 01? it is after all just over an hour.

Working code here:

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;

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

吲‖鸣 2024-11-24 20:12:38

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

result of date() depends on your timezone. You can change this behavior by setting timezone manually by date_default_timezone_set()

小瓶盖 2024-11-24 20:12:38

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

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 小时 3 分钟前 的结果

Check this code, it works good:

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';
}

It produces results like 2 hours and 3 minutes ago

无远思近则忧 2024-11-24 20:12:38

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

date('H', 3660) results in 01 for me. Perhaps the timezone that your in is being applied. That could be at the local level (application) or global level (php config). Maybe even it's your OS. I'm sorry I can't be of much more help with which PHP settings to look for and whatnot.

我的影子我的梦 2024-11-24 20:12:38

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

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

The second argument to date is not a duration, it's a timestamp. date answers the question "N seconds after 01/01/1970 00:00 UTC, what time was it?" and the answer to this question is given in your time zone, so your time zone offset is added to the answer.

Use date('Z') to find your time zone offset, in seconds. Or, even better, use floor($time/3600) to compute the hours.

唠甜嗑 2024-11-24 20:12:38

你的代码运行良好。
您调用它的方式有错误。
当 $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));

Your code is running fine.
There is an error in the way you are calling it.
It runs pretty well when $date is passed as a unix timestamp
eg $date = time() - 1*60*60 ( for 1 hour ago ).

http://codepad.org/HS25qThK

$aboutHourAgo = time() - 2.5*60*60;   // 2 and half hours ago
var_dump(getTimeInterval($aboutHourAgo));
能否归途做我良人 2024-11-24 20:12:38

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

在我们公司,我们在德国运行一些服务器,其上托管的应用程序适用于巴基斯坦 (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;
}

祝你好运!

My first question would be, where are you getting the time/timestamp/datetime from?

At our company, we run a few servers in Germany and the applications hosted on them are for Pakistan (GMT+5). we use this function that takes a Unix Timestamp to return a "Human readable" date time: -

/**
 * @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";
}

By modifying the $num_times variable, we can get something like "4 months, 3 days, 2 hours, 3 minutes, 15 seconds ago" (setting variable to 5, in this example).

Logically, the timestamp comes from a database - in our case MySQL - so we use another function that takes a MySQL timestamp and converts it into a Unix timestamp: -

/**
 * @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;
}

Good Luck!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文