У меня будет соблазн установить исходный год события, а затем добавить к нему достаточное количество целых лет, чтобы обеспечить значение, превышающее вашу контрольную дату (обычно сегодняшнюю дату). Или, возможно, больше или равно контрольной дате. Затем вы можете отсортировать в простом порядке дат.
Отредактировано для добавления :
Я недостаточно свободно владею 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);
Понятно, что это не очень эффективно - чтобы сделать это эффективным, вы должны вычислить значение date_on_or_after () один раз, а затем отсортировать по этим значениям. Сравнение Perl немного своеобразно - переменные $ a и $ b магические и выглядят как будто из ниоткуда.
При запуске скрипт выдает:
Before:
* 1980-04-14
* 2007-06-08
* 2008-12-25
* 1978-11-03
* 2008-10-04
* 2008-10-05
* 2008-10-06
* 2008-02-29
Reference date: 2008-10-05
After:
* 2008-10-05
* 2008-10-06
* 1978-11-03
* 2008-12-25
* 2008-02-29
* 1980-04-14
* 2007-06-08
* 2008-10-04
Обратите внимание, что это в значительной степени ставит вопрос о том, что происходит с 29 февраля, потому что это "работает", чтобы сделать это. По сути, он сгенерирует «дату» 2009-02-29, которая корректно сравнивается по порядку. Годовщина 2000-02-28 будет указана до годовщины 2008-02-29 (если 2000-02-28 были включены в данные).