<?php

function getAstroSign(DateTime $inputDateTime) {
    $astroSignToStartDate = [
        // Знак зодиака, начало (номер дня)
        ['Водолей', 21],
        ['Рыбы', 20],
        ['Овен', 21],
        ['Телец', 21],
        ['Близнецы', 22],
        ['Рак', 22],
        ['Лев', 23],
        ['Дева', 22],
        ['Весы', 24],
        ['Скорпион', 24],
        ['Стрелец', 23],
        ['Козерог', 23],
    ];
 
    // Порядковый номер месяца без ведущего нуля
    $month = (int) $inputDateTime->format('n');
    // Номер дня месяца без ведущего нуля
    $day = (int) $inputDateTime->format('j');

    // Минус 1 так как индексация в массиве начинается с нуля
    list($astro, $startDate) = $astroSignToStartDate[$month - 1];
    if ($day < $startDate) {
        // PHP не поддерживает негативные индексы для массивов, поэтому приходится извращаться
        $index = ($month === 1) ? 11 : $month - 2;
        return $astroSignToStartDate[$index][0];
    } else {
        return $astro;
    }
}


$testcases = [
	['1999-01-01', 'Козерог'],
	['1999-01-20', 'Козерог'],
	['1999-01-21', 'Водолей'],
	['1999-01-22', 'Водолей'],
	['1999-11-11', 'Скорпион'],
	['1999-06-25', 'Рак'],
	['1999-06-22', 'Рак'],
	['1999-12-23', 'Козерог'],
    ['1999-12-25', 'Козерог'],
	['1999-12-31', 'Козерог'],
];
 
foreach ($testcases as list($input, $expected)) {
    var_dump("Дата рождения {$input} ожидается: {$expected}, дано: " . getAstroSign(new DateTime($input)));
}
