15f58d1fdSGreg Roach<?php 23976b470SGreg Roach 35f58d1fdSGreg Roach/** 45f58d1fdSGreg Roach * webtrees: online genealogy 5*d11be702SGreg Roach * Copyright (C) 2023 webtrees development team 65f58d1fdSGreg Roach * This program is free software: you can redistribute it and/or modify 75f58d1fdSGreg Roach * it under the terms of the GNU General Public License as published by 85f58d1fdSGreg Roach * the Free Software Foundation, either version 3 of the License, or 95f58d1fdSGreg Roach * (at your option) any later version. 105f58d1fdSGreg Roach * This program is distributed in the hope that it will be useful, 115f58d1fdSGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 125f58d1fdSGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 135f58d1fdSGreg Roach * GNU General Public License for more details. 145f58d1fdSGreg Roach * You should have received a copy of the GNU General Public License 1589f7189bSGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>. 165f58d1fdSGreg Roach */ 17fcfa147eSGreg Roach 185f58d1fdSGreg Roachdeclare(strict_types=1); 195f58d1fdSGreg Roach 205f58d1fdSGreg Roachnamespace Fisharebest\Webtrees; 215f58d1fdSGreg Roach 22054771e9SGreg Roachuse function view; 235f58d1fdSGreg Roach 245f58d1fdSGreg Roach/** 250874af26SRichard Cissée * The difference between two GEDCOM dates. 265f58d1fdSGreg Roach */ 275f58d1fdSGreg Roachclass Age 285f58d1fdSGreg Roach{ 2943f2f523SGreg Roach private int $years; 305f58d1fdSGreg Roach 3143f2f523SGreg Roach private int $months; 325f58d1fdSGreg Roach 3343f2f523SGreg Roach private int $days; 345f58d1fdSGreg Roach 3543f2f523SGreg Roach private int $total_days; 365f58d1fdSGreg Roach 3743f2f523SGreg Roach private bool $is_exact; 38054771e9SGreg Roach 3943f2f523SGreg Roach private bool $is_valid; 405f58d1fdSGreg Roach 415f58d1fdSGreg Roach /** 425f58d1fdSGreg Roach * Age constructor. 435f58d1fdSGreg Roach * 44054771e9SGreg Roach * @param Date $x - The first date 45054771e9SGreg Roach * @param Date $y - The second date 465f58d1fdSGreg Roach */ 47054771e9SGreg Roach public function __construct(Date $x, Date $y) 485f58d1fdSGreg Roach { 49054771e9SGreg Roach // If the dates are ranges, use the start/end calendar dates. 50054771e9SGreg Roach $start = $x->minimumDate(); 51054771e9SGreg Roach $end = $y->maximumDate(); 525f58d1fdSGreg Roach 53054771e9SGreg Roach [$this->years, $this->months, $this->days] = $start->ageDifference($end); 545f58d1fdSGreg Roach 55054771e9SGreg Roach $this->total_days = $end->minimumJulianDay() - $start->minimumJulianDay(); 56054771e9SGreg Roach 57054771e9SGreg Roach // Use the same precision as found in the dates. 58054771e9SGreg Roach if ($start->day() === 0 || $end->day() === 0) { 59054771e9SGreg Roach $this->days = 0; 605f58d1fdSGreg Roach } 615f58d1fdSGreg Roach 62054771e9SGreg Roach if ($start->month() === 0 || $end->month() === 0) { 63054771e9SGreg Roach $this->months = 0; 645f58d1fdSGreg Roach } 655f58d1fdSGreg Roach 66054771e9SGreg Roach // Are the dates exact? 67054771e9SGreg Roach $this->is_exact = $start->day() !== 0 && $end->day() !== 0; 68054771e9SGreg Roach 69054771e9SGreg Roach // Are the dates valid? 70054771e9SGreg Roach $this->is_valid = $x->isOK() && $y->isOK(); 715f58d1fdSGreg Roach } 725f58d1fdSGreg Roach 735f58d1fdSGreg Roach /** 74054771e9SGreg Roach * Show an age in a human-friendly form, such as "34 years", "8 months", "20 days". 75054771e9SGreg Roach * Show an empty string for invalid/missing dates. 76054771e9SGreg Roach * Show a warning icon for negative ages. 77054771e9SGreg Roach * Show zero ages without any units. 78054771e9SGreg Roach * 79054771e9SGreg Roach * @return string 80a5fd6d7cSGreg Roach */ 81a5fd6d7cSGreg Roach public function __toString(): string 82a5fd6d7cSGreg Roach { 83054771e9SGreg Roach if (!$this->is_valid) { 84054771e9SGreg Roach return ''; 855f58d1fdSGreg Roach } 865f58d1fdSGreg Roach 87054771e9SGreg Roach if ($this->years < 0) { 88054771e9SGreg Roach return view('icons/warning'); 895f58d1fdSGreg Roach } 905f58d1fdSGreg Roach 91054771e9SGreg Roach if ($this->years > 0) { 92054771e9SGreg Roach return I18N::plural('%s year', '%s years', $this->years, I18N::number($this->years)); 935f58d1fdSGreg Roach } 945f58d1fdSGreg Roach 955f58d1fdSGreg Roach if ($this->months > 0) { 96054771e9SGreg Roach return I18N::plural('%s month', '%s months', $this->months, I18N::number($this->months)); 975f58d1fdSGreg Roach } 985f58d1fdSGreg Roach 99054771e9SGreg Roach if ($this->days > 0 || $this->is_exact) { 100054771e9SGreg Roach return I18N::plural('%s day', '%s days', $this->days, I18N::number($this->days)); 1015f58d1fdSGreg Roach } 1025f58d1fdSGreg Roach 103054771e9SGreg Roach return I18N::number(0); 1045f58d1fdSGreg Roach } 105783c6f8dSGreg Roach 106783c6f8dSGreg Roach /** 107054771e9SGreg Roach * How many days between two events? 108054771e9SGreg Roach * If either date is invalid return -1. 109783c6f8dSGreg Roach * 110783c6f8dSGreg Roach * @return int 111783c6f8dSGreg Roach */ 112054771e9SGreg Roach public function ageDays(): int 113783c6f8dSGreg Roach { 114054771e9SGreg Roach if ($this->is_valid) { 115054771e9SGreg Roach return $this->total_days; 116783c6f8dSGreg Roach } 117783c6f8dSGreg Roach 118054771e9SGreg Roach return -1; 119054771e9SGreg Roach } 120054771e9SGreg Roach 121054771e9SGreg Roach /** 122054771e9SGreg Roach * How many years between two events? 12353432476SGreg Roach * Return -1 for invalid or reversed dates. 124054771e9SGreg Roach * 125054771e9SGreg Roach * @return int 126054771e9SGreg Roach */ 127054771e9SGreg Roach public function ageYears(): int 128054771e9SGreg Roach { 129054771e9SGreg Roach if ($this->is_valid) { 130054771e9SGreg Roach return $this->years; 131054771e9SGreg Roach } 132054771e9SGreg Roach 133054771e9SGreg Roach return -1; 134054771e9SGreg Roach } 135054771e9SGreg Roach 136054771e9SGreg Roach /** 13753432476SGreg Roach * How many years between two events? 13853432476SGreg Roach * If either date is invalid return -1. 13953432476SGreg Roach * 14053432476SGreg Roach * @return string 14153432476SGreg Roach */ 14253432476SGreg Roach public function ageYearsString(): string 14353432476SGreg Roach { 14453432476SGreg Roach if (!$this->is_valid) { 14553432476SGreg Roach return ''; 14653432476SGreg Roach } 14753432476SGreg Roach 14853432476SGreg Roach if ($this->years < 0) { 14953432476SGreg Roach return view('icons/warning'); 15053432476SGreg Roach } 15153432476SGreg Roach 15253432476SGreg Roach 15353432476SGreg Roach return I18N::number($this->years); 15453432476SGreg Roach } 1555f58d1fdSGreg Roach} 156