Добавьте логическое значение функции года и замените трехбуквенный месяц на его номер месяца в массиве строк

Исходная информация:

  • Файл журнала копируется и считывается через равные промежутки времени.
  • Строки файла журнала не имеют спецификации года.
  • Месяцы идут непрерывно.
  • До января всегда предшествующий год.

Если в лог-файле не появляются январские строки, то речь идет только о текущем году. Пример:

  • 2023 март,
  • 2023 апр,
  • 2023 май,
  • 2023 июн

Если январь встречается один или несколько раз в месячном цикле, то текущий год начинается с начала последнего появления (января). Пример:

  • 2021 ноябрь,
  • 2021 дек,
  • 2021 дек
  • 2022 янв, // новый год
  • 2022 янв,
  • 2022 фев,
  • ...
  • 2022 дек,
  • 2023 янв, // новый год, последний янв = фактический год
  • 2023 янв,
  • 2023 фев,
  • ...

Код:

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

$arr = [
    // without first Dec, Jan and Jan lines:
    // all subsequent lines are the current year
    "Dec 23 21:37:56 hello",
    "Jan 12 02:08:23 hello",
    "Jan 16 17:34:33 hello",
    "Feb  4 12:21:09 hello",
    "Mar 19 17:07:26 hello",
    "Apr  1 00:00:03 hello",
    "Apr 12 23:07:39 hello",
    "May 21 04:09:34 hello",
    "Jun  7 23:34:56 hello",
    "Jul  1 14:45:34 hello",
    "Aug 13 11:37:23 hello",
    "Sep 29 07:36:03 hello",
    "Oct 30 09:01:00 hello",
    "Nov 10 11:00:03 hello",
    "Dec 25 21:47:51 hello"
];

Создайте функцию для нахождения лет.

function setYear()
{
    global $arr, $y;
    $first = explode(' ', $arr[array_key_first($arr)]);
    
    // if the 1st line doesn't start with Jan, then it's the previous year.
    if (!in_array('01', $first)) {
        $y = date("Y", strtotime("-1 year"));
    } else {
        $y = date("Y");
    }
    return $y;
}

Преобразование даты, года и месяца в целое число

$arr = preg_replace_callback(
    '/^(\w+)\s+(\d+)\s/',
    function ($matches) {
        global $y;
        $yy = setYear($y);
        return date($yy . ' m d', strtotime($matches[0] . ' ' . date("Y"))) . ' ';
    },
    $arr
);

echo '<pre>';
print_r($arr);
echo '</pre>';

Неожиданный результат:

Array
(
    [0] => 2022 12 23 21:37:56 hello
    [1] => 2022 01 12 02:08:23 hello
    [2] => 2022 01 16 17:34:33 hello
    [3] => 2022 02 04 12:21:09 hello
    [4] => 2022 03 19 17:07:26 hello
    // ...
    [9] => 2022 11 10 11:00:03 hello
    [10] => 2022 12 25 21:47:51 hello
)

Ожидаемый результат:

Array
(
    [0] => 2023 12 23 21:37:56 hello
    [1] => 2022 01 12 02:08:23 hello
    [2] => 2022 01 16 17:34:33 hello
    [3] => 2022 02 04 12:21:09 hello
    [4] => 2022 03 19 17:07:26 hello
    // ...
    [9] => 2022 11 10 11:00:03 hello
    [10] => 2022 12 25 21:47:51 hello
)

Глобальная кариес останется прежней?

0stone0 08.02.2023 17:24
setYear() не имеет параметров, почему вы вызываете его с $y в качестве аргумента?
Barmar 08.02.2023 17:29

В комментарии говорится, что вы проверяете Jan как первое слово строки. Так почему вы ищете 01 во всем массиве?

Barmar 08.02.2023 17:32

Это домашнее задание? Не похоже, что вы действительно пытались решить эту проблему, поскольку ваш код даже близко не подходит к тому, что вы хотите. Похоже, вы только что разместили соответствующий код, чтобы мы сделали это за вас.

Barmar 08.02.2023 17:35

Я не знаю, справедливая ли это оценка @Barmar. Хотя попытка кодирования ошибочна, это не просто словесный салат, это выглядит как разумная попытка выполнить описанную задачу. Я просто надеюсь, что массив со 100% гарантией будет содержать запись Jan, чтобы можно было переключать флаг смены года.

mickmackusa 08.02.2023 23:34
// if the 1st line doesn't start with Jan, then it's the previous year. - кажется немного произвольным. Набор данных в вашем примере не содержит непрерывного набора месяцев - так это вообще данность, что январь всегда будет там? Если бы ваш пример выше был декабрь-февраль-июнь-декабрь, то февраль и июнь по-прежнему принадлежали бы 2023 году.
CBroe 09.02.2023 09:01

@Barmar, возможно, для некоторых мой вопрос и описание не соответствуют их уровню. Мне жаль. Как новичок, мне может понадобиться время, чтобы приобрести ожидаемые навыки программирования. Я пытаюсь архивировать файлы журналов, отфильтрованные и очищенные категорически, как файл json. Для этого я создаю файл cronjob в php... Я часто застреваю, крутлюсь по кругу и застреваю... шлейф и ошибка...

Cem Firat 09.02.2023 09:50

@ 0stone0, что такое переменная?

Cem Firat 09.02.2023 09:58

@CBroe, я хотел, чтобы описание было кратким. Также может случиться так, что для определенного месяца нет записей.

Cem Firat 09.02.2023 10:00

Если январь не обязательно должен присутствовать - тогда ваш подход к явной проверке этого не имеет особого смысла для начала. Так что эта информация абсолютно необходима для вашего вопроса. «Краткость» не должна побеждать ясность.

