Php 按即将到来的日期排序

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-

所以我建立了一个不同日期的数组。生日、周年纪念日和假日。我想订购下一个发生的数组,基本上是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-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');