44
55use DataValues \IllegalValueException ;
66use DataValues \TimeValue ;
7+ use ValueParsers \CalendarModelParser ;
8+ use ValueParsers \IsoTimestampParser ;
79use ValueParsers \ParseException ;
810use ValueParsers \ParserOptions ;
911use 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 }
0 commit comments