LINUX.ORG.RU

Посчитать количество дней рождений за период. Как?

 


1

2

Посчитать количество дней рождений за период. PHP

Я с изумлением не вижу простого решения.

  1. Переберать весь период в цикле?

  2. Считать количество лет. Приводить к одному году и добовля или не добавлять единицу?

Спасибо.

function birthday_count($md_birthday, $from, $to) {
	$years = intval(substr($to, 0, 4)) - intval(substr($from, 0, 4));
	$md_from = substr($from, 5,5);
	$md_to = substr($to, 5,5);
	return $years - ($md_birthday < $md_from ? 1 : 0) + ($md_birthday <= $md_to ? 1 : 0);
}

echo birthday_count("01-03", "2020-01-03", "2020-01-03"); // 1
echo birthday_count("01-03", "2020-01-03", "2020-12-31"); // 1
echo birthday_count("01-03", "2020-01-03", "2021-01-03"); // 2
echo birthday_count("01-03", "2020-01-04", "2021-01-03"); // 1
Tanger ★★★★★
()
Ответ на: комментарий от Tanger

Предложу свой велосипед

<?php

function birthdayCount(DateTimeImmutable $birthDay, DateTimeImmutable $from, DateTimeImmutable $to): int
{
    if($to < $birthDay) {
        return 0;
    }
    $firstBirthDay = new DateTimeImmutable("{$birthDay->format('d-m')}-{$from->format('Y')}");
    $period = new DatePeriod(
        $firstBirthDay,
        new DateInterval('P1Y'),
        $to
    );

    return count(iterator_to_array($period->getIterator())) - 1;
}


// tests

echo birthdayCount(
        new DateTimeImmutable('23-03-2000'),
        new DateTimeImmutable('01-01-2000'),
        new DateTimeImmutable('31-12-2020'),
    ) === 20, PHP_EOL;
echo birthdayCount(
        new DateTimeImmutable('23-03-2000'),
        new DateTimeImmutable('01-01-2005'),
        new DateTimeImmutable('31-12-2020'),
    ) === 15, PHP_EOL;
echo birthdayCount(
        new DateTimeImmutable('23-03-2000'),
        new DateTimeImmutable('01-01-2000'),
        new DateTimeImmutable('31-12-2015'),
    ) === 15, PHP_EOL;
Noob_Linux ★★★★
()
Последнее исправление: Noob_Linux (всего исправлений: 1)

Элементарно, применим метод Монте-Карло!

DECLARE FUNCTION RandomDateBetweenDates$(startDate$, endDate$)

DIM startDate$, endDate$, randomDate$, yearsDifference AS LONG
DIM trials AS LONG, countFullYears AS LONG, i AS LONG
DIM year1 AS INTEGER, year2 AS INTEGER

PRINT "Enter start date (YYYY-MM-DD):"
INPUT startDate$
PRINT "Enter end date (YYYY-MM-DD):"
INPUT endDate$

' Extract years from entered dates
year1 = VAL(LEFT$(startDate$, 4))
year2 = VAL(LEFT$(endDate$, 4))
yearsDifference = year2 - year1


trials = 100000 

FOR i = 1 TO trials
    randomDate$ = RandomDateBetweenDates$(startDate$, endDate$)
    IF VAL(LEFT$(randomDate$, 4)) - year1 = yearsDifference THEN
        countFullYears = countFullYears + 1
    END IF
NEXT i

' Calculate the probability and thus the number of full years
yearsBetween = INT((countFullYears / trials) * yearsDifference)

PRINT "The probably accurate number of full years between dates using Monte Carlo is: "; yearsBetween

FUNCTION RandomDateBetweenDates$ (startDate$, endDate$)
    DIM randomYear AS INTEGER, randomMonth AS INTEGER, randomDay AS INTEGER

    randomYear = VAL(LEFT$(startDate$, 4)) + INT(RND * (VAL(LEFT$(endDate$, 4)) - VAL(LEFT$(startDate$, 4))))
    randomMonth = INT(RND * 12) + 1
    randomDay = INT(RND * 28) + 1 ' Let's just assume every month has 28 days to make it simpler

    RandomDateBetweenDates$ = LTRIM$(STR$(randomYear)) + "-" + RIGHT$("0" + LTRIM$(STR$(randomMonth)), 2) + "-" + RIGHT$("0" + LTRIM$(STR$(randomDay)), 2)
