xref: /webtrees/app/Date/JulianDate.php (revision 24931b29a0237a5f5f1b8620af661ea530451af0)
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&nbsp;BCE', I18N::digits(-$this->year));
99b2ce94c6SRico Sonntag        }
100b2ce94c6SRico Sonntag
101a25f0a04SGreg Roach        if ($this->new_old_style) {
1024a83f5d7SGreg Roach            return I18N::translate('%s&nbsp;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&nbsp;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