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\JulianCalendar; 230e62c4b8SGreg Roachuse Fisharebest\Webtrees\I18N; 24a25f0a04SGreg Roach 25a25f0a04SGreg Roach/** 264a83f5d7SGreg Roach * Definitions for proleptic Julian dates. 27a25f0a04SGreg Roach */ 284a83f5d7SGreg Roachclass JulianDate extends AbstractGregorianJulianDate 29c1010edaSGreg Roach{ 304a83f5d7SGreg Roach // GEDCOM calendar escape 3116d6367aSGreg Roach public const ESCAPE = '@#DJULIAN@'; 324a83f5d7SGreg Roach 3333c746f1SGreg Roach // For dates recorded in new-style/old-style format, e.g. 2 FEB 1743/44 3433c746f1SGreg Roach private bool $new_old_style = false; 35a25f0a04SGreg Roach 3676692c8bSGreg Roach /** 3776692c8bSGreg Roach * Create a date from either: 3876692c8bSGreg Roach * a Julian day number 3976692c8bSGreg Roach * day/month/year strings from a GEDCOM date 4076692c8bSGreg Roach * another CalendarDate object 4176692c8bSGreg Roach * 42f4c767fdSGreg Roach * @param array<string>|int|AbstractCalendarDate $date 4376692c8bSGreg Roach */ 44c1010edaSGreg Roach public function __construct($date) 45c1010edaSGreg Roach { 4659f2f229SGreg Roach $this->calendar = new JulianCalendar(); 47a25f0a04SGreg Roach parent::__construct($date); 48a25f0a04SGreg Roach } 49a25f0a04SGreg Roach 5076692c8bSGreg Roach /** 5176692c8bSGreg Roach * Most years are 1 more than the previous, but not always (e.g. 1BC->1AD) 5276692c8bSGreg Roach * 5376692c8bSGreg Roach * @param int $year 5476692c8bSGreg Roach * 5576692c8bSGreg Roach * @return int 5676692c8bSGreg Roach */ 57fe11e66dSGreg Roach protected function nextYear(int $year): int 58c1010edaSGreg Roach { 59e364afe4SGreg Roach if ($year === -1) { 60a25f0a04SGreg Roach return 1; 61a25f0a04SGreg Roach } 62b2ce94c6SRico Sonntag 63b2ce94c6SRico Sonntag return $year + 1; 64a25f0a04SGreg Roach } 65a25f0a04SGreg Roach 66a25f0a04SGreg Roach /** 67a25f0a04SGreg Roach * Process new-style/old-style years and years BC 68a25f0a04SGreg Roach * 6976692c8bSGreg Roach * @param string $year 7076692c8bSGreg Roach * 7176692c8bSGreg Roach * @return int 72a25f0a04SGreg Roach */ 73fe11e66dSGreg Roach protected function extractYear(string $year): int 74c1010edaSGreg Roach { 75a25f0a04SGreg Roach if (preg_match('/^(\d\d\d\d)\/\d{1,4}$/', $year, $match)) { 76a25f0a04SGreg Roach // Assume the first year is correct 77a25f0a04SGreg Roach $this->new_old_style = true; 78a25f0a04SGreg Roach 79db7bb364SGreg Roach return (int) $match[1] + 1; 80a25f0a04SGreg Roach } 81a0cead57SGreg Roach 82a0cead57SGreg Roach if (preg_match('/^(\d+) B\.C\.$/', $year, $match)) { 83a0cead57SGreg Roach return -(int) $match[1]; 84a0cead57SGreg Roach } 85a0cead57SGreg Roach 86a0cead57SGreg Roach return (int) $year; 87a25f0a04SGreg Roach } 88a25f0a04SGreg Roach 8976692c8bSGreg Roach /** 9076692c8bSGreg Roach * Generate the %Y format for a date. 9176692c8bSGreg Roach * 9276692c8bSGreg Roach * @return string 9376692c8bSGreg Roach */ 94fe11e66dSGreg Roach protected function formatLongYear(): string 95c1010edaSGreg Roach { 964a83f5d7SGreg Roach if ($this->year < 0) { 97ad3143ccSGreg Roach return /* I18N: BCE=Before the Common Era, for Julian years < 0. See https://en.wikipedia.org/wiki/Common_Era */ 984a83f5d7SGreg Roach I18N::translate('%s BCE', I18N::digits(-$this->year)); 99b2ce94c6SRico Sonntag } 100b2ce94c6SRico Sonntag 101a25f0a04SGreg Roach if ($this->new_old_style) { 1024a83f5d7SGreg Roach return I18N::translate('%s CE', I18N::digits(sprintf('%d/%02d', $this->year - 1, $this->year % 100))); 103b2ce94c6SRico Sonntag } 104b2ce94c6SRico Sonntag 105ad3143ccSGreg Roach /* I18N: CE=Common Era, for Julian years > 0. See https://en.wikipedia.org/wiki/Common_Era */ 1064a83f5d7SGreg Roach return I18N::translate('%s CE', I18N::digits($this->year)); 107a25f0a04SGreg Roach } 108a25f0a04SGreg Roach 10976692c8bSGreg Roach /** 11076692c8bSGreg Roach * Generate the %E format for a date. 11176692c8bSGreg Roach * 11276692c8bSGreg Roach * @return string 11376692c8bSGreg Roach */ 114fe11e66dSGreg Roach protected function formatGedcomYear(): string 115c1010edaSGreg Roach { 1164a83f5d7SGreg Roach if ($this->year < 0) { 1174a83f5d7SGreg Roach return sprintf('%04d B.C.', -$this->year); 118b2ce94c6SRico Sonntag } 119b2ce94c6SRico Sonntag 120a25f0a04SGreg Roach if ($this->new_old_style) { 1214a83f5d7SGreg Roach return sprintf('%04d/%02d', $this->year - 1, $this->year % 100); 122b2ce94c6SRico Sonntag } 123b2ce94c6SRico Sonntag 1244a83f5d7SGreg Roach return sprintf('%04d', $this->year); 125a25f0a04SGreg Roach } 126a25f0a04SGreg Roach} 127