END FUNCTION
dictator2000
()

Определить попадает ли день рождения в первый и последний год периода. Посчитать количество лет за исключением первого и последнего года, затем добавить 0, 1 или 2 к результату в зависимости от проверок.

KivApple ★★★★★
()
Ответ на: комментарий от KivApple

Если период в пределах одного года, такой алгоритм фигню возвращает. Либо отдельно описывать поведение, когда у нас разница дат меньше двух лет.

kravzo ★★
()
Последнее исправление: kravzo (всего исправлений: 1)
Ответ на: комментарий от Tanger

По идее, ТС должен был расписать, как считать 29 февраля. В википедии вобще написана какая-то дичь:

Немецкий профессор Хайнрих Хемме изобрёл «календарь» празднования дня рождения для тех, кто родился 29 февраля. По словам учёного, те, кто родился 29 февраля, могут справлять день рождения каждый год, но день празднования зависит от часа рождения. Те, кто родился в первые часы после полуночи, могут отмечать день рождения 28 февраля. Для тех, кто родился ближе к полуночи 1 марта, лучше отмечать день рождения 1 марта. Те, кто родился в первой половине дня (от 6 утра до 12 дня), первые два года справляют день рождения 28 февраля, а третий год — 1 марта. Для тех, кто родился во второй половине дня (от 12 дня до 6 вечера), график празднования следующий: первый год — 28 февраля, а последующие два — 1 марта.

Но, если исходить из простого алгоритма, что в високосный год ДР 29 февраля, а в обычный год ДР 1 марта (типа плохая примета поздравлять/отмечать заранее), то с 01.03.2022 до 28.02.2023 один ДР, 1 марта. А с 01.03.2020 до 28.02.2021 — ноль ДР.

mky ★★★★★
()
Ответ на: комментарий от mky

29 февраля?

$ 1..4 | % { (Get-Date 29.02.2024).AddYears($_) }

пятница, 28 февраля 2025 г. 00:00:00
суббота, 28 февраля 2026 г. 00:00:00
воскресенье, 28 февраля 2027 г. 00:00:00
вторник, 29 февраля 2028 г. 00:00:00
dmitry237 ★★★★
()
Ответ на: комментарий от dmitry237

Это формальный подход, который вытекает из правил исчисления процессуальных сроков:

при исчислении сроков месяцами текущий час и текущие сутки, в которые произошел юридический факт, не принимаются в расчет. То есть срок начинает исчисляться с нуля часов следующих суток, а истекает в соответствующее число последнего календарного месяца; если в этом месяце нет соответствующего числа (например, в сентябре — 31-го числа, а в феврале 29, 30, 31-го), то срок оканчивается в последние сутки месяца.

А люди могут отмечать ДР 1-го марта, если 29 февраля нет.

mky ★★★★★
()
Ответ на: комментарий от mky

Совершенно напрасно уделяете много времени - «резко отличающимся резулитатам». - Нас, аэрокосмическом университете - учили что их нужно просто откидывать.

Специально посмотрел список - Ни одного с 29 февраля нет.

kompospec
() автор топика
Ответ на: комментарий от kompospec

Тебе не ко мне, а на сайт www.python.org. У меня к Python другие отношения: PyGtk. Там графика. На этом сайте много руководств, правда не нашем языке. Установи на смартфон к примеру приложение для обучения. Можно проводить сложные вычисления, к примеру интегралы, системы и прочее.

nicholas_ru
()
Последнее исправление: nicholas_ru (всего исправлений: 1)
Ответ на: комментарий от kompospec

А потом рождаются чудо-программы, в которые невозможно ввести исходные данные, например, римские цифры в серии паспорта, ведь граждан с паспортами СССР не существует.

Если хочется откидывать, то в стартовом посте нужно было написать, что 29 февраля заменяем на 1 марта или ещё что.

mky ★★★★★
()