CBroe 09.02.2023 10:33

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

CBroe 09.02.2023 10:36

@CBroe, да, ты прав. нет месяца без активности. файлы logiles синхронизируются через регулярные промежутки времени. затем он обрабатывается другим cronjob. строки файлов журнала не содержат указание года. Переход от прошлого года к текущему признается по январю. Я пересмотрел вопрос. Спасибо.

Cem Firat 09.02.2023 11:19
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
12
117
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Используйте переменную static вместо включения глобальных переменных в область видимости с помощью global. Ключевое слово static гарантирует, что объявление предыдущих итераций будет сохранено и доступно. Если Jan встречается или встречалось ранее, установите флаг как true. Пока флаг не установлен на true, вычтите 1 год из года даты.

Код: (Демо)

var_export(
    preg_replace_callback(
        '/^([a-z]{3}) +\d+/i',
        function($m) {
            static $encounteredJan = false;
            $encounteredJan = $encounteredJan || $m[1] === 'Jan';
            return date('Y m d', strtotime($m[0] . ($encounteredJan ? '' : ' -1 year')));
        },
        $arr
    )
);

Если вы не можете полагаться на январь, существующий в наборе данных, тогда (при условии, что вам никогда не нужно прыгать более чем на один год вперед) просто проверьте, меньше ли текущий месяц, чем последний встреченный месяц. Если, скажем, идти с сентября по апрель (с 10 по 4), то можно смело предположить, что год нужно увеличивать/приращать.

Код: (Демо)

var_export(
    preg_replace_callback(
        '/^([a-z]{3}) +\d+/i',
        function($m) {
            static $lastMonthInt = 0;
            static $year = null;
            $year ??= date('Y', strtotime('-1 year'));
            $currentMonthInt = date('n', strtotime($m[1]));
            if ($currentMonthInt < $lastMonthInt) {
                ++$year;
            }
            $lastMonthInt = $currentMonthInt;
            return "$year " . date('m d', strtotime($m[0]));
        },
        $arr
    )
);

Окончательное редактирование:

Чтобы убедиться, что самым высоким сгенерированным годом является текущий год, используйте array_reverse() для обработки данных от последней записи до самой ранней записи. Сравните стандартизированное выражение временной метки с предыдущей временной меткой. Когда текущий штамп больше предыдущего, уменьшите год. По завершении обработки вызовите array_reverse() результат, чтобы вернуть его в исходный порядок.

Код: (Демо)

var_export(
    array_reverse(
        preg_replace_callback(
            '/^[a-z]{3} +\d+ \d\d:\d\d:\d\d/i',
            function($m) {
                static $lastStamp = null;
                static $year = null;
                $year ??= date('Y');
                $currentStamp = date('m d H:i:s', strtotime($m[0]));
                if ($currentStamp > ($lastStamp ?? $currentStamp)) {
                    --$year;
                }
                $lastStamp = $currentStamp;
                return "$year $currentStamp";
            },
            array_reverse($arr)
        )
    )
);

как все сложно. Я снова кое-что узнаю об этом. Я вам очень благодарен. Я еще не знал "статическую переменную". Я должен прочитать это.

Cem Firat 09.02.2023 09:57

Я понял, что предыдущий год берется, даже если в строке нет «джан». У меня нет знаний, чтобы отредактировать/дополнить ваше предложение. Я немного отредактировал вопрос. Вот ссылка что я имею в виду

Cem Firat 09.02.2023 13:57

Я все время пробую. Я не могу понять это. это вне моей логики: ссылка

Cem Firat 09.02.2023 17:27

@Cem добавлен новый фрагмент.

mickmackusa 10.02.2023 00:55

Я понял, что был преждевременным. Что произойдет, если Ян появится больше раз или не появится вообще? Я отредактировал свой вопрос, чтобы он был немного более подробным, и добавил некоторую справочную информацию. Прости меня за мой хаотичный характер. Это еще раз доказывает, что мне еще многому предстоит научиться. Принимаете ли вы небольшие заказы за оплату?

Cem Firat 10.02.2023 14:57

Есть ли что-то в моем обновленном ответе, что не удовлетворяет?

mickmackusa 11.02.2023 12:14

Привет. Спасибо. Самый высокий год всегда является текущим годом. В вашем примере есть даты в будущем или только 2022 год. Если нет переходного месяца, все месяцы должны быть 2023. Я пробовал, но не могу найти решение.

Cem Firat 11.02.2023 20:05

@Cem Я добавил последнее редактирование.

mickmackusa 11.02.2023 22:46

это выглядит идеально, я проверю код в понедельник. Я вам очень благодарен. благодаря вам я иду вперед. Я владею тобой кое-что. LG из Вены.

Cem Firat 12.02.2023 10:58

привет, я изменил код и вижу, что он работает как положено. Следующее, что мне нужно сделать: поместить файлы json с правильным содержимым в правильные каталоги (год/месяц). Мне нужна поддержка здесь, потому что моих знаний здесь уже недостаточно. Можно ли мне помочь здесь за плату? Спасибо

Cem Firat 14.02.2023 11:56

Я очень дорогой для найма. Вам будет лучше попытаться стать разработчиком самостоятельно, а затем опубликовать новый вопрос, когда вы застряли. Верь в себя, работай, учись по ходу дела. Если вы не будете делать эти вещи, вы не будете расти.

mickmackusa 14.02.2023 12:55

Спасибо за вашу честность и мотивацию – это мотивирует меня.

Cem Firat 14.02.2023 16:16

Другие вопросы по теме