Skip to content

Commit

Permalink
Unlocalize months in YearMonthDayTimeParser
Browse files Browse the repository at this point in the history
  • Loading branch information
thiemowmde committed Feb 21, 2018
1 parent e923a93 commit 7ee93b7
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 6 deletions.
36 changes: 33 additions & 3 deletions src/ValueParsers/YearMonthDayTimeParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ class YearMonthDayTimeParser extends StringValueParser {
*/
private $eraParser;

/**
* @var int[]
*/
private $months;

/**
* @var ValueParser
*/
Expand All @@ -30,12 +35,19 @@ class YearMonthDayTimeParser extends StringValueParser {
/**
* @param ValueParser|null $eraParser String parser that detects signs, "BC" suffixes and such and
* returns an array with the detected sign character and the remaining value.
* @param int[] $months Array mapping localized month names (possibly including full month
* names, genitive names and abbreviations) to the numbers 1 to 12.
* @param ParserOptions|null $options
*/
public function __construct( ValueParser $eraParser = null, ParserOptions $options = null ) {
public function __construct(
ValueParser $eraParser = null,
array $months = [],
ParserOptions $options = null
) {
parent::__construct( $options );

$this->eraParser = $eraParser ?: new EraParser();
$this->months = $months;
$this->isoTimestampParser = new IsoTimestampParser( null, $this->options );
}

Expand Down Expand Up @@ -69,10 +81,28 @@ protected function stringParse( $value ) {
* @return string[]
*/
private function parseYearMonthDay( $value ) {
if ( !preg_match( '/^\D*?(-?\d+)\D+(\d+)\D+?(-?\d+)\D*$/', $value, $matches ) ) {
$monthPattern = '(?:\d+|'
. implode( '|', array_map( 'preg_quote', array_keys( $this->months ) ) )
. ')';
if ( !preg_match(
'<^\D*?(-?' . $monthPattern . ')\D+(' . $monthPattern . ')\D+?(-?' . $monthPattern . ')\D*$>',
$value,
$matches
) ) {
throw new ParseException( 'Can not find three numbers' );
}

$monthAt = null;
foreach ( $matches as $i => &$match ) {
if ( isset( $this->months[$match] ) ) {
if ( $monthAt !== null ) {
throw new ParseException( 'Two months found' );
}
$match = $this->months[$match];
$monthAt = $i;
}
}

// A 32 in the first spot can not be confused with anything.
if ( $matches[1] < 1 || $matches[1] > 31 ) {
if ( $matches[3] > 12 || $matches[2] == $matches[3] ) {
Expand All @@ -99,7 +129,7 @@ private function parseYearMonthDay( $value ) {
throw new ParseException( 'Can not identify year' );
}

return array( $signedYear, $month, $day );
return [ $signedYear, $month, $day ];
}

/**
Expand Down
71 changes: 68 additions & 3 deletions tests/ValueParsers/YearMonthDayTimeParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,16 @@ protected function getParserClass() {
* @return YearMonthDayTimeParser
*/
protected function getInstance() {
return new YearMonthDayTimeParser();
return $this->getYearMonthDayTimeParser();
}

/**
* @param int[] $months
*
* @return YearMonthDayTimeParser
*/
private function getYearMonthDayTimeParser( array $months = array() ) {
return new YearMonthDayTimeParser( null, $months );
}

/**
Expand Down Expand Up @@ -195,6 +204,62 @@ public function invalidInputProvider() {
return $cases;
}

/**
* @dataProvider monthNamesProvider
*/
public function testMonthNameParsing( $value, array $months, TimeValue $expected ) {
$parser = $this->getYearMonthDayTimeParser( $months );
$this->assertTrue( $expected->equals( $parser->parse( $value ) ) );
}

public function monthNamesProvider() {
$gregorian = 'http://www.wikidata.org/entity/Q1985727';

$valid = [
'13.12.1999' => [
[],
'+1999-12-13T00:00:00Z',
],
'13. February 1999' => [
[ 'February' => 2 ],
'+1999-02-13T00:00:00Z',
],
];

$cases = [];

foreach ( $valid as $value => $args ) {
$months = $args[0];
$timestamp = $args[1];
$calendarModel = isset( $args[2] ) ? $args[2] : $gregorian;

$cases[] = [
(string)$value,
$months,
new TimeValue( $timestamp, 0, 0, 0, TimeValue::PRECISION_DAY, $calendarModel )
];
}

return $cases;
}

/**
* @dataProvider invalidMonthNamesProvider
*/
public function testInvalidMonthNameParsing( $value, array $months ) {
$parser = $this->getYearMonthDayTimeParser( $months );
$this->setExpectedException( 'ValueParsers\ParseException' );
$parser->parse( $value );
}

public function invalidMonthNamesProvider() {
return [
[ '13. February 1999', [] ],
[ 'February. February 1999', [ 'February' => 2 ] ],
[ '13. Feb 1999', [ 'February' => 2 ] ],
];
}

/**
* @dataProvider optionsProvider
*/
Expand All @@ -205,7 +270,7 @@ public function testOptions(
$calendarModel,
$precision = TimeValue::PRECISION_DAY
) {
$parser = new YearMonthDayTimeParser( null, new ParserOptions( $options ) );
$parser = new YearMonthDayTimeParser( null, [], new ParserOptions( $options ) );
$this->assertEquals(
new TimeValue( $timestamp, 0, 0, 0, $precision, $calendarModel ),
$parser->parse( $value )
Expand Down Expand Up @@ -276,7 +341,7 @@ public function optionsProvider() {
* @dataProvider invalidOptionsProvider
*/
public function testInvalidOptions( array $options ) {
$parser = new YearMonthDayTimeParser( null, new ParserOptions( $options ) );
$parser = new YearMonthDayTimeParser( null, [], new ParserOptions( $options ) );
$this->setExpectedException( ParseException::class );
$parser->parse( '2016-01-31' );
}
Expand Down

0 comments on commit 7ee93b7

Please sign in to comment.