Completed
Push — precisionOption ( 604f81 )
by no
02:21
created

YearMonthDayTimeParserTest::testInvalidOptions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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