Created
June 24, 2025 11:19
-
-
Save Chemaclass/65f68f2383202f528b7a550ee7478092 to your computer and use it in GitHub Desktop.
Visualizes a life calendar in the terminal. Each line is a year, each character is 2 days. Tracks progress and supports leap years.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env php | |
| <?php | |
| declare(strict_types=1); | |
| /** | |
| * Life Calendar Visualizer | |
| * | |
| * This script prints a visual timeline of a person's life in years and "day pairs", | |
| * where each line represents a year, and each character represents 2 days. | |
| * It uses `X` for days already lived and `_` for days yet to come. | |
| * | |
| * Usage: | |
| * ./life-passes.php <birth-date> [max-years] | |
| * | |
| * Examples: | |
| * ./life-passes.php 1993-06-15 | |
| * ./life-passes.php 15-06-1993 90 | |
| * ./life-passes.php 1993 100 | |
| * | |
| * Supports birth date formats: YYYY-MM-DD, DD-MM-YYYY, or YYYY | |
| * Supports leap years and provides life stats at the end. | |
| */ | |
| // ------------------------------------------------------------ | |
| // Helpers | |
| // ------------------------------------------------------------ | |
| /** | |
| * Parses a birthdate string into a DateTime object. | |
| */ | |
| function parseBirthDate(string $input): DateTime | |
| { | |
| $formats = ['Y-m-d', 'd-m-Y', 'Y']; | |
| foreach ($formats as $format) { | |
| $d = DateTime::createFromFormat($format, $input); | |
| if ($d && $d->format($format) === $input) { | |
| return $d; | |
| } | |
| } | |
| fwrite(STDERR, "β Invalid date format. Use YYYY-MM-DD, DD-MM-YYYY, or YYYY.\n"); | |
| exit(1); | |
| } | |
| /** | |
| * Parses optional max-years argument. | |
| */ | |
| function parseMaxYears(?string $input, int $default = 80): int | |
| { | |
| if ($input === null) { | |
| return $default; | |
| } | |
| if (!ctype_digit($input) || (int)$input <= 0) { | |
| fwrite(STDERR, "β Invalid max years. Must be a positive integer.\n"); | |
| exit(1); | |
| } | |
| return (int)$input; | |
| } | |
| /** | |
| * Checks if a given year is a leap year. | |
| */ | |
| function isLeapYear(int $year): bool | |
| { | |
| return ($year % 4 === 0 && $year % 100 !== 0) || ($year % 400 === 0); | |
| } | |
| // ------------------------------------------------------------ | |
| // Core Logic | |
| // ------------------------------------------------------------ | |
| /** | |
| * Prints the visual matrix and life stats. | |
| */ | |
| function printLifeMatrix(DateTime $birthDate, int $maxYears): void | |
| { | |
| $today = new DateTime(); | |
| $birthYear = (int)$birthDate->format('Y'); | |
| $startOfLife = new DateTime("{$birthYear}-01-01"); | |
| $totalExpectedDays = 0; | |
| $realDaysLived = (int)$birthDate->diff($today)->days; | |
| echo PHP_EOL; | |
| for ($y = 0; $y < $maxYears; ++$y) { | |
| $year = $birthYear + $y; | |
| $lineIndex = str_pad((string)$y, 2, ' ', STR_PAD_LEFT); | |
| $line = "{$year}({$lineIndex}): "; | |
| $daysInYear = isLeapYear($year) ? 366 : 365; | |
| $charsInLine = (int)floor($daysInYear / 2); | |
| for ($c = 0; $c < $charsInLine; ++$c) { | |
| $dayOffset = $c * 2; | |
| $day = (new DateTime("{$year}-01-01"))->modify("+{$dayOffset} days"); | |
| $char = ($day < $birthDate) ? '_' | |
| : (($day <= $today) ? 'X' : '_'); | |
| $line .= $char; | |
| } | |
| $totalExpectedDays += $daysInYear; | |
| echo $line . PHP_EOL; | |
| } | |
| echo PHP_EOL; | |
| echo "π Life Summary\n"; | |
| echo "---------------------------\n"; | |
| echo "π Days lived: {$realDaysLived}\n"; | |
| echo "π Days expected: {$totalExpectedDays}\n"; | |
| printf("π Life progress: %.2f%%\n", min(100, ($realDaysLived / $totalExpectedDays) * 100)); | |
| } | |
| // ------------------------------------------------------------ | |
| // Entry Point | |
| // ------------------------------------------------------------ | |
| if ($argc < 2) { | |
| fwrite(STDERR, "Usage: ./life-passes.php <birth-date> [max-years]\n"); | |
| exit(1); | |
| } | |
| $birthDate = parseBirthDate($argv[1]); | |
| $maxYears = parseMaxYears($argv[2] ?? null); | |
| printLifeMatrix($birthDate, $maxYears); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment