YearTimeParser::stringParse()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 21
ccs 12
cts 12
cp 1
rs 9.584
c 0
b 0
f 0
cc 3
nc 4
nop 1
crap 3
1
<?php
2
3
namespace ValueParsers;
4
5
use DataValues\TimeValue;
6
7
/**
8
 * A straight parser that accepts various strings representing a year, and only a year. Accepts
9
 * years before common era as well as optional thousands separators. Should be called after
10
 * YearMonthTimeParser when you want to accept both formats, because strings like "1 999" may either
11
 * represent a month and a year or a year with digit grouping.
12
 *
13
 * @since 0.8.4
14
 *
15
 * @license GPL-2.0+
16
 * @author Addshore
17
 * @author Thiemo Kreuz
18
 */
19
class YearTimeParser extends StringValueParser {
20
21
	const FORMAT_NAME = 'year';
22
23
	/**
24
	 * Option to allow parsing of years with localized digit group separators. For example, the
25
	 * English year -10,000 (with a comma) is written as -10.000 (with a dot) in German.
26
	 */
27
	const OPT_DIGIT_GROUP_SEPARATOR = 'digitGroupSeparator';
28
29
	/**
30
	 * Default, canonical digit group separator, as in the year -10,000.
31
	 */
32
	const CANONICAL_DIGIT_GROUP_SEPARATOR = ',';
33
34
	/**
35
	 * @var ValueParser
36
	 */
37
	private $eraParser;
38
39
	/**
40
	 * @var ValueParser
41
	 */
42
	private $isoTimestampParser;
43
44
	/**
45
	 * @see StringValueParser::__construct
46
	 *
47
	 * @param ValueParser|null $eraParser
48
	 * @param ParserOptions|null $options
49
	 */
50 40
	public function __construct( ValueParser $eraParser = null, ParserOptions $options = null ) {
51 40
		parent::__construct( $options );
52
53 40
		$this->defaultOption(
54 40
			self::OPT_DIGIT_GROUP_SEPARATOR,
55 40
			self::CANONICAL_DIGIT_GROUP_SEPARATOR
56
		);
57
58 40
		$this->eraParser = $eraParser ?: new EraParser( $this->options );
59 40
		$this->isoTimestampParser = new IsoTimestampParser( null, $this->options );
60 40
	}
61
62
	/**
63
	 * @see StringValueParser::stringParse
64
	 *
65
	 * @param string $value
66
	 *
67
	 * @throws ParseException
68
	 * @return TimeValue
69
	 */
70 33
	protected function stringParse( $value ) {
71 33
		list( $sign, $year ) = $this->eraParser->parse( $value );
72 33
		$year = trim( $year );
73
74
		// Negative dates usually don't have a month, assume non-digits are thousands separators
75 33
		if ( $sign === '-' ) {
76 11
			$separator = $this->getOption( self::OPT_DIGIT_GROUP_SEPARATOR );
77
			// Always accept ISO (e.g. "1 000 BC") as well as programming style (e.g. "-1_000")
78 11
			$year = preg_replace(
79 11
				'/(?<=\d)[' . preg_quote( $separator, '/' ) . '\s_](?=\d)/',
80 11
				'',
81 11
				$year
82
			);
83
		}
84
85 33
		if ( !preg_match( '/^\d+\z/', $year ) ) {
86 18
			throw new ParseException( 'Failed to parse year', $value, self::FORMAT_NAME );
87
		}
88
89 15
		return $this->isoTimestampParser->parse( $sign . $year . '-00-00T00:00:00Z' );
90
	}
91
92
}
93