Php 按即将到来的日期排序
所以我建立了一个不同日期的数组。生日、周年纪念日和假日。我想订购下一个发生的数组,基本上是10月到9月的排序(包装到明年) 如果我的数组是Php 按即将到来的日期排序,php,arrays,sorting,Php,Arrays,Sorting,所以我建立了一个不同日期的数组。生日、周年纪念日和假日。我想订购下一个发生的数组,基本上是10月到9月的排序(包装到明年) 如果我的数组是 $a = ([0]=>"1980-04-14", [1]=>"2007-06-08", [2]=>"2008-12-25", [3]=>"1978-11-03") 我想把它分类以便安排好 $a = ([0]=>"1978-11-03", [1]=>"2008-12-25", [2]=>"1980-04-
$a = ([0]=>"1980-04-14", [1]=>"2007-06-08",
[2]=>"2008-12-25", [3]=>"1978-11-03")
我想把它分类以便安排好
$a = ([0]=>"1978-11-03", [1]=>"2008-12-25",
[2]=>"1980-04-14", [3]=>"2007-06-08")
因为11月的“事件”是下一个将要发生的事件(基于现在的10月)
我正在尝试在cmp函数所在的位置进行排序
function cmp($a, $b)
{
$a_tmp = split("-", $a);
$b_tmp = split("-", $b);
return strcmp($a_tmp[1], $b_tmp[1]);
}
我不知道如何修改它以获得我想要的效果。不要比较字符串,而是使用1970年以来的秒数(整数): 我也不懂PHP,但我认为要点是正确的
编辑:比较函数被封装以执行比较,仅此而已。要为原始问题的列表排序,请对包含今天日期的数组进行排序,在数组中找到今天的日期,然后按位置升序将该位置之前的元素移动到末尾。我很想确定事件的原始年份,然后再加上足够的整年,以确保该值大于您的参考日期(通常是今天的日期)。或者,可能大于或等于参考日期。然后可以按简单的日期顺序排序 编辑以添加: 我的PHP不够流利,无法给出答案,但这里有一个Perl解决方案
#!/bin/perl -w
# Sort sequence of dates by next occurrence of anniversary.
# Today's "birthdays" count as low (will appear first in sequence)
use strict;
my $refdate = "2008-10-05";
my @list = (
"1980-04-14", "2007-06-08",
"2008-12-25", "1978-11-03",
"2008-10-04", "2008-10-05",
"2008-10-06", "2008-02-29"
);
sub date_on_or_after
{
my($actdate, $refdate) = @_;
my($answer) = $actdate;
if ($actdate lt $refdate) # String compare OK with ISO8601 format
{
my($act_yy, $act_mm, $act_dd) = split /-/, $actdate;
my($ref_yy, $ref_mm, $ref_dd) = split /-/, $refdate;
$ref_yy++ if ($act_mm < $ref_mm || ($act_mm == $ref_mm && $act_dd < $ref_dd));
$answer = "$ref_yy-$act_mm-$act_dd";
}
return $answer;
}
sub anniversary_compare
{
my $r1 = date_on_or_after($a, $refdate);
my $r2 = date_on_or_after($b, $refdate);
return $r1 cmp $r2;
}
my @result = sort anniversary_compare @list;
print "Before:\n";
print "* $_\n" foreach (@list);
print "Reference date: $refdate\n";
print "After:\n";
print "* $_\n" foreach (@result);
请注意,它在很大程度上回避了2月29日会发生什么的问题,因为这样做“有效”。基本上,它将生成“日期”2009-02-29,按顺序正确比较。2000-02-28的周年纪念将在2008-02-29的周年纪念日之前列出(如果数据中包括2000-02-28)。因此,我想到在任何少于我的目标月的月份中加上12。 它现在正在工作 那么最后一个函数
function cmp($a, $b)
{
$a_tmp = explode('-', $a['date']);
$b_tmp = explode('-', $b['date']);
if ($a_tmp[1] < date('m')) {
$a_tmp[1] += 12;
}
if ($b_tmp[1] < date('m')) {
$b_tmp[1] += 12;
}
return strcmp($a_tmp[1] . $a_tmp[2], $b_tmp[1] . $b_tmp[2]);
}
函数cmp($a,$b)
{
$a_tmp=爆炸('-',$a['date']);
$b_tmp=爆炸('-',$b['date']);
如果($a_tmp[1]<日期('m')){
$a_tmp[1]+=12;
}
如果($b_tmp[1]<日期('m')){
$b_tmp[1]+=12;
}
返回strcmp($a_-tmp[1]。$a_-tmp[2],$b_-tmp[1]。$b_-tmp[2]);
}
函数相对年日($date){
$value=date('z',strottime($date))-date('z');
如果($value<0)
$value+=365;
返回$value;
}
功能cmp($a$b)
{
$aValue=相对年日($a);
$b值=相对年日($b);
如果($aValue==$bValue)
返回0;
回报率($aValue<$bValue)?-1:1;
}
$a=阵列(“1980-04-14”、“2007-06-08”,
"2008-12-25", "1978-11-03");
usort($a,“cmp”);
在将所有日期添加到数组之前,使用strotime()将所有日期转换为时间戳,然后可以将数组按升序(也按时间顺序)排序。现在,您所要做的就是处理过去的日期,这很容易通过将它们与当前时间戳进行比较来完成
i、 e
for($i=0;$i$a[$i]){
未结算($a[$i]);
}
}
没有理由重新发明轮子。如果你不在乎钥匙,你可以用这个
$a = array_combine(array_map('strtotime', $a), $a);
ksort($a);
或者如果您想定义自己的回调函数
function dateCmp($date1, $date2) {
return (strtotime($date1) > strtotime($date2))?1:-1;
}
usort($a, 'dateCmp');
如果您想保持键正确关联,只需调用uasort即可
uasort($a, 'dateCmp');
我做了一个快速的速度检查,回调函数慢了一个数量级。我喜欢那个日期。显然是打字错误。现在更正。如果您试图在已经过去的月份中包含一天(例如,如果您在列表中包含2000年10月1日),那么这将不起作用。当其中一个日期是2008-02-29时会发生什么情况?鉴于今天是2008-10-05,您的代码如何显示处理条目2008-10-042008-10-052008-10-06?特别要注意的是,下一个庆祝2008-10-04的日子要比其他所有正在考虑的日子晚。你还没有定义今天的日期是今年还是明年。而且,麻烦的是,我之前评论中的“显示”是多余的。可能会显示10-04。在这一点上,我并不担心。我可能需要在当前天数的基础上再增加30天。这只是字符串排序,所以像02-29和10-45这样的日子没关系,它只是按顺序排序。我怀疑我的也不是很有效。但我也不觉得我的有02-29错误。嗯,是的,你必须将滴答1和滴答2模化31536000以消除年份,但我担心它会正常工作。
for ($i=0; $i<count($a); $i++){
if ($currentTimestamp > $a[$i]){
unset($a[$i]);
}
}
$a = array_combine(array_map('strtotime', $a), $a);
ksort($a);
function dateCmp($date1, $date2) {
return (strtotime($date1) > strtotime($date2))?1:-1;
}
usort($a, 'dateCmp');
uasort($a, 'dateCmp');