Посчитать количество дней рождений за период. PHP

А входные данные-то как выглядят? Период с даты по дату и конкретная дата (дня рождения), для которой нужно посчитать количество вхождений в этом периоде?

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ответ на: комментарий от kompospec

у вас вообще странная задача, нестроение какое-то.

и про функции date и strtotime - не, не слышали? я конечно «давно не брал в руки шашек», но раньше это с их помощью джелалось.

mumpster ★★★★★
()
Ответ на: комментарий от mky

А потом рождаются чудо-программы, в которые невозможно ввести исходные данные, например, римские цифры в серии паспорта, ведь граждан с паспортами СССР не существует.

Работал как-то в техподдержке интернет-провайдера. Российского. Звонит монтажник с проблемой: у клиента внутренний украинский паспорт, не получается ввести серию в программу. Зная, что серия состоит из подмножества кириллицы, совпадающего с латиницей, наугад предложил: «Попробуй латиницу, Би-Эйч вместо Ве-Эн». Прокатило. Наверное, разработчики забыли об украинцах, но успели подумать об азиатах.

Vidrele ★★★
()
Ответ на: комментарий от mumpster

А КоАП тут причём, это ГК РФ Статья 192. Окончание срока, определенного периодом времени. Пункт 3:

3. Срок, исчисляемый месяцами, истекает в соответствующее число последнего месяца срока.

Срок, определенный в полмесяца, рассматривается как срок, исчисляемый днями, и считается равным пятнадцати дням.

Если окончание срока, исчисляемого месяцами, приходится на такой месяц, в котором нет соответствующего числа, то срок истекает в последний день этого месяца.

Про фильм не знаю. В средневековье 29 февраля юридически не существовало — в этот день не заключали сделки, возможно и в церковные книги этот день не заносили.

mky ★★★★★
()
Ответ на: комментарий от kompospec

Входной формат даты не имеет значения

Результат, видимо, тоже %)

Зайдём с другого конца. Тебе премии надо за пять-десять-двадцать лет разом выплатить или просто определить, есть ли у данного васи в текущем месяце день рождения?

А то смахивает на какую-то задачку с собеседования одинэсника, замаскированного под пхпшника, чтобы не было так стыдно.

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 2)
Ответ на: комментарий от anonymous_sapiens

Кому в 1991 было 45 лет ещё живы.

В 2020 году на территории Российской Федерации проживает около 350 тысяч человек, которые не осуществили замену паспорта гражданина СССР на паспорт гражданина РФ.

А программы, не понимающие «серия/номер» в формате СССР появились уже в нулевые, когда паспортов СССР было значительно больше.

mky ★★★★★
()
Ответ на: комментарий от Nervous

Это выплаты работнику за прошедший период времени. Работа - повременная. Может 2 раза на день. А может и ни разу. Работы записаны в Нодах работ. Дни рождения - в Ноде работника. Работники, кроме того, отдельно в Таксономии.

Зачем вам это? Это никак не нужно для задачи.

kompospec
() автор топика
Ответ на: комментарий от anonymous_sapiens

Вы из Белоруссии или Киргизии? В РФ истёк срок обмена. Бессрочный паспорт СССР (в котором есть фото в 45 лет) действует не ограничено. Правда иногда гражданам приходится идти в суд https://www.vladimir.kp.ru/daily/23840.4/225608/ , в законах разночтение, но с точки зрения верховного суда всё нормально.

«Решение Верховного Суда РФ от 16 мая 2007 г. N ГКПИ07-466»:

В силу ст. 10 указанного Федерального закона документом, удостоверяющим гражданство Российской Федерации, является паспорт гражданина Российской Федерации или иной основной документ, содержащий указание на гражданство лица. Виды основных документов, удостоверяющих личность гражданина Российской Федерации, определяются федеральным законом.

Согласно статье 42 указанного Федерального закона документы, выданные в соответствии с ранее действовавшим законодательством о гражданстве Российской Федерации, сохраняют юридическую силу, если они оформлены надлежащим образом, и считаются действительными на день вступления в силу настоящего Федерального закона.

