1a25f0a04SGreg Roach<?php 23976b470SGreg Roach 3a25f0a04SGreg Roach/** 4a25f0a04SGreg Roach * webtrees: online genealogy 5*d11be702SGreg Roach * Copyright (C) 2023 webtrees development team 6a25f0a04SGreg Roach * This program is free software: you can redistribute it and/or modify 7a25f0a04SGreg Roach * it under the terms of the GNU General Public License as published by 8a25f0a04SGreg Roach * the Free Software Foundation, either version 3 of the License, or 9a25f0a04SGreg Roach * (at your option) any later version. 10a25f0a04SGreg Roach * This program is distributed in the hope that it will be useful, 11a25f0a04SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 12a25f0a04SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13a25f0a04SGreg Roach * GNU General Public License for more details. 14a25f0a04SGreg 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/>. 16a25f0a04SGreg Roach */ 17fcfa147eSGreg Roach 18e7f56f2aSGreg Roachdeclare(strict_types=1); 19e7f56f2aSGreg Roach 2076692c8bSGreg Roachnamespace Fisharebest\Webtrees\Date; 21a25f0a04SGreg Roach 22a25f0a04SGreg Roachuse Fisharebest\ExtCalendar\FrenchCalendar; 230e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N; 244ba350e3SGreg Roachuse Fisharebest\Webtrees\Services\RomanNumeralsService; 25a25f0a04SGreg Roach 26a25f0a04SGreg Roach/** 274a83f5d7SGreg Roach * Definitions for French Republican dates. 28a25f0a04SGreg Roach */ 294a83f5d7SGreg Roachclass FrenchDate extends AbstractCalendarDate 30c1010edaSGreg Roach{ 314a83f5d7SGreg Roach // GEDCOM calendar escape 3216d6367aSGreg Roach public const ESCAPE = '@#DFRENCH R@'; 334a83f5d7SGreg Roach 3452348eb8SGreg Roach // Convert GEDCOM month names to month numbers 35d8809d62SGreg Roach protected const MONTH_TO_NUMBER = [ 36c1010edaSGreg Roach 'VEND' => 1, 37c1010edaSGreg Roach 'BRUM' => 2, 38c1010edaSGreg Roach 'FRIM' => 3, 39c1010edaSGreg Roach 'NIVO' => 4, 40c1010edaSGreg Roach 'PLUV' => 5, 41c1010edaSGreg Roach 'VENT' => 6, 42c1010edaSGreg Roach 'GERM' => 7, 43c1010edaSGreg Roach 'FLOR' => 8, 44c1010edaSGreg Roach 'PRAI' => 9, 45c1010edaSGreg Roach 'MESS' => 10, 46c1010edaSGreg Roach 'THER' => 11, 47c1010edaSGreg Roach 'FRUC' => 12, 48c1010edaSGreg Roach 'COMP' => 13, 49c1010edaSGreg Roach ]; 50a25f0a04SGreg Roach 51d8809d62SGreg Roach protected const NUMBER_TO_MONTH = [ 52d8809d62SGreg Roach 1 => 'VEND', 53d8809d62SGreg Roach 2 => 'BRUM', 54d8809d62SGreg Roach 3 => 'FRIM', 55d8809d62SGreg Roach 4 => 'NIVO', 56d8809d62SGreg Roach 5 => 'PLUV', 57d8809d62SGreg Roach 6 => 'VENT', 58d8809d62SGreg Roach 7 => 'GERM', 59d8809d62SGreg Roach 8 => 'FLOR', 60d8809d62SGreg Roach 9 => 'PRAI', 61d8809d62SGreg Roach 10 => 'MESS', 62d8809d62SGreg Roach 11 => 'THER', 63d8809d62SGreg Roach 12 => 'FRUC', 64d8809d62SGreg Roach 13 => 'COMP', 65d8809d62SGreg Roach ]; 66d8809d62SGreg Roach 6743f2f523SGreg Roach private RomanNumeralsService $roman_numerals_service; 684ba350e3SGreg Roach 6976692c8bSGreg Roach /** 7076692c8bSGreg Roach * Create a date from either: 7176692c8bSGreg Roach * a Julian day number 7276692c8bSGreg Roach * day/month/year strings from a GEDCOM date 7376692c8bSGreg Roach * another CalendarDate object 7476692c8bSGreg Roach * 75f4c767fdSGreg Roach * @param array<string>|int|AbstractCalendarDate $date 7676692c8bSGreg Roach */ 77c1010edaSGreg Roach public function __construct($date) 78c1010edaSGreg Roach { 794ba350e3SGreg Roach $this->roman_numerals_service = new RomanNumeralsService(); 8059f2f229SGreg Roach $this->calendar = new FrenchCalendar(); 814ba350e3SGreg Roach 82a25f0a04SGreg Roach parent::__construct($date); 83a25f0a04SGreg Roach } 84a25f0a04SGreg Roach 8576692c8bSGreg Roach /** 8676692c8bSGreg Roach * Full month name in nominative case. 8776692c8bSGreg Roach * 887bb2eb25SGreg Roach * @param int $month 8976692c8bSGreg Roach * @param bool $leap_year Some calendars use leap months 9076692c8bSGreg Roach * 9176692c8bSGreg Roach * @return string 9276692c8bSGreg Roach */ 937bb2eb25SGreg Roach protected function monthNameNominativeCase(int $month, bool $leap_year): string 94c1010edaSGreg Roach { 95a25f0a04SGreg Roach static $translated_month_names; 96a25f0a04SGreg Roach 97a25f0a04SGreg Roach if ($translated_month_names === null) { 9813abd6f3SGreg Roach $translated_month_names = [ 99a25f0a04SGreg Roach 0 => '', 100bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 101bbb76c12SGreg Roach 1 => I18N::translateContext('NOMINATIVE', 'Vendemiaire'), 102bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 103bbb76c12SGreg Roach 2 => I18N::translateContext('NOMINATIVE', 'Brumaire'), 104bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 105bbb76c12SGreg Roach 3 => I18N::translateContext('NOMINATIVE', 'Frimaire'), 106bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 107bbb76c12SGreg Roach 4 => I18N::translateContext('NOMINATIVE', 'Nivose'), 108bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 109bbb76c12SGreg Roach 5 => I18N::translateContext('NOMINATIVE', 'Pluviose'), 110bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 111bbb76c12SGreg Roach 6 => I18N::translateContext('NOMINATIVE', 'Ventose'), 112bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 113bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 114bbb76c12SGreg Roach 7 => I18N::translateContext('NOMINATIVE', 'Germinal'), 115bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 116bbb76c12SGreg Roach 8 => I18N::translateContext('NOMINATIVE', 'Floreal'), 117bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 118bbb76c12SGreg Roach 9 => I18N::translateContext('NOMINATIVE', 'Prairial'), 119bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 120bbb76c12SGreg Roach 10 => I18N::translateContext('NOMINATIVE', 'Messidor'), 121bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 122bbb76c12SGreg Roach 11 => I18N::translateContext('NOMINATIVE', 'Thermidor'), 123bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 124bbb76c12SGreg Roach 12 => I18N::translateContext('NOMINATIVE', 'Fructidor'), 125bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 126bbb76c12SGreg Roach 13 => I18N::translateContext('NOMINATIVE', 'jours complementaires'), 12713abd6f3SGreg Roach ]; 128a25f0a04SGreg Roach } 129a25f0a04SGreg Roach 1307bb2eb25SGreg Roach return $translated_month_names[$month]; 131a25f0a04SGreg Roach } 132a25f0a04SGreg Roach 13376692c8bSGreg Roach /** 13476692c8bSGreg Roach * Full month name in genitive case. 13576692c8bSGreg Roach * 1367bb2eb25SGreg Roach * @param int $month 13776692c8bSGreg Roach * @param bool $leap_year Some calendars use leap months 13876692c8bSGreg Roach * 13976692c8bSGreg Roach * @return string 14076692c8bSGreg Roach */ 1417bb2eb25SGreg Roach protected function monthNameGenitiveCase(int $month, bool $leap_year): string 142c1010edaSGreg Roach { 143a25f0a04SGreg Roach static $translated_month_names; 144a25f0a04SGreg Roach 145a25f0a04SGreg Roach if ($translated_month_names === null) { 14613abd6f3SGreg Roach $translated_month_names = [ 147a25f0a04SGreg Roach 0 => '', 148bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 149bbb76c12SGreg Roach 1 => I18N::translateContext('GENITIVE', 'Vendemiaire'), 150bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 151bbb76c12SGreg Roach 2 => I18N::translateContext('GENITIVE', 'Brumaire'), 152bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 153bbb76c12SGreg Roach 3 => I18N::translateContext('GENITIVE', 'Frimaire'), 154bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 155bbb76c12SGreg Roach 4 => I18N::translateContext('GENITIVE', 'Nivose'), 156bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 157bbb76c12SGreg Roach 5 => I18N::translateContext('GENITIVE', 'Pluviose'), 158bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 159bbb76c12SGreg Roach 6 => I18N::translateContext('GENITIVE', 'Ventose'), 160bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 161bbb76c12SGreg Roach 7 => I18N::translateContext('GENITIVE', 'Germinal'), 162bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 163bbb76c12SGreg Roach 8 => I18N::translateContext('GENITIVE', 'Floreal'), 164bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 165bbb76c12SGreg Roach 9 => I18N::translateContext('GENITIVE', 'Prairial'), 166bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 167bbb76c12SGreg Roach 10 => I18N::translateContext('GENITIVE', 'Messidor'), 168bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 169bbb76c12SGreg Roach 11 => I18N::translateContext('GENITIVE', 'Thermidor'), 170bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 171bbb76c12SGreg Roach 12 => I18N::translateContext('GENITIVE', 'Fructidor'), 172bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 173bbb76c12SGreg Roach 13 => I18N::translateContext('GENITIVE', 'jours complementaires'), 17413abd6f3SGreg Roach ]; 175a25f0a04SGreg Roach } 176a25f0a04SGreg Roach 1777bb2eb25SGreg Roach return $translated_month_names[$month]; 178a25f0a04SGreg Roach } 179a25f0a04SGreg Roach 18076692c8bSGreg Roach /** 18176692c8bSGreg Roach * Full month name in locative case. 18276692c8bSGreg Roach * 1837bb2eb25SGreg Roach * @param int $month 18476692c8bSGreg Roach * @param bool $leap_year Some calendars use leap months 18576692c8bSGreg Roach * 18676692c8bSGreg Roach * @return string 18776692c8bSGreg Roach */ 1887bb2eb25SGreg Roach protected function monthNameLocativeCase(int $month, bool $leap_year): string 189c1010edaSGreg Roach { 190a25f0a04SGreg Roach static $translated_month_names; 191a25f0a04SGreg Roach 192a25f0a04SGreg Roach if ($translated_month_names === null) { 19313abd6f3SGreg Roach $translated_month_names = [ 194a25f0a04SGreg Roach 0 => '', 195bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 196bbb76c12SGreg Roach 1 => I18N::translateContext('LOCATIVE', 'Vendemiaire'), 197bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 198bbb76c12SGreg Roach 2 => I18N::translateContext('LOCATIVE', 'Brumaire'), 199bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 200bbb76c12SGreg Roach 3 => I18N::translateContext('LOCATIVE', 'Frimaire'), 201bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 202bbb76c12SGreg Roach 4 => I18N::translateContext('LOCATIVE', 'Nivose'), 203bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 204bbb76c12SGreg Roach 5 => I18N::translateContext('LOCATIVE', 'Pluviose'), 205bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 206bbb76c12SGreg Roach 6 => I18N::translateContext('LOCATIVE', 'Ventose'), 207bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 208bbb76c12SGreg Roach 7 => I18N::translateContext('LOCATIVE', 'Germinal'), 209bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 210bbb76c12SGreg Roach 8 => I18N::translateContext('LOCATIVE', 'Floreal'), 211bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 212bbb76c12SGreg Roach 9 => I18N::translateContext('LOCATIVE', 'Prairial'), 213bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 214bbb76c12SGreg Roach 10 => I18N::translateContext('LOCATIVE', 'Messidor'), 215bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 216bbb76c12SGreg Roach 11 => I18N::translateContext('LOCATIVE', 'Thermidor'), 217bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 218bbb76c12SGreg Roach 12 => I18N::translateContext('LOCATIVE', 'Fructidor'), 219bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 220bbb76c12SGreg Roach 13 => I18N::translateContext('LOCATIVE', 'jours complementaires'), 22113abd6f3SGreg Roach ]; 222a25f0a04SGreg Roach } 223a25f0a04SGreg Roach 2247bb2eb25SGreg Roach return $translated_month_names[$month]; 225a25f0a04SGreg Roach } 226a25f0a04SGreg Roach 22776692c8bSGreg Roach /** 22876692c8bSGreg Roach * Full month name in instrumental case. 22976692c8bSGreg Roach * 2307bb2eb25SGreg Roach * @param int $month 23176692c8bSGreg Roach * @param bool $leap_year Some calendars use leap months 23276692c8bSGreg Roach * 23376692c8bSGreg Roach * @return string 23476692c8bSGreg Roach */ 2357bb2eb25SGreg Roach protected function monthNameInstrumentalCase(int $month, bool $leap_year): string 236c1010edaSGreg Roach { 237a25f0a04SGreg Roach static $translated_month_names; 238a25f0a04SGreg Roach 239a25f0a04SGreg Roach if ($translated_month_names === null) { 24013abd6f3SGreg Roach $translated_month_names = [ 241a25f0a04SGreg Roach 0 => '', 242bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 243bbb76c12SGreg Roach 1 => I18N::translateContext('INSTRUMENTAL', 'Vendemiaire'), 244bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 245bbb76c12SGreg Roach 2 => I18N::translateContext('INSTRUMENTAL', 'Brumaire'), 246bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 247bbb76c12SGreg Roach 3 => I18N::translateContext('INSTRUMENTAL', 'Frimaire'), 248bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 249bbb76c12SGreg Roach 4 => I18N::translateContext('INSTRUMENTAL', 'Nivose'), 250bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 251bbb76c12SGreg Roach 5 => I18N::translateContext('INSTRUMENTAL', 'Pluviose'), 252bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 253bbb76c12SGreg Roach 6 => I18N::translateContext('INSTRUMENTAL', 'Ventose'), 254bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 255bbb76c12SGreg Roach 7 => I18N::translateContext('INSTRUMENTAL', 'Germinal'), 256bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 257bbb76c12SGreg Roach 8 => I18N::translateContext('INSTRUMENTAL', 'Floreal'), 258bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 259bbb76c12SGreg Roach 9 => I18N::translateContext('INSTRUMENTAL', 'Prairial'), 260bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 261bbb76c12SGreg Roach 10 => I18N::translateContext('INSTRUMENTAL', 'Messidor'), 262bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 263bbb76c12SGreg Roach 11 => I18N::translateContext('INSTRUMENTAL', 'Thermidor'), 264bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 265bbb76c12SGreg Roach 12 => I18N::translateContext('INSTRUMENTAL', 'Fructidor'), 266bbb76c12SGreg Roach /* I18N: a month in the French republican calendar */ 267bbb76c12SGreg Roach 13 => I18N::translateContext('INSTRUMENTAL', 'jours complementaires'), 26813abd6f3SGreg Roach ]; 269a25f0a04SGreg Roach } 270a25f0a04SGreg Roach 2717bb2eb25SGreg Roach return $translated_month_names[$month]; 272a25f0a04SGreg Roach } 273a25f0a04SGreg Roach 27476692c8bSGreg Roach /** 27576692c8bSGreg Roach * Abbreviated month name 27676692c8bSGreg Roach * 2777bb2eb25SGreg Roach * @param int $month 27876692c8bSGreg Roach * @param bool $leap_year Some calendars use leap months 27976692c8bSGreg Roach * 28076692c8bSGreg Roach * @return string 28176692c8bSGreg Roach */ 2827bb2eb25SGreg Roach protected function monthNameAbbreviated(int $month, bool $leap_year): string 283c1010edaSGreg Roach { 2847bb2eb25SGreg Roach return $this->monthNameNominativeCase($month, $leap_year); 285a25f0a04SGreg Roach } 286a25f0a04SGreg Roach 28776692c8bSGreg Roach /** 28876692c8bSGreg Roach * Full day of the week 28976692c8bSGreg Roach * 29076692c8bSGreg Roach * @param int $day_number 29176692c8bSGreg Roach * 29276692c8bSGreg Roach * @return string 29376692c8bSGreg Roach */ 294fe11e66dSGreg Roach public function dayNames(int $day_number): string 295c1010edaSGreg Roach { 296a25f0a04SGreg Roach static $translated_day_names; 297a25f0a04SGreg Roach 298a25f0a04SGreg Roach if ($translated_day_names === null) { 29913abd6f3SGreg Roach $translated_day_names = [ 300bbb76c12SGreg Roach /* I18N: The first day in the French republican calendar */ 301bbb76c12SGreg Roach 0 => I18N::translate('Primidi'), 302bbb76c12SGreg Roach /* I18N: The second day in the French republican calendar */ 303bbb76c12SGreg Roach 1 => I18N::translate('Duodi'), 304bbb76c12SGreg Roach /* I18N: The third day in the French republican calendar */ 305bbb76c12SGreg Roach 2 => I18N::translate('Tridi'), 306bbb76c12SGreg Roach /* I18N: The fourth day in the French republican calendar */ 307bbb76c12SGreg Roach 3 => I18N::translate('Quartidi'), 308bbb76c12SGreg Roach /* I18N: The fifth day in the French republican calendar */ 309bbb76c12SGreg Roach 4 => I18N::translate('Quintidi'), 310bbb76c12SGreg Roach /* I18N: The sixth day in the French republican calendar */ 311bbb76c12SGreg Roach 5 => I18N::translate('Sextidi'), 312bbb76c12SGreg Roach /* I18N: The seventh day in the French republican calendar */ 313bbb76c12SGreg Roach 6 => I18N::translate('Septidi'), 314bbb76c12SGreg Roach /* I18N: The eighth day in the French republican calendar */ 315bbb76c12SGreg Roach 7 => I18N::translate('Octidi'), 316bbb76c12SGreg Roach /* I18N: The ninth day in the French republican calendar */ 317bbb76c12SGreg Roach 8 => I18N::translate('Nonidi'), 318bbb76c12SGreg Roach /* I18N: The tenth day in the French republican calendar */ 319bbb76c12SGreg Roach 9 => I18N::translate('Decidi'), 32013abd6f3SGreg Roach ]; 321a25f0a04SGreg Roach } 322a25f0a04SGreg Roach 323a25f0a04SGreg Roach return $translated_day_names[$day_number]; 324a25f0a04SGreg Roach } 325a25f0a04SGreg Roach 32676692c8bSGreg Roach /** 32776692c8bSGreg Roach * Abbreviated day of the week 32876692c8bSGreg Roach * 32976692c8bSGreg Roach * @param int $day_number 33076692c8bSGreg Roach * 33176692c8bSGreg Roach * @return string 33276692c8bSGreg Roach */ 333fe11e66dSGreg Roach protected function dayNamesAbbreviated(int $day_number): string 334c1010edaSGreg Roach { 33517920f94SGreg Roach return $this->dayNames($day_number); 336a25f0a04SGreg Roach } 337a25f0a04SGreg Roach 33876692c8bSGreg Roach /** 33976692c8bSGreg Roach * Generate the %Y format for a date. 34076692c8bSGreg Roach * 34176692c8bSGreg Roach * @return string 34276692c8bSGreg Roach */ 343fe11e66dSGreg Roach protected function formatLongYear(): string 344c1010edaSGreg Roach { 3454ff9827fSGreg Roach return 'An ' . $this->roman_numerals_service->numberToRomanNumerals($this->year); 346a25f0a04SGreg Roach } 347a25f0a04SGreg Roach} 348