Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Unlocalize months in YearMonthDayTimeParser #93

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 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 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 = [] ) {
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