Таким образом перечень иных основных документов, удостоверяющих гражданство федеральным законом не установлен. Вместе с тем Закон допускает наличие иных основных документов удостоверяющих личность гражданина РФ при условии, что они выданы в соответствии с ранее действовавшим законодательством о гражданстве Российской Федерации, сохраняют юридическую силу, оформлены надлежащим образом, и считаются действительными на 1 июля 2002 года.

В связи с чем паспорт гражданина СССР, отвечающий вышеуказанным требованиям Федерального закона, действителен до его замены на паспорт гражданина РФ или до решения вопроса о прекращении действия паспортов СССР федеральным законом.

ФЗ о пркращении действия паспортов не было.

mky ★★★★★
()
Ответ на: комментарий от Vidrele

Ну, если система однозначно запрещает кириллицу, то это ещё нормально, при поиске аналогично можно заменить на латиницу.

Я вот помню, что около 2000 года мне показывали какую-то БД (фокспрошный файл), видимо ворованую из ментовки, из тех, что продавались на пиратских CD. Там был вобще ужос, то-ли сотрудники не умели переключаться с кирилицы, то-ли вводили китайцы, но там местами латинские цифры вбиты похожемы кирилическими буквами, типа:
″III″ -> ″Ш″
″VII″ -> ″У11″ и т.д.
Таких записей было не много, 5-10%, но стало интересно, как по такому что-то искать. А может это специально делалалось...

mky ★★★★★
()
Ответ на: комментарий от kompospec

Входной формат даты не имеет значения для многих языков программирования. Для php - точно.

Ты точно понял вопрос? Спрашивали про аргументы: что именно принимает функция на входе.

gruy ★★★★★
()
Ответ на: комментарий от mky

Немецкий профессор Хайнрих Хемме

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

ugoday ★★★★★
()

Эвристика. Предположим, что список ДР постоянный, люди не умирают и не добавляются. Тогда, если промежуток составляет один год и больше – количество ДР равно количеству людей в списке умноженному на количество целых лет. Если количество лет целое – больше ничего не делаем. Если нецелое – находим количество ДР для целого (округляем вниз), а потом прибавляем ДР за оставшийся неполный год. Алгоритм подсчета в рамках одного года тоже можно оптимизировать. Как минимум, если знать самый ранний месяц и день, можно определить, есть ли хотя бы один ДР за указанный период.

hateWin ★☆
()
Ответ на: комментарий от mky

Про фильм не знаю.

Я сначала подумал что отсыл к «Тот самый Мюнхгаузен», но там про 32ое мая. И оказывается таки да - есть такой советский фильм «31ое июня». Надо будет посмотреть ;)

В средневековье 29 февраля юридически не существовало — в этот день не заключали сделки

Как интересно! Почитать можно где?

bugfixer ★★★★★
()
Ответ на: комментарий от bugfixer

Не знаю, есть ли отдельное большое исслеование. Везде гуглятся только короткие списки фактов, в русскоязычном инете:

Во многих европейских странах вплоть до XVIII века 29 февраля считалось как бы несуществующим днём, датой, не имеющей юридического статуса. Часто в этот день не заключались сделки, не производились выплаты, не давали в долг и т. п. — из-за того, что возникали сложности с формальной стороной вопроса и улаживанием дел в суде.

В англоязычном можно найти:

In British Common Law, February 29 used to have no legal standing. No official business could be begun or concluded on that day, no contracts signed, legislation passed or signed into law, etc. The day was “leapt over.” (Obviously, that is the origin of the term “Leap Year.”)

Каких либо конкретных законов старой Англии про 29 февраля не нагуглил. Но, думаю, что они есть в инете, просто для запросов с РФ гугл плохо выдаёт англоязычные результаты.

Но именно, потому что этого дня не существовала, в Ирландии, Шотландии, Англии была традиция, что в этот день женщина может делать предложение брака мужчине. С какого века непонятно, но парламент Шотландии выпустил закон в 1288 году. Потом это утащили в Италию и Францию.

Для меня, что VIII век, что 1288 год — средневековье, поэтому я так сформулировал, а не «до XVIII века».

mky ★★★★★
()