|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
declare(strict_types=1); |
|
4
|
|
|
|
|
5
|
|
|
namespace Application\Service; |
|
6
|
|
|
|
|
7
|
|
|
use Application\Model\Dating; |
|
8
|
|
|
use Cake\Chronos\Chronos; |
|
9
|
|
|
|
|
10
|
|
|
class DatingRule |
|
11
|
|
|
{ |
|
12
|
|
|
private array $replace = [ |
|
13
|
|
|
'/zwischen[[:space:]]*([[:digit:]\.]+)[[:space:]]*(und|-)/' => '$1 - ', |
|
14
|
|
|
'/[[:space:]]*\(.*\)[[:space:]]*/' => '', |
|
15
|
|
|
'/(around|ca\.?|~|begonnen|ab|vor|nach)/' => '', |
|
16
|
|
|
'/(jahrhunderts?|jhd?t?s?\.?)/' => 'jh', |
|
17
|
|
|
'/(v\.|vor)[[:space:]]*(christus|chr?\.?)/' => 'vor chr', |
|
18
|
|
|
'/(n\.|nach)[[:space:]]*chr\.?/' => '', |
|
19
|
|
|
'/(\/|bis)/' => '-', |
|
20
|
|
|
'/[[:space:]]+/' => ' ', |
|
21
|
|
|
'/erstes/' => '1', |
|
22
|
|
|
'/fr(ä|ue|u)hes/' => 'anfang', |
|
23
|
|
|
'/sp(ä|ae|a)tes/' => 'ende', |
|
24
|
|
|
'/(gegen|vollendet)/' => 'vor', |
|
25
|
|
|
'/letztes[[:space:]]*viertel/' => '4. viertel', |
|
26
|
|
|
'/letztes[[:space:]]*drittel/' => '3. drittel', |
|
27
|
|
|
'/(u\.|und|bzw\.?|oder)/' => ';', |
|
28
|
|
|
]; |
|
29
|
|
|
|
|
30
|
|
|
/** |
|
31
|
|
|
* @return Dating[] |
|
32
|
|
|
*/ |
|
33
|
50 |
|
public function compute(string $input): array |
|
34
|
|
|
{ |
|
35
|
50 |
|
$romanReplaced = $this->replaceRoman($input); |
|
36
|
50 |
|
$replaced = mb_trim(preg_replace(array_keys($this->replace), array_values($this->replace), mb_strtolower($romanReplaced))); |
|
37
|
50 |
|
$dates = explode(';', $replaced); |
|
38
|
50 |
|
$result = []; |
|
39
|
50 |
|
foreach ($dates as $date) { |
|
40
|
50 |
|
foreach ($this->getMatches() as $pattern => $callbacks) { |
|
41
|
50 |
|
$match = []; |
|
42
|
50 |
|
if (preg_match($pattern, $date, $match)) { |
|
43
|
40 |
|
$dating = new Dating(); |
|
44
|
40 |
|
$dating->setFrom($callbacks['from']($match)); |
|
45
|
40 |
|
$dating->setTo($callbacks['to']($match)); |
|
46
|
40 |
|
$result[] = $dating; |
|
47
|
|
|
|
|
48
|
40 |
|
break; |
|
49
|
|
|
} |
|
50
|
|
|
} |
|
51
|
|
|
} |
|
52
|
|
|
|
|
53
|
50 |
|
return $result; |
|
54
|
|
|
} |
|
55
|
|
|
|
|
56
|
|
|
/** |
|
57
|
|
|
* Replace roman number into numeric. |
|
58
|
|
|
* |
|
59
|
|
|
* This use hardcoded Roman numbers as seen in old Dilps |
|
60
|
|
|
*/ |
|
61
|
50 |
|
private function replaceRoman(string $input): string |
|
62
|
|
|
{ |
|
63
|
50 |
|
$romain = ['XXI', 'XX', 'XIX', 'XVIII', 'XVII', 'XVI', 'XV', 'XIV', 'XIII', 'XII', 'XI', 'X', 'IX', 'VIII', 'VII', 'VI', 'V', 'IV', 'III', 'II', 'I']; |
|
64
|
50 |
|
$numeric = ['2001-2100', '1901-2000', '1801-1900', '1701-1800', '1601-1700', '1501-1600', '1401-1500', '1301-1400', '1201-1300', '1101-1200', '1001-1100', '901-1000', '801-900', '701-800', '601-700', '501-600', '401-500', '301-400', '201-300', '101-200', '1-100']; |
|
65
|
|
|
|
|
66
|
50 |
|
$numeric = array_map(fn ($a) => ';' . $a . ';', $numeric); |
|
67
|
|
|
|
|
68
|
50 |
|
return str_replace($romain, $numeric, $input); |
|
69
|
|
|
} |
|
70
|
|
|
|
|
71
|
|
|
/** |
|
72
|
|
|
* Create a DateTime but force year 1 instead of year 0. |
|
73
|
|
|
*/ |
|
74
|
40 |
|
private static function toDateTime(int $year, int $month, int $day): Chronos |
|
75
|
|
|
{ |
|
76
|
40 |
|
if ($year === 0) { |
|
77
|
1 |
|
$year = 1; |
|
78
|
|
|
} |
|
79
|
|
|
|
|
80
|
40 |
|
$date = new Chronos(); |
|
81
|
|
|
|
|
82
|
40 |
|
return $date->setDate($year, $month, $day); |
|
83
|
|
|
} |
|
84
|
|
|
|
|
85
|
50 |
|
private function getMatches(): array |
|
86
|
|
|
{ |
|
87
|
50 |
|
return [ |
|
88
|
|
|
// 64 == 1.1.1964 - 31.12.1964 |
|
89
|
50 |
|
'/^[[:space:]]*(\d{2})[[:space:]]*$/' => [ |
|
90
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime((int) ('19' . $match[1]), 1, 1), |
|
91
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime((int) ('19' . $match[1]), 12, 31), |
|
92
|
50 |
|
], |
|
93
|
|
|
// 1875-1877 == 1.1.1875 - 31.12.1877 |
|
94
|
|
|
// 1875-77 == 1.1.1875 - 31.12.1877 |
|
95
|
|
|
// 1875/77 == 1.1.1875 - 31.12.1877 |
|
96
|
50 |
|
'/^[[:space:]]*(um|nach|vor)?[[:space:]]*(\d{3,4})[[:space:]]*-[[:space:]]*(\d{1,4})[[:space:]]*$/' => [ |
|
97
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime((int) $match[2], 1, 1), |
|
98
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime((int) (mb_substr($match[2], 0, max(0, mb_strlen($match[2]) - mb_strlen($match[3]))) . $match[3]), 12, 31), |
|
99
|
50 |
|
], |
|
100
|
|
|
// 1875 v. Chr. == 1.1.-1875 - 31.12.-1875 |
|
101
|
50 |
|
'/^[[:space:]]*(\d{3,4})[[:space:]]*vor[[:space:]]chr.?[[:space:]]*$/' => [ |
|
102
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime(-(int) $match[1], 1, 1), |
|
103
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime(-(int) $match[1], 12, 31), |
|
104
|
50 |
|
], |
|
105
|
|
|
// 1875 n. Chr. == 1.1.1875 - 31.12.1875 |
|
106
|
|
|
// 1875 == 1.1.1875 - 31.12.1875 |
|
107
|
50 |
|
'/^[[:space:]]*(\d{3,4})[[:space:]]*$/' => [ |
|
108
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime((int) $match[1], 1, 1), |
|
109
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime((int) $match[1], 12, 31), |
|
110
|
50 |
|
], |
|
111
|
|
|
// 1876-1872 v. Chr. == 1.1.-1876 - 31.12.-1872 |
|
112
|
50 |
|
'/^[[:space:]]*(um)?[[:space:]]*(\d+)[[:space:]]*-[[:space:]]*(\d+)[[:space:]]*vor[[:space:]]chr.?[[:space:]]*$/' => [ |
|
113
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime(-max((int) $match[2], (int) ($match[3])), 1, 1), |
|
114
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime(-min((int) $match[2], (int) ($match[3])), 12, 31), |
|
115
|
50 |
|
], |
|
116
|
|
|
// um 1875 v. Chr. == 1.1.-1875 - 31.12.-1875 |
|
117
|
50 |
|
'/^[[:space:]]*um[[:space:]]*(\d+)[[:space:]]*vor[[:space:]]chr.?[[:space:]]*(\(.*\))?[[:space:]]*$/' => [ |
|
118
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime(-(int) $match[1], 1, 1), |
|
119
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime(-(int) $match[1], 12, 31), |
|
120
|
50 |
|
], |
|
121
|
|
|
// 23.10.2003 == 23.10.2003 - 23.10.2003 |
|
122
|
50 |
|
'/^[[:space:]]*(\d{2}).(\d{2}).(\d{4})[[:space:]]*$/' => [ |
|
123
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime((int) $match[3], (int) $match[2], (int) ($match[1])), |
|
124
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime((int) $match[3], (int) $match[2], (int) ($match[1])), |
|
125
|
50 |
|
], |
|
126
|
|
|
// spätantike == 1.1.275 - 31.12.525 |
|
127
|
50 |
|
'/^[[:space:]]*spät[[:space:]]*antike[[:space:]]*$/' => [ |
|
128
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime(275, 1, 1), |
|
|
|
|
|
|
129
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime(525, 12, 31), |
|
|
|
|
|
|
130
|
50 |
|
], |
|
131
|
|
|
// Shang-Dynastie == 16 - 11 Jh. v. Chr |
|
132
|
50 |
|
'/^[[:space:]]*shang[[:space:]-]*dynastie[[:space:]]*$/' => [ |
|
133
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime(-1625, 1, 1), |
|
|
|
|
|
|
134
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime(-975, 12, 31), |
|
|
|
|
|
|
135
|
50 |
|
], |
|
136
|
|
|
// antike == 1.1.-825 - 31.12.525 |
|
137
|
50 |
|
'/^[[:space:]]*antike[[:space:]]*$/' => [ |
|
138
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime(-825, 1, 1), |
|
|
|
|
|
|
139
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime(525, 12, 31), |
|
|
|
|
|
|
140
|
50 |
|
], |
|
141
|
|
|
// 6. Jhdt. == 1.1.500 - 31.12.599 |
|
142
|
|
|
// 6. Jhdt. n Chr. == 1.1.500 - 31.12.599 |
|
143
|
|
|
// 6 Jh. n. Chr. == 1.1.500 - 31.12.599 |
|
144
|
50 |
|
'/^[[:space:]]*(\d{1,2})[.]?[[:space:]]*jh[[:space:]]*$/' => [ |
|
145
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime((int) (($match[1] - 1) . '00'), 1, 1), |
|
146
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime((int) (($match[1] - 1) . '99'), 12, 31), |
|
147
|
50 |
|
], |
|
148
|
|
|
// um 1874 == 1873 - 1875 |
|
149
|
50 |
|
'/^[[:space:]]*um[[:space:]]*(\d{3,4})[[:space:]]*$/' => [ |
|
150
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime((int) ($match[1]) - 1, 1, 1), |
|
151
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime((int) ($match[1]) + 1, 12, 31), |
|
152
|
50 |
|
], |
|
153
|
|
|
// Anfang 6. Jhdt. == 1.1.500 - 31.12.525 |
|
154
|
50 |
|
'/^[[:space:]]*anf(ang)?.?([[:space:]]*des)?[[:space:]]*(\d{1,2})[.]?[[:space:]]*jh[[:space:]]*$/' => [ |
|
155
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime((int) (((int) ($match[3]) - 1) . '00'), 1, 1), |
|
156
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime((int) (((int) ($match[3]) - 1) . '25'), 12, 31), |
|
157
|
50 |
|
], |
|
158
|
|
|
// 6. Jhdt. v. Chr. == 1.1.-501 - 31.12.-600 |
|
159
|
50 |
|
'/^[[:space:]]*(\d{1,2})[.]?[[:space:]]*jh[[:space:]]*vor[[:space:]]*chr.?[[:space:]]*$/' => [ |
|
160
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime(-(int) (($match[1] - 1) . '01'), 1, 1), |
|
161
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime(-(int) ($match[1] . '00'), 12, 31), |
|
162
|
50 |
|
], |
|
163
|
|
|
// 6. Jhdt. n. Chr. == 1.1.500 - 31.12.599 |
|
164
|
50 |
|
'/^[[:space:]]*(um|nach|vor)?[[:space:]]*(\d{1,2}).?[[:space:]]*-[[:space:]]*(\d{1,2}).?[[:space:]]*jh[[:space:]]*$/' => [ |
|
165
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime((int) (($match[2] - 1) . '00'), 1, 1), |
|
166
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime((int) (((int) ($match[3]) - 1) . '99'), 12, 31), |
|
167
|
50 |
|
], |
|
168
|
|
|
// Ende 6. Jhdt. == 1.1.575 - 31.12.599 |
|
169
|
50 |
|
'/^[[:space:]]*ende([[:space:]]*des)?[[:space:]]*(\d{1,2})[.]?[[:space:]]*jh[[:space:]]*$/' => [ |
|
170
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime((int) (($match[2] - 1) . '75'), 1, 1), |
|
171
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime((int) (($match[2] - 1) . '99'), 12, 31), |
|
172
|
50 |
|
], |
|
173
|
|
|
// mitte 6. Jhdt. == 1.1.533 - 31.12.566 |
|
174
|
50 |
|
'/^[[:space:]]*mitte[[:space:]]*(des[[:space:]]*)?(\d{1,2})[.]?[[:space:]]*jh[[:space:]]*$/' => [ |
|
175
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime((int) (($match[2] - 1) . '33'), 1, 1), |
|
176
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime((int) (($match[2] - 1) . '66'), 12, 31), |
|
177
|
50 |
|
], |
|
178
|
|
|
// mitte 6. Jhdt. v. chr == -0666-01-01 - -0633-12-31 |
|
179
|
50 |
|
'/^[[:space:]]*mitte[[:space:]]*(des[[:space:]]*)?(\d{1,2})[.]?[[:space:]]*jh[[:space:]]*vor[[:space:]]chr.?[[:space:]]*$/' => [ |
|
180
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime(-(int) ($match[2] . '00') - 66, 1, 1), |
|
181
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime(-(int) ($match[2] . '00') - 33, 12, 31), |
|
182
|
50 |
|
], |
|
183
|
|
|
// um 6. Jhdt. == 1.1.480 - 31.12.620 |
|
184
|
50 |
|
'/^[[:space:]]*um[[:space:]]*(\d{1,2})[.]?[[:space:]]*jh[[:space:]]*$/' => [ |
|
185
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime((int) (($match[1] - 1) . '00') - 20, 1, 1), |
|
186
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime((int) (($match[1] - 1) . '00') + 120, 12, 31), |
|
187
|
50 |
|
], |
|
188
|
|
|
// 2. - 1. Jh. v. Chr. == -0200-01-01 - -0001-12-31 |
|
189
|
50 |
|
'/^[[:space:]]*(um|nach|vor)?[[:space:]]*(\d{1,2}).?[[:space:]]*-[[:space:]]*(\d{1,2}).?[[:space:]]*jh[[:space:]]*vor[[:space:]]*chr.?[[:space:]]*(\(.*\))?[[:space:]]*$/' => [ |
|
190
|
50 |
|
'from' => fn (array $match): Chronos => self::toDateTime(-(int) ((max((int) $match[2], (int) ($match[3]))) . '00'), 1, 1), |
|
191
|
50 |
|
'to' => fn (array $match): Chronos => self::toDateTime(-(int) ((min((int) $match[2], (int) ($match[3])) - 1) . '01'), 12, 31), |
|
192
|
50 |
|
], |
|
193
|
|
|
|
|
194
|
50 |
|
]; |
|
195
|
|
|
} |
|
196
|
|
|
} |
|
197
|
|
|
|
This check looks for parameters that have been defined for a function or method, but which are not used in the method body.