xref: /webtrees/app/Date/JulianDate.php (revision 20ac4041ff6d2c96733f4df91b821d1c039e0259)
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 */
16namespace Fisharebest\Webtrees\Date;
17
18use Fisharebest\ExtCalendar\JulianCalendar;
19use Fisharebest\Webtrees\I18N;
20
21/**
22 * Definitions for the Julian Proleptic calendar
23 * (Proleptic means we extend it backwards, prior to its introduction in 46BC)
24 */
25class JulianDate extends CalendarDate
26{
27    /** @var bool True for dates recorded in new-style/old-style format, e.g. 2 FEB 1743/44 */
28    private $new_old_style = false;
29
30    /**
31     * Create a date from either:
32     * a Julian day number
33     * day/month/year strings from a GEDCOM date
34     * another CalendarDate object
35     *
36     * @param array|int|CalendarDate $date
37     */
38    public function __construct($date)
39    {
40        $this->calendar = new JulianCalendar();
41        parent::__construct($date);
42    }
43
44    /**
45     * Most years are 1 more than the previous, but not always (e.g. 1BC->1AD)
46     *
47     * @param int $year
48     *
49     * @return int
50     */
51    protected function nextYear(int $year): int
52    {
53        if ($year == -1) {
54            return 1;
55        } else {
56            return $year + 1;
57        }
58    }
59
60    /**
61     * Process new-style/old-style years and years BC
62     *
63     * @param string $year
64     *
65     * @return int
66     */
67    protected function extractYear(string $year): int
68    {
69        if (preg_match('/^(\d\d\d\d)\/\d{1,4}$/', $year, $match)) {
70            // Assume the first year is correct
71            $this->new_old_style = true;
72
73            return $match[1] + 1;
74        } elseif (preg_match('/^(\d+) B\.C\.$/', $year, $match)) {
75            return -$match[1];
76        } else {
77            return (int) $year;
78        }
79    }
80
81    /**
82     * Generate the %Y format for a date.
83     *
84     * @return string
85     */
86    protected function formatLongYear(): string
87    {
88        if ($this->y < 0) {
89            return /*  I18N: BCE=Before the Common Era, for Julian years < 0. See http://en.wikipedia.org/wiki/Common_Era */
90                I18N::translate('%s&nbsp;BCE', I18N::digits(-$this->y));
91        } else {
92            if ($this->new_old_style) {
93                return I18N::translate('%s&nbsp;CE', I18N::digits(sprintf('%d/%02d', $this->y - 1, $this->y % 100)));
94            } else {
95                /* I18N: CE=Common Era, for Julian years > 0. See http://en.wikipedia.org/wiki/Common_Era */
96                return I18N::translate('%s&nbsp;CE', I18N::digits($this->y));
97            }
98        }
99    }
100
101    /**
102     * Generate the %E format for a date.
103     *
104     * @return string
105     */
106    protected function formatGedcomYear(): string
107    {
108        if ($this->y < 0) {
109            return sprintf('%04d B.C.', -$this->y);
110        } else {
111            if ($this->new_old_style) {
112                return sprintf('%04d/%02d', $this->y - 1, $this->y % 100);
113            } else {
114                return sprintf('%04d', $this->y);
115            }
116        }
117    }
118}
119