@@ -69,8 +69,7 @@ public static DateTime ParseShortestXsdDateTime(string dateTimeStr)
6969 }
7070
7171 if ( dateTimeStr . Length == XsdDateTimeFormatSeconds . Length )
72- return DateTime . ParseExact ( dateTimeStr , XsdDateTimeFormatSeconds , null ,
73- DateTimeStyles . AdjustToUniversal ) ;
72+ return DateTime . ParseExact ( dateTimeStr , XsdDateTimeFormatSeconds , null , DateTimeStyles . AdjustToUniversal ) ;
7473
7574 if ( dateTimeStr . Length >= XsdDateTimeFormat3F . Length
7675 && dateTimeStr . Length <= XsdDateTimeFormat . Length
@@ -79,15 +78,119 @@ public static DateTime ParseShortestXsdDateTime(string dateTimeStr)
7978#if NETFX_CORE
8079 var dateTimeType = JsConfig . DateHandler != JsonDateHandler . ISO8601
8180 ? "yyyy-MM-ddTHH:mm:sszzzzzzz"
82- : "yyyy-MM-ddTHH:mm:sszzzzzzz" ;
81+ : "yyyy-MM-ddTHH:mm:sszzzzzzz" ;
8382
8483 return XmlConvert . ToDateTimeOffset ( dateTimeStr , dateTimeType ) . DateTime . Prepare ( ) ;
8584#else
85+ var dateTime = Env . IsMono ? ParseManual ( dateTimeStr ) : null ;
86+ if ( dateTime != null )
87+ return dateTime . Value ;
88+
8689 return XmlConvert . ToDateTime ( dateTimeStr , XmlDateTimeSerializationMode . Utc ) . Prepare ( ) ;
8790#endif
8891 }
8992
90- return DateTime . Parse ( dateTimeStr , null , DateTimeStyles . AssumeLocal ) . Prepare ( ) ;
93+ try
94+ {
95+ return DateTime . Parse ( dateTimeStr , null , DateTimeStyles . AssumeLocal ) . Prepare ( ) ;
96+ }
97+ catch ( FormatException )
98+ {
99+ var manualDate = ParseManual ( dateTimeStr ) ;
100+ if ( manualDate != null )
101+ return manualDate . Value ;
102+
103+ throw ;
104+ }
105+ }
106+
107+ public static DateTime ? ParseManual ( string dateTimeStr )
108+ {
109+ if ( dateTimeStr == null || dateTimeStr . Length < "YYYY-MM-DD" . Length )
110+ return null ;
111+
112+ var dateKind = DateTimeKind . Utc ;
113+ if ( dateTimeStr . EndsWith ( "Z" ) )
114+ {
115+ dateTimeStr = dateTimeStr . Substring ( 0 , dateTimeStr . Length - 1 ) ;
116+ }
117+
118+ var parts = dateTimeStr . Split ( 'T' ) ;
119+ if ( parts . Length == 1 )
120+ parts = dateTimeStr . SplitOnFirst ( ' ' ) ;
121+
122+ var dateParts = parts [ 0 ] . Split ( '-' ) ;
123+ int hh = 0 , min = 0 , ss = 0 , ms = 0 ;
124+ double subMs = 0 ;
125+ int offsetMultiplier = 0 ;
126+
127+ if ( parts . Length == 2 )
128+ {
129+ var timeStringParts = parts [ 1 ] . Split ( '+' ) ;
130+ if ( timeStringParts . Length == 2 )
131+ {
132+ offsetMultiplier = - 1 ;
133+ }
134+ else
135+ {
136+ timeStringParts = parts [ 1 ] . Split ( '-' ) ;
137+ if ( timeStringParts . Length == 2 )
138+ {
139+ offsetMultiplier = 1 ;
140+ }
141+ }
142+
143+ var timeOffset = timeStringParts . Length == 2 ? timeStringParts [ 1 ] : null ;
144+ var timeParts = timeStringParts [ 0 ] . Split ( ':' ) ;
145+
146+ if ( timeParts . Length == 3 )
147+ {
148+ int . TryParse ( timeParts [ 0 ] , out hh ) ;
149+ int . TryParse ( timeParts [ 1 ] , out min ) ;
150+
151+ var secParts = timeParts [ 2 ] . Split ( '.' ) ;
152+ int . TryParse ( secParts [ 0 ] , out ss ) ;
153+ if ( secParts . Length == 2 )
154+ {
155+ var msStr = secParts [ 1 ] . PadRight ( 3 , '0' ) ;
156+ ms = int . Parse ( msStr . Substring ( 0 , 3 ) ) ;
157+
158+ if ( msStr . Length > 3 )
159+ {
160+ var subMsStr = msStr . Substring ( 3 ) ;
161+ subMs = double . Parse ( subMsStr ) / Math . Pow ( 10 , subMsStr . Length ) ;
162+ }
163+ }
164+ }
165+
166+ var dateTime = new DateTime ( int . Parse ( dateParts [ 0 ] ) , int . Parse ( dateParts [ 1 ] ) , int . Parse ( dateParts [ 2 ] ) , hh , min , ss , ms , dateKind ) ;
167+ if ( subMs != 0 )
168+ {
169+ dateTime . AddMilliseconds ( subMs ) ;
170+ }
171+
172+ if ( offsetMultiplier != 0 && timeOffset != null )
173+ {
174+ timeParts = timeOffset . Split ( ':' ) ;
175+ if ( timeParts . Length == 2 )
176+ {
177+ hh = int . Parse ( timeParts [ 0 ] ) ;
178+ min = int . Parse ( timeParts [ 1 ] ) ;
179+ }
180+ else
181+ {
182+ hh = int . Parse ( timeOffset . Substring ( 0 , 2 ) ) ;
183+ min = int . Parse ( timeOffset . Substring ( 2 ) ) ;
184+ }
185+
186+ dateTime = dateTime . AddHours ( offsetMultiplier * hh ) ;
187+ dateTime = dateTime . AddMinutes ( offsetMultiplier * min ) ;
188+ }
189+
190+ return dateTime . ToLocalTime ( ) . Prepare ( ) ;
191+ }
192+
193+ return null ;
91194 }
92195
93196 public static string ToDateTimeString ( DateTime dateTime )
0 commit comments