Completed
Pull Request — master (#134)
by no
07:39 queued 01:13
created

YearMonthDayTimeParserTest::getParserClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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