<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55
global $wpdb2;
global $failure;
global $file_hist;
///// echo '<H2><b>Старт загрузки</b></H2><br>';
$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
///// echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}
$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
///// echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}
/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
///// echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
///// echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist); ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7]; ////получаем размер файла
$m_mtime_file=$masiv_data_file[9]; ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file
///// echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
///// echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
///// echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);
if ($results)
{ foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));
////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
///// echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
///// echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}
////загружаем данные
$table='vin_history'; // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация // (путь от корня web-сервера)
$delim=';'; // Разделитель полей в CSV файле
$enclosed='"'; // Кавычки для содержимого полей
$escaped='\
как то все сложно, у меня вот так получилось:
Показать
(1) как месяцев может быть 12?
пример покажите,
я лично не вижу куска где такое возможно
Да, невозможно, это я ошибся, только проблема с високосными годами осталась. Дни неправильно считает…
Полагаю в ЗУП уже есть подобные процедуры и функции
А почему именно запросом получать дни?
Ведь гораздо проще соорудить такую, например, конструкцию:
Показать
Вопрос с месяцами скорее методический — как складывать между собой два неполных месяца интервала и с чем сравнивать их суммарное количество дней.
Сравнивать их с 29, 30, 31, с количеством дней в месяце первой даты, с количеством дней в месяце второй даты, или с минимумом количества дней в месяцах обеих дат.
(1) херня. вбейте
Имя параметра Значение параметра
ДР 05.05.2015 0:00:00
ТД 03.05.2017 0:00:00
и получите 1 лет и 29 дней.
Странный запрос в (1) и процедура в (6) странная, и считает не правильно, для 27.04.2017 — 29.02.1988 выдала: «Лет: 29 Месяцев: 1 Дней: 30».
У меня запрос из трех строк выдает следующее:
27.04.2017 — 29.02.1988 = 29 лет 1 мес 27 дней
03.05.2017 — 29.02.1988 = 29 лет 2 мес 3 дня
(10) Для високосного года достаточно добавить одно условие и будет правильно.
Показать
Между прочим, для 03.05.2017 — 29.02.1988 должно быть 29 лет 2 мес 4 дня, а не 3 дня, как у вас.
В экселе с разностью дат аналогичные проблемыhttp://excel2.ru/articles/funkciya-razndat-vychislenie-raznosti-dvuh-dat-v-dnyah-mesyacah-godah-v-ms-excel-razndat по ссылке варианты разностей с полными месяцами и с неполными, альтернативные формулы и немного обсуждения
(6) Я скажу, что такова была постановка задачи, решить которую надо запросом, в коде же модулей было бы значительно проще.
(5) Можете скинуть реализацию из ЗУП?
(11) Ну я считал так:
29.02.1988 — 28.02.2017 = 29 лет
01.03.2017 — 30.04.2017 = 2 мес
01.05.2017 — 03.05.2017 = 3 дня
поправьте меня, где я потерял день?
В моем понимании, 29.02.1988 не должно считаться за день в этом расчете — это собсна день рождения, в этот день у человека «полный год», а вот со след. дня и пошел расчет … «между прочим» )).
P.S.
А «високосный» Вы по прежнему считаете не правильно. А саму конструкцию проверки високосного я бы сделал так: «Год(ДатаР) % 4». Ваш способ, конечно, оригинален, я бы не додумался. Скорее всего я бы сделал так: День(КонецМесяца(ДатаР)) = 29 … вау ))))))))
И еще, у Вас если д/р 29.02.1988, то Високосный = 1, а если 28.02.1988, то Високосный = 0 … странно все ето ))) ужОс !!
(15) Високосный нужен только для 29.02, остальные дни считаются одинаково.
Логика расчета проста: каждое число следующего месяца, совпадающее с днем рождения дает полный месяц. Каждый следующий день, если месяц неполный, добавляется к дням. Именно так у вас «потерялся» один день. Полный месяц приходится на 29-е число. Затем идут 30,1,2,3. Итого 4 дня.
(16) Да, Вы правы. Я зачем-то считал календарные месяцы, вместо реальных.
Переделал запрос, теперь все четко:
(15) из википедии:
(14) В ЗУП не нашёл. Может быть это?
http://kb.mista.ru/article.php?id=664
Нашел и у себя ошибку. На 28-м числе дает неверные значения. Вот так поправил, теперь вроде с 29.02 все верно:
Показать
А можно еще упростить, ведь сбивается общий расчет только для 29.02 при переходе с високосного года на обычный:
Показать
Вот мой реально работающий код в отчете:
Показать
(20) Вчера гонял Ваш предыдущий вариант на ошибки и видел что на 28 числе они были, сейчас проверим новый вариант )).
Думаю, что и в Вашем варианте и в варианте из (22) будут ошибки, а думаю так, потому что Вы используете деление на «сутки». Чисто математически, очевидно, что при расчете за 1000 лет «что-то пойдет не так».
(18)
… НЕ кратен 100, либо кратен 400 …
Мой мозг не смог впитать сие …
(24)
Год високосный в одном из двух случаев:
1) кратен 4, но при этом не кратен 100, например, 16, 96, 1996.
2) кратен 400, например 800, 2000.
Иначе — обычный, например, 100, 200, 300.
(23)Сомневаюсь, что за 1000 лет что-то поменяется. Если только календарь вдруг закончится, как у Майя. 🙂
В моем алгоритме загвоздка была только в добавлении месяца с 29.01 до 29.02. 1C автоматом исправляла недопустимую дату на 28.02, если год не високосный. Достаточно было это обойти, чтобы программа заблистала во всей красе.
(25)
Если уж совсем быть точными, григорианский календарь запустили 4 октября 1582 года, то есть кратные 400 года надо считать високосными если год>=1600. Но в нашем случае это, думаю, несущественно.
(25) , (27)
Да, я видимо, застрял в юлианском календаре. Теперь вместо «Год % 4» буду делать
Кстати, в 1С 400,800,1200 — високосные, т.е. уже не важно, что запустили в 1582 году )).
(26) Проверил Ваш новый вариант, количество ошибок прежнее, просто они чуть сместились по дням, вот пара замеров:
Показать
На всякий случай, замечу, что я в своих расчетах не использую определение «високосности».
А Ваш цикл расчета месяцев всегда будет «грешить», т.к. конец месяца будет сбиваться не только в феврале и не обязательно в високосный год:
— 29.11.2016 + з мес = 28.02.2017 ( 29 -> 28 )
— 31.03.2017 + 3 мес = 30.06.2017 ( 31 -> 30 )
имеется в виду ДобавитьМесяц(Дата, 3).
Задайте ДР = 31.03.1975 и ДТ = 29.01.2017:
— старый = Лет: 41 Месяцев: 10 Дней: 1
— новый = Лет: 41 Месяцев: 9 Дней: 30
— д.быть = 29.01.2017 = 41 — 09 — 29.
Тут вот еще замер производительности сделал, вариант (26) с циклом, явно проигрывает:
Показать
(30) Ну, понятно, что на множественных циклах будет потеря времени. Тогда и алгоритм можно другой сделать, просто прибавляя по дню к полученному первоначально значению.
Я переделал свою обработку. Проверяйте.
Показать
Остается открытым вопрос: от дня рождения на 31.05.2016 до 28.02.2017 будет полных 9 месяцев или 8 месяцев и 28 дней?
недокументированная Разндат() экселя считает, что 8
(32)Тогда получается, что полных 9 месяцев никогда не будет, что несколько странно. Придется еще костылей добавлять.
С 31.05.2016 по 01.03.2017эксель считает 9 полных месяцев, или я что-то не понял?
(34)У меня получается 0 дней, если числа дат совпадают. Следующая дата это уже n-месяцев + 1 день.
(31) Я, думаю, что это 9 полных месяцев, т.к. «месячный» день рождения приходится именно на 28.02.2017.
Вроде можно проще:
(37) Вы когда этот комментарий писали, думали хоть, что в контексте моего запроса и задачи он вообще ничего значит. Зачем мне количество полных лет кодом, когда я написал, что задачу необходимо решать запросом было? Или Вы может не мне написали?
(38) Дали задачу в ЗУП 3.1 посчитать стаж работника на предприятии относительно даты приёма. Чтоб не рисовать новый код и отчёт, взял отчёт «Штатные сотрудники». Изменяя вариант, добавил в предприятии 3 пользовательских поля-выражения:
Лет, выражение:
РазностьДат([Дата приема], ТекущаяДата(), «ГОД») + Выбор
Когда Месяц([Дата приема]) < Месяц(ТекущаяДата()) Или Месяц([Дата приема]) = Месяц(ТекущаяДата()) И День([Дата приема]) <= День(ТекущаяДата())
Тогда 0
Иначе -1
Конец
Месяцев, выражение:
(РазностьДат(ДобавитьКДате([Дата приема], «Месяц», 1), ТекущаяДата(), «МЕСЯЦ») + Выбор
Когда День([Дата приема]) <= День(ТекущаяДата())
Тогда 1
Иначе 0
Конец) % 12
Дней, выражение:
Выбор
Когда День([Дата приема]) <= День(ТекущаяДата())
Тогда День(ТекущаяДата()) — День([Дата приема])
Иначе День(ТекущаяДата()) + РазностьДат([Дата приема], КонецПериода([Дата приема], «Месяц»), «День»)
Конец + 1.
В детальных записях их вывел и сгруппировал в группу «Стаж на предприятии». Кадровики довольны.
Но это писал на языке СКД, в обычных запросах надо дописать несколько строк, чтобы получить остаток от деления на 12 при вычислении полных месяцев, а текущую дату втыкать параметром в запрос. Думаю, в решении Вашей задачи вполне может помочь.
Вот моя реализация вашей задачи, прошу закрепить, она считает полное количество лет, но можно легко переделать чтобы еще количество месяцев и дней выводила. Встал вопрос решить в запросе т.к. не нашел пришлось самому писать:
(40)
Правильнее будет заменить «>» на «>=», тогда если день рождения совпадет с текущей датой, то количество полных лет будет максимальное уже на эту дату.
(16) Может показалось …
Каков возраст на 01.03.2019 в полных годах, если дата рождения будет 29.02.2008, покажет Ваш запрос ?
У меня Ваш запрос показал след. результаты:
ДатаРождения ТекущаяДата Условие ПолныхЛет
29.02.2008 0:00:00 01.03.2019 0:00:00 > 12
29.02.2008 0:00:00 01.03.2019 0:00:00 >= 12
(42) Не найду эту обработку. Чисто теоретически (по моим алгоритмам) должно быть 11 лет и 1 день.
(43) Ой, не к тому сообщению написал … это я к сообщению № 40
Мои расчеты показывают такой же результат )), а вот у ребят как-то странно!
(40) Может показалось …
Каков возраст на 01.03.2019 в полных годах, если дата рождения будет 29.02.2008, покажет Ваш запрос ?
У меня Ваш запрос показал след. результаты:
ДатаРождения ____ ТекущаяДата _____ Условие ____ ПолныхЛет
29.02.2008 0:00:00 ___ 01.03.2019 0:00:00 ___ > ___ 12
29.02.2008 0:00:00 ___ 01.03.2019 0:00:00 ___ >= ___ 12
(45) Попробуйте вот так. Должно все правильно считать.
ДатаРождения: 29.02.2019
ТекущаяДата: 28.02.2019
Тоже считает правильно, как полных — 11лет.
Явот тут уже публиковал свой запрос. Повторю его здесь:
Показать
(47) На датах 29.02.2008 — 28.02.2019
Он показывает 11лет -1 месяц 31 день.
Это дата кстати на многих онлайн калькуляторах расчета возраста даёт очень интересные результаты)))
Что-то, за два года, мы так и не увидели «правильный» запрос по расчету возраста в Год-Месяц-День … будем ждать дальше ))
Да, онлайн калькуляторы тоже смотрел, ржал, почти все показывают какую-то ерунду.