Исходная информация:
Если в лог-файле не появляются январские строки, то речь идет только о текущем году. Пример:
Если январь встречается один или несколько раз в месячном цикле, то текущий год начинается с начала последнего появления (января). Пример:
Код:
Распознайте, какой год он основан на трех буквах и строках, и добавьте правильный год к каждой строке.
$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
)
setYear()
не имеет параметров, почему вы вызываете его с $y
в качестве аргумента?
В комментарии говорится, что вы проверяете Jan
как первое слово строки. Так почему вы ищете 01
во всем массиве?
Это домашнее задание? Не похоже, что вы действительно пытались решить эту проблему, поскольку ваш код даже близко не подходит к тому, что вы хотите. Похоже, вы только что разместили соответствующий код, чтобы мы сделали это за вас.
Я не знаю, справедливая ли это оценка @Barmar. Хотя попытка кодирования ошибочна, это не просто словесный салат, это выглядит как разумная попытка выполнить описанную задачу. Я просто надеюсь, что массив со 100% гарантией будет содержать запись Jan
, чтобы можно было переключать флаг смены года.
// if the 1st line doesn't start with Jan, then it's the previous year.
- кажется немного произвольным. Набор данных в вашем примере не содержит непрерывного набора месяцев - так это вообще данность, что январь всегда будет там? Если бы ваш пример выше был декабрь-февраль-июнь-декабрь, то февраль и июнь по-прежнему принадлежали бы 2023 году.
@Barmar, возможно, для некоторых мой вопрос и описание не соответствуют их уровню. Мне жаль. Как новичок, мне может понадобиться время, чтобы приобрести ожидаемые навыки программирования. Я пытаюсь архивировать файлы журналов, отфильтрованные и очищенные категорически, как файл json. Для этого я создаю файл cronjob в php... Я часто застреваю, крутлюсь по кругу и застреваю... шлейф и ошибка...
@ 0stone0, что такое переменная?
@CBroe, я хотел, чтобы описание было кратким. Также может случиться так, что для определенного месяца нет записей.
Если январь не обязательно должен присутствовать - тогда ваш подход к явной проверке этого не имеет особого смысла для начала. Так что эта информация абсолютно необходима для вашего вопроса. «Краткость» не должна побеждать ясность.
Или вы пытались сказать, что январь всегда будет, а другие месяцы могут быть, а могут и не быть? Даже это сейчас не совсем ясно.
@CBroe, да, ты прав. нет месяца без активности. файлы logiles синхронизируются через регулярные промежутки времени. затем он обрабатывается другим cronjob. строки файлов журнала не содержат указание года. Переход от прошлого года к текущему признается по январю. Я пересмотрел вопрос. Спасибо.
Используйте переменную 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 добавлен новый фрагмент.
Я понял, что был преждевременным. Что произойдет, если Ян появится больше раз или не появится вообще? Я отредактировал свой вопрос, чтобы он был немного более подробным, и добавил некоторую справочную информацию. Прости меня за мой хаотичный характер. Это еще раз доказывает, что мне еще многому предстоит научиться. Принимаете ли вы небольшие заказы за оплату?
Есть ли что-то в моем обновленном ответе, что не удовлетворяет?
Привет. Спасибо. Самый высокий год всегда является текущим годом. В вашем примере есть даты в будущем или только 2022 год. Если нет переходного месяца, все месяцы должны быть 2023. Я пробовал, но не могу найти решение.
@Cem Я добавил последнее редактирование.
это выглядит идеально, я проверю код в понедельник. Я вам очень благодарен. благодаря вам я иду вперед. Я владею тобой кое-что. LG из Вены.
привет, я изменил код и вижу, что он работает как положено. Следующее, что мне нужно сделать: поместить файлы json с правильным содержимым в правильные каталоги (год/месяц). Мне нужна поддержка здесь, потому что моих знаний здесь уже недостаточно. Можно ли мне помочь здесь за плату? Спасибо
Я очень дорогой для найма. Вам будет лучше попытаться стать разработчиком самостоятельно, а затем опубликовать новый вопрос, когда вы застряли. Верь в себя, работай, учись по ходу дела. Если вы не будете делать эти вещи, вы не будете расти.
Спасибо за вашу честность и мотивацию – это мотивирует меня.
Глобальная кариес останется прежней?