xref: /webtrees/app/Date/JulianDate.php (revision e7f56f2af615447ab1a7646851f88b465ace9e04)
1<?php
2/**
3 * webtrees: online genealogy
4 * Copyright (C) 2018 webtrees development team
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16declare(strict_types=1);
17
18namespace Fisharebest\Webtrees\Date;
19
20use Fisharebest\ExtCalendar\JulianCalendar;
21use Fisharebest\Webtrees\I18N;
22
23/**
24 * Definitions for the Julian Proleptic calendar
25 * (Proleptic means we extend it backwards, prior to its introduction in 46BC)
26 */
27class JulianDate extends CalendarDate
28{
29    /** @var bool True for dates recorded in new-style/old-style format, e.g. 2 FEB 1743/44 */
30    private $new_old_style = false;
31
32    /**
33     * Create a date from either:
34     * a Julian day number
35     * day/month/year strings from a GEDCOM date
36     * another CalendarDate object
37     *
38     * @param array|int|CalendarDate $date
39     */
40    public function __construct($date)
41    {
42        $this->calendar = new JulianCalendar();
43        parent::__construct($date);
44    }
45
46    /**
47     * Most years are 1 more than the previous, but not always (e.g. 1BC->1AD)
48     *
49     * @param int $year
50     *
51     * @return int
52     */
53    protected function nextYear(int $year): int
54    {
55        if ($year == -1) {
56            return 1;
57        }
58
59        return $year + 1;
60    }
61
62    /**
63     * Process new-style/old-style years and years BC
64     *
65     * @param string $year
66     *
67     * @return int
68     */
69    protected function extractYear(string $year): int
70    {
71        if (preg_match('/^(\d\d\d\d)\/\d{1,4}$/', $year, $match)) {
72            // Assume the first year is correct
73            $this->new_old_style = true;
74
75            return (int) $match[1] + 1;
76        }
77
78        if (preg_match('/^(\d+) B\.C\.$/', $year, $match)) {
79            return - (int) $match[1];
80        }
81
82        return (int) $year;
83    }
84
85    /**
86     * Generate the %Y format for a date.
87     *
88     * @return string
89     */
90    protected function formatLongYear(): string
91    {
92        if ($this->y < 0) {
93            return /*  I18N: BCE=Before the Common Era, for Julian years < 0. See http://en.wikipedia.org/wiki/Common_Era */
94                I18N::translate('%s&nbsp;BCE', I18N::digits(-$this->y));
95        }
96
97        if ($this->new_old_style) {
98            return I18N::translate('%s&nbsp;CE', I18N::digits(sprintf('%d/%02d', $this->y - 1, $this->y % 100)));
99        }
100
101        /* I18N: CE=Common Era, for Julian years > 0. See http://en.wikipedia.org/wiki/Common_Era */
102        return I18N::translate('%s&nbsp;CE', I18N::digits($this->y));
103    }
104
105    /**
106     * Generate the %E format for a date.
107     *
108     * @return string
109     */
110    protected function formatGedcomYear(): string
111    {
112        if ($this->y < 0) {
113            return sprintf('%04d B.C.', -$this->y);
114        }
115
116        if ($this->new_old_style) {
117            return sprintf('%04d/%02d', $this->y - 1, $this->y % 100);
118        }
119
120        return sprintf('%04d', $this->y);
121    }
122}
123