Упорядочить файлы по нестандартной дате в имени файла (PHP) - PullRequest
3 голосов
/ 20 апреля 2011

Я работаю с PHP-скриптом, который позволяет вести хронологический просмотр сгенерированных Eggdrop IRC-журналов. Первоначально я читал содержимое каталога и вставлял имена журналов в массив на основе даты изменения файла. Однако после недавнего перемещения сервера даты обновления файлов были обновлены, и навигация теперь неупорядоченная!

Структура имени файла журнала выглядит следующим образом:

channel.log.dayMONTHyear.txt

например:

shrawberry.log.08Apr2011.txt

, который из-за того, что он достаточно читабелен, трудно правильно заказать.

Поскольку код месяца всегда состоит из трех символов и занимает предсказуемую позицию в последовательности, я мог бы вручную проанализировать нестандартный код даты в метку времени Unix, выполнить итерацию по списку и добавить каждый элемент в массив с этой меткой времени а затем отсортировать массив по этому номеру.

Но это звучит чрезмерно.

Я на деньгах или предложенное мной решение идеально?


С помощью Марка Б. я реализовал следующее:

function dateFromEggLog($string){
    $month = substr($string,-11,-8);
    $day = substr($string,-13,-11);
    $year = substr($string,-8,-4);

    for($i=1;$i<=12;$i++){
        if(strtolower(date("M", mktime(0, 0, 0, $i, 1, 0))) == strtolower($month)){
            $month = $i;
            break;
        }
    }

    return "$year-$month-$day";
}

function my_compare($a, $b) {
    $a_date = dateFromEggLog($a);
    $b_date = dateFromEggLog($b);
    if ($a_date == $b_date) {
        return 0;
    }
    $a = strtotime($a_date); // convert to PHP timestamp
    $b = strtotime($b_date); // convert to PHP timestamp

    return (($a < $b) ? -1 : 1);
}

Это успешно сортирует мои журналы, без необходимости копаться в моем массиве.

Ответы [ 3 ]

3 голосов
/ 20 апреля 2011

Ваш пример имени файла не соответствует образцу "выглядит как" - 'txt' и строка даты поменялись местами.но в любом случае вы можете использовать функцию PHP usort(), которая позволяет пользовательской функции выполнять сравнения.

Это может быть не особенно эффективно, но вам следуеткак то так:

function my_compare($a, $b) {
    $a_date = ... extract date field from filename in $a
    $b_date = ... extract date field from filename in $b
    if ($a_date == $b_date) {
        return 0;
    }
    $a = strtotime($a_date); // convert to PHP timestamp
    $b = strtotime($b_date); // convert to PHP timestamp

    return (($a < $b) ? -1 : 1);
}

usort($array_of_filenames, 'my_compare');
0 голосов
/ 20 апреля 2011

Почему бы не в вашей функции сортировки изменить порядок channel.log.dayMONTHyear.txt на channel.log.yyyymmdd.txt, используя манипуляции со строками, а затем использовать базовое сравнение строк?

<?php

/* Helper stuff */

$months = Array(
  "Jan" => "01", "Feb" => "02", "Mar" => "03",
  "Apr" => "04", "May" => "05", "Jun" => "06",
  "Jul" => "07", "Aug" => "08", "Sep" => "09",
  "Oct" => "10", "Nov" => "11", "Dec" => "12"
);

/* The hard work */

function convertLogFilename($file) {

   $pos = strpos($file, ".log.");
   if ($pos === FALSE)
      throw new Exception("Invalid log file format");

   $pos += strlen(".log.");

   $dd   = substr($file, $pos, 2);
   $mm   = substr($file, $pos + 2, 3);
   $yyyy = substr($file, $pos + 5, 4);

   return substr($file, 0, $pos) . "$yyyy${months[$mm]}$dd.txt";
}

function sort_func($a, $b) {
   return convertLogFilename($a) < convertLogFilename($b);
}


/* Your program */

$files = Array(
   "channel.log.18Apr2011.txt",
   "channel2.log.21Jan2002.txt"
);

usort($files, 'sort_func');
print_r($files);
?>

Выход:

Array
(
    [0] => channel2.log.21Jan2002.txt
    [1] => channel.log.18Apr2011.txt
)

Это должно быть значительно быстрее, чем создание полных представлений даты для каждого имени файла.

0 голосов
/ 20 апреля 2011

Вы использовали filemtime раньше?Почему бы не использовать filectime сейчас?

...