Passed
Push — master ( 7af698...31dd3f )
by Jeroen De
01:04 queued 34s
created

YearMonthDayTimeParserTest::getParserClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace ValueParsers\Test;
4
5
use DataValues\TimeValue;
6
use ValueParsers\IsoTimestampParser;
7
use ValueParsers\ParseException;
8
use ValueParsers\ParserOptions;
9
use ValueParsers\YearMonthDayTimeParser;
10
11
/**
12
 * @covers ValueParsers\YearMonthDayTimeParser
13
 *
14
 * @group DataValue
15
 * @group DataValueExtensions
16
 * @group TimeParsers
17
 * @group ValueParsers
18
 *
19
 * @license GPL-2.0+
20
 * @author Thiemo Kreuz
21
 */
22
class YearMonthDayTimeParserTest extends StringValueParserTest {
23
24
	/**
25
	 * @see ValueParserTestBase::getInstance
26
	 *
27
	 * @return YearMonthDayTimeParser
28
	 */
29
	protected function getInstance() {
30
		return new YearMonthDayTimeParser();
31
	}
32
33
	/**
34
	 * @see ValueParserTestBase::validInputProvider
35
	 */
36
	public function validInputProvider() {
37
		$gregorian = 'http://www.wikidata.org/entity/Q1985727';
38
		$julian = 'http://www.wikidata.org/entity/Q1985786';
39
40
		$valid = array(
41
			// Whitespace
42
			"2016-01-01\n" => array( '+2016-01-01T00:00:00Z' ),
43
			' 2016-01-01 ' => array( '+2016-01-01T00:00:00Z' ),
44
45
			// YMD, typically used in ISO 8601
46
			'2015-12-31' => array( '+2015-12-31T00:00:00Z' ),
47
			'2015 12 31' => array( '+2015-12-31T00:00:00Z' ),
48
			'2015 1 13' => array( '+2015-01-13T00:00:00Z' ),
49
50
			// DMY
51
			'31.12.2015' => array( '+2015-12-31T00:00:00Z' ),
52
			'31. 12. 2015' => array( '+2015-12-31T00:00:00Z' ),
53
			'31/12/2015' => array( '+2015-12-31T00:00:00Z' ),
54
			'31 12 2015' => array( '+2015-12-31T00:00:00Z' ),
55
			'31th 12th 2015' => array( '+2015-12-31T00:00:00Z' ),
56
			'day 31, month 12, year 2015' => array( '+2015-12-31T00:00:00Z' ),
57
58
			// MDY, almost exclusively used in the United States
59
			'12/31/2015' => array( '+2015-12-31T00:00:00Z' ),
60
			'12-31-2015' => array( '+2015-12-31T00:00:00Z' ),
61
			'12 31 2015' => array( '+2015-12-31T00:00:00Z' ),
62
63
			// YDM, exclusively used in Kazakhstan
64
			// https://en.wikipedia.org/wiki/Calendar_date#Gregorian.2C_year-day-month_.28YDM.29
65
			'2015.31.12' => array( '+2015-12-31T00:00:00Z' ),
66
			'2015 13 1' => array( '+2015-01-13T00:00:00Z' ),
67
68
			// Month and day are the same, does not matter if DMY or MDY
69
			'01 1 2015' => array( '+2015-01-01T00:00:00Z' ),
70
			'12 12 2015' => array( '+2015-12-12T00:00:00Z' ),
71
72
			// Month and day are the same, does not matter if YMD or YDM
73
			'2015 01 1' => array( '+2015-01-01T00:00:00Z' ),
74
			'2015 12 12' => array( '+2015-12-12T00:00:00Z' ),
75
76
			// Julian
77
			'32-12-31' => array( '+0032-12-31T00:00:00Z', $julian ),
78
			'31.12.32' => array( '+0032-12-31T00:00:00Z', $julian ),
79
			'12/31/60' => array( '+0060-12-31T00:00:00Z', $julian ),
80
81
			// Negative years
82
			'-2015-12-31' => array( '-2015-12-31T00:00:00Z', $julian ),
83
			'year -2015-12-31' => array( '-2015-12-31T00:00:00Z', $julian ),
84
			'31 12 -2015' => array( '-2015-12-31T00:00:00Z', $julian ),
85
			'12/31/-2015' => array( '-2015-12-31T00:00:00Z', $julian ),
86
			'2015-12-31 BC' => array( '-2015-12-31T00:00:00Z', $julian ),
87
			'31 12 2015 BC' => array( '-2015-12-31T00:00:00Z', $julian ),
88
			'12/31/2015 BC' => array( '-2015-12-31T00:00:00Z', $julian ),
89
90
			// A negative number must be the year.
91
			'year -3-2-13' => array( '-0003-02-13T00:00:00Z', $julian ),
92
			'13. 2. -3' => array( '-0003-02-13T00:00:00Z', $julian ),
93
			'23:12:-59' => array( '-0059-12-23T00:00:00Z', $julian ),
94
		);
95
96
		$cases = array();
97
98
		foreach ( $valid as $value => $args ) {
99
			$timestamp = $args[0];
100
			$calendarModel = isset( $args[1] ) ? $args[1] : $gregorian;
101
102
			$cases[] = array(
103
				// Because PHP magically turns numeric keys into ints/floats
104
				(string)$value,
105
				new TimeValue( $timestamp, 0, 0, 0, TimeValue::PRECISION_DAY, $calendarModel )
106
			);
107
		}
108
109
		return $cases;
110
	}
111
112
	/**
113
	 * @see StringValueParserTest::invalidInputProvider
114
	 */
115
	public function invalidInputProvider() {
116
		$invalid = array(
117
			// This parser can only parse strings that contain exactly three numbers.
118
			'2015',
119
			'12.2015',
120
			'May 1 2015',
121
			'1. May 2015',
122
			'1 2015-12-31',
123
			'31.12.2015 23',
124
			'31.12.2015 23:59',
125
			'+2015-12-31T00:00:00Z',
126
127
			// Can be confused with a time (HMS)
128
			'12:31:59',
129
			'12:59:59',
130
			'23:12:59',
131
			'23:12:31',
132
			'-23:12:31',
133
			'-24:00:00',
134
135
			// No year can be identified if all numbers are smaller than 32.
136
			'12 12 12',
137
			'31 12 12',
138
			'12 31 12',
139
			'31 31 12',
140
			'12 12 31',
141
			'31 12 31',
142
			'12 31 31',
143
			'31 31 31',
144
145
			// Two or more candidates for the year.
146
			'32 32 12',
147
			'32 12 32',
148
			'12 32 32',
149
			'32 32 32',
150
151
			// Year can be identified, but month and day can not be distinguished.
152
			'32 2 1',
153
			'2015-12-11',
154
			'1 2 32',
155
			'11.12.2015',
156
157
			// Formats DYM and MYD do not exist and should not be parsed.
158
			'12 -1 12',
159
			'12 32 12',
160
			'12 2015 31',
161
			'31 2015 12',
162
163
			// Duplicate era.
164
			'year -2015-12-31 BC',
165
			'31.12.-2015 BC',
166
167
			// Zeros.
168
			'-2015-00-00',
169
			'0000-00-00',
170
			'2015-00-00',
171
			'2015-12-00',
172
			'0. 0. -2015',
173
			'0. 0. 0',
174
			'0. 0. 2015',
175
			'0. 12. 2015',
176
177
			// To long.
178
			'2015-12-031',
179
			'2015-012-31',
180
		);
181
182
		$cases = parent::invalidInputProvider();
183
184
		foreach ( $invalid as $value ) {
185
			$cases[] = array( $value );
186
		}
187
188
		return $cases;
189
	}
190
191
	/**
192
	 * @dataProvider optionsProvider
193
	 */
194
	public function testOptions(
195
		$value,
196
		array $options,
197
		$timestamp,
198
		$calendarModel,
199
		$precision = TimeValue::PRECISION_DAY
200
	) {
201
		$parser = new YearMonthDayTimeParser( null, new ParserOptions( $options ) );
202
		$this->assertEquals(
203
			new TimeValue( $timestamp, 0, 0, 0, $precision, $calendarModel ),
204
			$parser->parse( $value )
205
		);
206
	}
207
208
	public function optionsProvider() {
209
		$gregorian = 'http://www.wikidata.org/entity/Q1985727';
210
		$julian = 'http://www.wikidata.org/entity/Q1985786';
211
212
		return array(
213
			'Auto-detected Gregorian' => array(
214
				'1583-01-31',
215
				array(),
216
				'+1583-01-31T00:00:00Z',
217
				$gregorian
218
			),
219
			'Option overrides auto-detected Gregorian' => array(
220
				'1583-01-31',
221
				array( IsoTimestampParser::OPT_CALENDAR => $julian ),
222
				'+1583-01-31T00:00:00Z',
223
				$julian
224
			),
225
			'Auto-detected Julian' => array(
226
				'1582-01-31',
227
				array(),
228
				'+1582-01-31T00:00:00Z',
229
				$julian
230
			),
231
			'Option overrides auto-detected Julian' => array(
232
				'1582-01-31',
233
				array( IsoTimestampParser::OPT_CALENDAR => $gregorian ),
234
				'+1582-01-31T00:00:00Z',
235
				$gregorian
236
			),
237
			'Option can decrease precision' => array(
238
				'2016-01-31',
239
				array( IsoTimestampParser::OPT_PRECISION => TimeValue::PRECISION_MONTH ),
240
				'+2016-01-31T00:00:00Z',
241
				$gregorian,
242
				TimeValue::PRECISION_MONTH
243
			),
244
			'Option can set minimal precision' => array(
245
				'2016-01-31',
246
				array( IsoTimestampParser::OPT_PRECISION => TimeValue::PRECISION_YEAR1G ),
247
				'+2016-01-31T00:00:00Z',
248
				$gregorian,
249
				TimeValue::PRECISION_YEAR1G
250
			),
251
			'Option can increase day precision' => array(
252
				'2016-01-31',
253
				array( IsoTimestampParser::OPT_PRECISION => TimeValue::PRECISION_HOUR ),
254
				'+2016-01-31T00:00:00Z',
255
				$gregorian,
256
				TimeValue::PRECISION_HOUR
257
			),
258
			'Precision option accepts strings' => array(
259
				'2016-01-31',
260
				array( IsoTimestampParser::OPT_PRECISION => '10' ),
261
				'+2016-01-31T00:00:00Z',
262
				$gregorian,
263
				TimeValue::PRECISION_MONTH
264
			),
265
		);
266
	}
267
268
	/**
269
	 * @dataProvider invalidOptionsProvider
270
	 */
271
	public function testInvalidOptions( array $options ) {
272
		$parser = new YearMonthDayTimeParser( null, new ParserOptions( $options ) );
273
		$this->setExpectedException( ParseException::class );
274
		$parser->parse( '2016-01-31' );
275
	}
276
277
	public function invalidOptionsProvider() {
278
		return array(
279
			array( array( IsoTimestampParser::OPT_PRECISION => -1 ) ),
280
			array( array( IsoTimestampParser::OPT_PRECISION => 1.5 ) ),
281
			array( array( IsoTimestampParser::OPT_PRECISION => 1000 ) ),
282
			array( array( IsoTimestampParser::OPT_PRECISION => 'invalid' ) ),
283
		);
284
	}
285
286
}
287