格式化具有最小差异的日期时间间隔
Format datetime interval with a minimum difference
我 found 这个非常好的 PHP 脚本可以将任何日期时间转换成相对字符串,例如:
'2013-05-01 00:22:35' -> '3 months ago'
这真的很酷,但我想 "trick" 这个函数,这样即使日期是,比方说,20 分钟前,函数 returns 1 hour ago
而不是20 minutes ago
。因此,我想强制执行 1 小时的最小差异,即使差异小于 1 小时。
作为参考,这里是函数。
function time_elapsed_string($datetime, $full = false) {
$now = new DateTime;
$ago = new DateTime($datetime);
$diff = $now->diff($ago);
$diff->w = floor($diff->d / 7);
$diff->d -= $diff->w * 7;
$string = array(
'y' => 'year',
'm' => 'month',
'w' => 'week',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second',
);
foreach ($string as $k => &$v) {
if ($diff->$k) {
$v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : '');
} else {
unset($string[$k]);
}
}
if (!$full) $string = array_slice($string, 0, 1);
return $string ? implode(', ', $string) . ' ago' : 'just now';
}
我尝试了很多不同的方法,但没有任何效果。
如何强制执行 1 小时的最小差异?
days :如果 DateInterval 对象是由 DateTime::diff() 创建的,则这是开始日期和结束日期之间的总天数。否则,days 将为 FALSE。 http://php.net/manual/en/class.dateinterval.php
因为我们知道它不会为 false,所以只有当为 0 时它才会计算为 false。
if($diff->days) {
$diff->w = floor($diff->d / 7);
$diff->d -= $diff->w * 7;
} else /* less than a day's difference */ if(!$diff->h && ($diff->i || $diff->s)) /* less than an hour's difference */ {
$diff->h = 1;
$diff->i = 0;
$diff->s = 0;
}
找出差异后,只需检查最大差异是否只有分钟或秒。如果是这样,return 您需要的最少 1 小时。
// here is your foreach loop
// check if less than 1 hour, if so, return that
$keys = array_keys($string);
if ($keys[0] === 'i' || $keys[0] === 's') {
return 'less than 1 hour ago';
}
Try it online!
我把发题时间放在这个例子里。当您在 1 个多小时后查看它时,您必须将测试用例修改为 UTC 时间小于 1 小时前的 DateTime。
测试用例。 现在是 2017-06-10 12:45:00 UTC。
time_elapsed_string("2017-06-10 12:11:19"); // less than 1 hour ago
time_elapsed_string("2017-06-10 11:44:00"); // 1 hour ago
time_elapsed_string("2017-06-10 11:44:00", true); // 1 hour, 1 minute ago
time_elapsed_string("2017-06-09 11:45:00", true); // 1 day, 1 hour ago
time_elapsed_string("2017-06-09 11:45:00"); // 1 day ago
我对您的原始代码进行了一些改进。我还从您的函数中删除了 full
选项,因为我认为您不打算将它用于您的案例。如果我的内联评论无法解释我的过程,请问。
代码:(Demo)
function time_elapsed_string($datetime){
$now=new DateTime; // current datetime
$ago=new DateTime($datetime); // user datetime
if($now<$ago){return "Unexpected future datetime value";}
$diff=$now->diff($ago); // datetime difference
$diff->w=intval(floor($diff->d/7)); // add weeks to diff output
$diff->d-=$diff->w*7; // reduce days based on weeks calculation
$units=[
'y'=>'year',
'm'=>'month',
'w'=>'week',
'd'=>'day',
'h'=>'hour'
];
$kept_diff=array_intersect_key((array)$diff,$units); // omit unwanted elements of diff()'s output
if(!max($kept_diff)){ // if y, m, w, d, & h all = 0, show default
return 'default: 1 hour ago'; // inserted "default: " for demo. Remove in production.
}else{
$diffs=array_filter(array_merge($units,$kept_diff)); // sort by $units order, then omit elements with 0 value
return current($diffs).' '.$units[key($diffs)].(current($diffs)>1?'s':'').' ago'; // return highest unit data in plain English
}
}
echo time_elapsed_string('2017-06-30 02:22:35'); // output: 3 weeks ago
我 found 这个非常好的 PHP 脚本可以将任何日期时间转换成相对字符串,例如:
'2013-05-01 00:22:35' -> '3 months ago'
这真的很酷,但我想 "trick" 这个函数,这样即使日期是,比方说,20 分钟前,函数 returns 1 hour ago
而不是20 minutes ago
。因此,我想强制执行 1 小时的最小差异,即使差异小于 1 小时。
作为参考,这里是函数。
function time_elapsed_string($datetime, $full = false) {
$now = new DateTime;
$ago = new DateTime($datetime);
$diff = $now->diff($ago);
$diff->w = floor($diff->d / 7);
$diff->d -= $diff->w * 7;
$string = array(
'y' => 'year',
'm' => 'month',
'w' => 'week',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second',
);
foreach ($string as $k => &$v) {
if ($diff->$k) {
$v = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : '');
} else {
unset($string[$k]);
}
}
if (!$full) $string = array_slice($string, 0, 1);
return $string ? implode(', ', $string) . ' ago' : 'just now';
}
我尝试了很多不同的方法,但没有任何效果。
如何强制执行 1 小时的最小差异?
days :如果 DateInterval 对象是由 DateTime::diff() 创建的,则这是开始日期和结束日期之间的总天数。否则,days 将为 FALSE。 http://php.net/manual/en/class.dateinterval.php
因为我们知道它不会为 false,所以只有当为 0 时它才会计算为 false。
if($diff->days) {
$diff->w = floor($diff->d / 7);
$diff->d -= $diff->w * 7;
} else /* less than a day's difference */ if(!$diff->h && ($diff->i || $diff->s)) /* less than an hour's difference */ {
$diff->h = 1;
$diff->i = 0;
$diff->s = 0;
}
找出差异后,只需检查最大差异是否只有分钟或秒。如果是这样,return 您需要的最少 1 小时。
// here is your foreach loop
// check if less than 1 hour, if so, return that
$keys = array_keys($string);
if ($keys[0] === 'i' || $keys[0] === 's') {
return 'less than 1 hour ago';
}
Try it online!
我把发题时间放在这个例子里。当您在 1 个多小时后查看它时,您必须将测试用例修改为 UTC 时间小于 1 小时前的 DateTime。
测试用例。 现在是 2017-06-10 12:45:00 UTC。
time_elapsed_string("2017-06-10 12:11:19"); // less than 1 hour ago
time_elapsed_string("2017-06-10 11:44:00"); // 1 hour ago
time_elapsed_string("2017-06-10 11:44:00", true); // 1 hour, 1 minute ago
time_elapsed_string("2017-06-09 11:45:00", true); // 1 day, 1 hour ago
time_elapsed_string("2017-06-09 11:45:00"); // 1 day ago
我对您的原始代码进行了一些改进。我还从您的函数中删除了 full
选项,因为我认为您不打算将它用于您的案例。如果我的内联评论无法解释我的过程,请问。
代码:(Demo)
function time_elapsed_string($datetime){
$now=new DateTime; // current datetime
$ago=new DateTime($datetime); // user datetime
if($now<$ago){return "Unexpected future datetime value";}
$diff=$now->diff($ago); // datetime difference
$diff->w=intval(floor($diff->d/7)); // add weeks to diff output
$diff->d-=$diff->w*7; // reduce days based on weeks calculation
$units=[
'y'=>'year',
'm'=>'month',
'w'=>'week',
'd'=>'day',
'h'=>'hour'
];
$kept_diff=array_intersect_key((array)$diff,$units); // omit unwanted elements of diff()'s output
if(!max($kept_diff)){ // if y, m, w, d, & h all = 0, show default
return 'default: 1 hour ago'; // inserted "default: " for demo. Remove in production.
}else{
$diffs=array_filter(array_merge($units,$kept_diff)); // sort by $units order, then omit elements with 0 value
return current($diffs).' '.$units[key($diffs)].(current($diffs)>1?'s':'').' ago'; // return highest unit data in plain English
}
}
echo time_elapsed_string('2017-06-30 02:22:35'); // output: 3 weeks ago