Я обнаружил неожиданное поведение сортировки со строковыми значениями в форме YYYY-MM-DD
такие как 2016-12-16
когда используешь Collator::asort
. Использование PHP нормально asort
Нет проблем. С версией Collator, похоже, что есть какая-то ошибка, и вместо этого она сортируется по ключам массива.
Изменить: я использую версию PHP 5.6.29 для этого теста.
Я сделал небольшую примерную программу, чтобы показать проблему:
<?php
$list["off-to-the-races"] = "2015-04-14";
$list["new-years-2015"] = "2015-01-01";
$list["ground-hog-day"] = "2015-02-02";
$list["back-to-the-future"] = "2015-08-12";
$locale = setlocale(LC_COLLATE, 0);
$col = Collator::create($locale);
$res_val = collator_get_locale( $col, \Locale::VALID_LOCALE );
$res_act = collator_get_locale( $col, \Locale::ACTUAL_LOCALE );
echo "<pre>";
printf( "Valid locale name: %s <br /> Actual locale name: %s <br />",
$res_val, $res_act );echo "<br /><br />Raw List: <br />";
print_r($list);$col->asort($list);
echo "<br /><br />\$col->asort(\$list): <br />";
print_r($list);
echo "<br /><br />Collator error message: <br />";
echo $col->getErrorMessage();
asort($list, $sort_flags);
echo "<br /><br />asort(\$list) (without collation): <br />";
print_r($list);
Вот мой вывод на тестовом сервере:
Valid locale name: en_US_POSIX
Actual locale name: en_US_POSIXRaw List:
Array
(
[off-to-the-races] => 2015-04-14
[new-years-2015] => 2015-01-01
[ground-hog-day] => 2015-02-02
[back-to-the-future] => 2015-08-12
)$col->asort($list):
Array
(
[back-to-the-future] => 2015-08-12
[ground-hog-day] => 2015-02-02
[new-years-2015] => 2015-01-01
[off-to-the-races] => 2015-04-14
)Collator error message:
U_ZERO_ERROR
asort($list) (without collation):
Array
(
[new-years-2015] => 2015-01-01
[ground-hog-day] => 2015-02-02
[off-to-the-races] => 2015-04-14
[back-to-the-future] => 2015-08-12
)
Как видите, при использовании $col->asort($list)
он не в исходном порядке, но явно не отсортирован, как ожидалось.
Весь смысл использования YYYY-MM-DD
Способ представления даты в виде строки заключается в том, что в случае сортировки в виде строки она будет в алфавитном и хронологическом порядке в большинстве реализаций.
Обратите внимание, если я добавлю следующий контрольный пример с $sort_flag
задавать:
$col->asort($list, 1 );
echo "<br /><br />\$col->asort(\$list, 1): <br />";
print_r($list);
это будет работать правильно:
$col->asort($list, 1):
Array
(
[new-years-2015] => 2015-01-01
[ground-hog-day] => 2015-02-02
[off-to-the-races] => 2015-04-14
[back-to-the-future] => 2015-08-12
)
Хотя это адекватный обходной путь, если вы знаете, что все ваши значения будут в этом формате, я ожидал бы, что он также будет работать как естественная или строковая сортировка — для случаев, когда ваши значения представляют собой смеси строк даты и других произвольных строк.
Я не уверен, является ли это специфическим для данной локали / сопоставления. Есть ли способ отладки дальше?
Задача ещё не решена.
Других решений пока нет …