Skip to content

Commit fc07b93

Browse files
committed
Construct parsers with a copy of ParserOptions
MwDateFormatParserFactory::getMwDateFormatParser modifies the provided ParserOptions instance (lines 60-62 there). Both calls receive the same instance, so the options for the first call are overwritten with the second call. Passing a shallow copy avoids this. An alternative would be to go through all parsers and make sure they create a copy before they modify the object. Unfortunately, some tests start to fail, mostly due to wrong default calendar model for ancient dates. Instead of determining it ourselves here, we use IsoTimestampParser to decide the correct one. Bug: T221097 Bug: T324392 Change-Id: I5389b639dbf04f6d3e4802c802d5f2029dadc5d5
1 parent 8544a47 commit fc07b93

File tree

3 files changed

+23
-4
lines changed

3 files changed

+23
-4
lines changed

repo/includes/Parsers/DateFormatParser.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use DataValues\IllegalValueException;
66
use DataValues\TimeValue;
7+
use ValueParsers\CalendarModelParser;
8+
use ValueParsers\IsoTimestampParser;
79
use ValueParsers\ParseException;
810
use ValueParsers\ParserOptions;
911
use ValueParsers\StringValueParser;
@@ -44,6 +46,9 @@ class DateFormatParser extends StringValueParser {
4446
*/
4547
public const OPT_PRECISION = 'precision';
4648

49+
/** @var IsoTimestampParser */
50+
private $isoTimestampParser;
51+
4752
public function __construct( ParserOptions $options = null ) {
4853
parent::__construct( $options );
4954

@@ -52,6 +57,11 @@ public function __construct( ParserOptions $options = null ) {
5257
$this->defaultOption( self::OPT_DIGIT_TRANSFORM_TABLE, null );
5358
$this->defaultOption( self::OPT_MONTH_NAMES, null );
5459
$this->defaultOption( self::OPT_PRECISION, null );
60+
61+
$this->isoTimestampParser = new IsoTimestampParser(
62+
new CalendarModelParser( $this->options ),
63+
$this->options
64+
);
5565
}
5666

5767
/**
@@ -109,8 +119,14 @@ protected function stringParse( $value ) {
109119

110120
$timestamp = vsprintf( '+%04s-%02s-%02sT%02s:%02s:%02sZ', $time );
111121

122+
// Use IsoTimestampParser to detect the correct calendar model.
123+
$iso = $this->isoTimestampParser->parse( $timestamp );
124+
112125
try {
113-
return new TimeValue( $timestamp, 0, 0, 0, $precision, TimeValue::CALENDAR_GREGORIAN );
126+
// We intentionally do not re-use the precision from IsoTimestampParser here,
127+
// because it reduces precision for values with zeros in the right-most fields.
128+
// Our above method of determining the precision is therefore better.
129+
return new TimeValue( $timestamp, 0, 0, 0, $precision, $iso->getCalendarModel() );
114130
} catch ( IllegalValueException $ex ) {
115131
throw new ParseException( $ex->getMessage(), $value, self::FORMAT_NAME );
116132
}

repo/includes/Parsers/TimeParserFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,13 @@ private function getTimeParsers() {
9090
$this->options->getOption( ValueParser::OPT_LANG ),
9191
$dateFormatPreference,
9292
'date',
93-
$this->options
93+
clone $this->options
9494
);
9595
$parsers[] = $mwDateFormatParserFactory->getMwDateFormatParser(
9696
$this->options->getOption( ValueParser::OPT_LANG ),
9797
$dateFormatPreference,
9898
'monthonly',
99-
$this->options
99+
clone $this->options
100100
);
101101

102102
$parsers[] = new PhpDateTimeParser(

repo/tests/phpunit/includes/Parsers/MwDateFormatParserFactoryTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,14 @@ public function validInputProvider() {
104104
if ( $precision === null ) {
105105
$precision = $maximumPrecision;
106106
}
107+
$calendarModel = intval( substr( $mwTimestamp, 0, 4 ) ) <= 1582
108+
? TimeValue::CALENDAR_JULIAN
109+
: TimeValue::CALENDAR_GREGORIAN;
107110
$expected = new TimeValue(
108111
$this->getIsoTimestamp( $mwTimestamp, $precision ),
109112
0, 0, 0,
110113
$precision,
111-
TimeValue::CALENDAR_GREGORIAN
114+
$calendarModel
112115
);
113116

114117
yield [

0 commit comments

Comments
 (0)