@@ -21,6 +21,7 @@ namespace ServiceStack.Text.Common
2121{
2222 public static class DateTimeSerializer
2323 {
24+ public const string CondensedDateTimeFormat = "yyyyMMdd" ; //8
2425 public const string ShortDateTimeFormat = "yyyy-MM-dd" ; //11
2526 public const string DefaultDateTimeFormat = "dd/MM/yyyy HH:mm:ss" ; //20
2627 public const string DefaultDateTimeFormatWithFraction = "dd/MM/yyyy HH:mm:ss.fff" ; //24
@@ -40,6 +41,9 @@ public static class DateTimeSerializer
4041 private const char XsdTimeSeparator = 'T' ;
4142 private static readonly int XsdTimeSeparatorIndex = XsdDateTimeFormat . IndexOf ( XsdTimeSeparator ) ;
4243 private const string XsdUtcSuffix = "Z" ;
44+ private static readonly char [ ] DateTimeSeperators = new [ ] { '-' , '/' } ;
45+
46+ public static Func < string , Exception , DateTime > OnParseErrorFn { get ; set ; }
4347
4448 /// <summary>
4549 /// If AlwaysUseUtc is set to true then convert all DateTime to UTC.
@@ -70,69 +74,84 @@ public static DateTime ParseRFC1123DateTime(string dateTimeStr)
7074
7175 public static DateTime ParseShortestXsdDateTime ( string dateTimeStr )
7276 {
73- if ( string . IsNullOrEmpty ( dateTimeStr ) )
74- return DateTime . MinValue ;
77+ try
78+ {
79+ if ( string . IsNullOrEmpty ( dateTimeStr ) )
80+ return DateTime . MinValue ;
7581
76- if ( dateTimeStr . StartsWith ( EscapedWcfJsonPrefix , StringComparison . Ordinal ) || dateTimeStr . StartsWith ( WcfJsonPrefix , StringComparison . Ordinal ) )
77- return ParseWcfJsonDate ( dateTimeStr ) . Prepare ( ) ;
82+ if ( dateTimeStr . StartsWith ( EscapedWcfJsonPrefix , StringComparison . Ordinal ) || dateTimeStr . StartsWith ( WcfJsonPrefix , StringComparison . Ordinal ) )
83+ return ParseWcfJsonDate ( dateTimeStr ) . Prepare ( ) ;
7884
79- if ( dateTimeStr . Length == DefaultDateTimeFormat . Length
80- || dateTimeStr . Length == DefaultDateTimeFormatWithFraction . Length )
81- {
82- var unspecifiedDate = DateTime . Parse ( dateTimeStr , CultureInfo . InvariantCulture ) ;
83- if ( JsConfig . AssumeUtc )
84- unspecifiedDate = DateTime . SpecifyKind ( unspecifiedDate , DateTimeKind . Utc ) ;
85+ if ( dateTimeStr . Length == DefaultDateTimeFormat . Length
86+ || dateTimeStr . Length == DefaultDateTimeFormatWithFraction . Length )
87+ {
88+ var unspecifiedDate = DateTime . Parse ( dateTimeStr , CultureInfo . InvariantCulture ) ;
89+ if ( JsConfig . AssumeUtc )
90+ unspecifiedDate = DateTime . SpecifyKind ( unspecifiedDate , DateTimeKind . Utc ) ;
8591
86- return unspecifiedDate . Prepare ( ) ;
87- }
92+ return unspecifiedDate . Prepare ( ) ;
93+ }
8894
89- switch ( JsConfig . DateHandler )
90- {
91- case DateHandler . UnixTime :
92- int unixTime ;
93- if ( int . TryParse ( dateTimeStr , out unixTime ) )
94- return unixTime . FromUnixTime ( ) ;
95- break ;
96- case DateHandler . UnixTimeMs :
97- long unixTimeMs ;
98- if ( long . TryParse ( dateTimeStr , out unixTimeMs ) )
99- return unixTimeMs . FromUnixTimeMs ( ) ;
100- break ;
101- }
95+ switch ( JsConfig . DateHandler )
96+ {
97+ case DateHandler . UnixTime :
98+ int unixTime ;
99+ if ( int . TryParse ( dateTimeStr , out unixTime ) )
100+ return unixTime . FromUnixTime ( ) ;
101+ break ;
102+ case DateHandler . UnixTimeMs :
103+ long unixTimeMs ;
104+ if ( long . TryParse ( dateTimeStr , out unixTimeMs ) )
105+ return unixTimeMs . FromUnixTimeMs ( ) ;
106+ break ;
107+ }
102108
103- dateTimeStr = RepairXsdTimeSeparator ( dateTimeStr ) ;
109+ dateTimeStr = RepairXsdTimeSeparator ( dateTimeStr ) ;
104110
105- if ( dateTimeStr . Length == XsdDateTimeFormatSeconds . Length )
106- return DateTime . ParseExact ( dateTimeStr , XsdDateTimeFormatSeconds , null , DateTimeStyles . AdjustToUniversal ) . Prepare ( parsedAsUtc : true ) ;
111+ if ( dateTimeStr . Length == XsdDateTimeFormatSeconds . Length )
112+ return DateTime . ParseExact ( dateTimeStr , XsdDateTimeFormatSeconds , null , DateTimeStyles . AdjustToUniversal ) . Prepare ( parsedAsUtc : true ) ;
107113
108- if ( dateTimeStr . Length >= XsdDateTimeFormat3F . Length
109- && dateTimeStr . Length <= XsdDateTimeFormat . Length
110- && dateTimeStr . EndsWith ( XsdUtcSuffix ) )
111- {
112- var dateTime = Env . IsMono ? ParseManual ( dateTimeStr ) : null ;
113- if ( dateTime != null )
114- return dateTime . Value ;
114+ if ( dateTimeStr . Length >= XsdDateTimeFormat3F . Length
115+ && dateTimeStr . Length <= XsdDateTimeFormat . Length
116+ && dateTimeStr . EndsWith ( XsdUtcSuffix ) )
117+ {
118+ var dateTime = Env . IsMono ? ParseManual ( dateTimeStr ) : null ;
119+ if ( dateTime != null )
120+ return dateTime . Value ;
115121
116- return PclExport . Instance . ParseXsdDateTimeAsUtc ( dateTimeStr ) ;
117- }
122+ return PclExport . Instance . ParseXsdDateTimeAsUtc ( dateTimeStr ) ;
123+ }
118124
119- if ( dateTimeStr . Length == ShortDateTimeFormat . Length )
120- {
121- var manualDate = ParseManual ( dateTimeStr ) ;
122- if ( manualDate != null )
123- return manualDate . Value ;
124- }
125+ if ( dateTimeStr . Length == CondensedDateTimeFormat . Length && dateTimeStr . IndexOfAny ( DateTimeSeperators ) == - 1 )
126+ {
127+ return DateTime . ParseExact ( dateTimeStr , "yyyyMMdd" , CultureInfo . InvariantCulture , DateTimeStyles . None ) ;
128+ }
125129
126- try
127- {
128- var dateTime = DateTime . Parse ( dateTimeStr , null , DateTimeStyles . AssumeLocal ) ;
129- return dateTime . Prepare ( ) ;
130+ if ( dateTimeStr . Length == ShortDateTimeFormat . Length )
131+ {
132+ var manualDate = ParseManual ( dateTimeStr ) ;
133+ if ( manualDate != null )
134+ return manualDate . Value ;
135+ }
136+
137+ try
138+ {
139+ var dateTime = DateTime . Parse ( dateTimeStr , null , DateTimeStyles . AssumeLocal ) ;
140+ return dateTime . Prepare ( ) ;
141+ }
142+ catch ( FormatException )
143+ {
144+ var manualDate = ParseManual ( dateTimeStr ) ;
145+ if ( manualDate != null )
146+ return manualDate . Value ;
147+
148+ throw ;
149+ }
130150 }
131- catch ( FormatException )
151+ catch ( Exception ex )
132152 {
133- var manualDate = ParseManual ( dateTimeStr ) ;
134- if ( manualDate != null )
135- return manualDate . Value ;
153+ if ( OnParseErrorFn != null )
154+ return OnParseErrorFn ( dateTimeStr , ex ) ;
136155
137156 throw ;
138157 }
0 commit comments