public static TimeSpan DeserializeStatic(ref JsonReader reader, JsonSerializerOptions options) { var str = reader.ReadNotNullStringSegmentRaw(); var i = 0; var to = str.Length; // check day exists var hasDay = false; { var foundDot = false; var foundColon = false; for (var j = i; j < str.Length; j++) { if (str[j] == '.') { if (foundColon) { break; } foundDot = true; } else if (str[j] == ':') { if (foundDot) { hasDay = true; } foundColon = true; } } } // check sign var minus = false; if (str[i] == '-') { minus = true; i++; } var day = 0; if (hasDay) { var poolArray = ArrayPool <byte> .Shared.Rent(256); try { for (; str[i] != '.'; i++) { poolArray[day++] = str[i]; } var jsonReader = new JsonReader(poolArray); day = jsonReader.ReadInt32(); i++; // skip '.' } finally { ArrayPool <byte> .Shared.Return(poolArray); } } var hour = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)':') { goto ERROR; } var minute = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)':') { goto ERROR; } var second = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); var ticks = 0; if (i < to && str[i] == '.') { i++; // *7. if (!(i < to) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 1000000; i++; if (!(i < to) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 100000; i++; if (!(i < to) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 10000; i++; if (!(i < to) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 1000; i++; if (!(i < to) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 100; i++; if (!(i < to) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 10; i++; if (!(i < to) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 1; i++; // others, lack of precision while (i < to && IntegerConverter.IsNumber(str[i])) { i++; } } END_TICKS: // be careful to overflow var ts = new TimeSpan(day, hour, minute, second); var tk = TimeSpan.FromTicks(ticks); return((minus) ? ts.Negate().Subtract(tk) : ts.Add(tk)); ERROR: #if SPAN_BUILTIN throw new InvalidOperationException("invalid datetime format. value:" + StringEncoding.Utf8.GetString(str)); #else throw new InvalidOperationException("invalid datetime format."); #endif }
public static DateTimeOffset DeserializeStatic(ref JsonReader reader, JsonSerializerOptions options) { var str = reader.ReadNotNullStringSegmentRaw(); var i = 0; switch (str.Length) { // YYYY case 4: { var y = (str[i++] - (byte)'0') * 1000 + (str[i++] - (byte)'0') * 100 + (str[i++] - (byte)'0') * 10 + (str[i] - (byte)'0'); return(new DateTimeOffset(y, 1, 1, 0, 0, 0, TimeSpan.Zero)); } // YYYY-MM case 7: { var y = (str[i++] - (byte)'0') * 1000 + (str[i++] - (byte)'0') * 100 + (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)'-') { goto ERROR; } var m = (str[i++] - (byte)'0') * 10 + (str[i] - (byte)'0'); return(new DateTimeOffset(y, m, 1, 0, 0, 0, TimeSpan.Zero)); } // YYYY-MM-DD case 10: { var y = (str[i++] - (byte)'0') * 1000 + (str[i++] - (byte)'0') * 100 + (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)'-') { goto ERROR; } var m = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)'-') { goto ERROR; } var d = (str[i++] - (byte)'0') * 10 + (str[i] - (byte)'0'); return(new DateTimeOffset(y, m, d, 0, 0, 0, TimeSpan.Zero)); } } // range-first section requires 19 if (str.Length < 19) { goto ERROR; } var year = (str[i++] - (byte)'0') * 1000 + (str[i++] - (byte)'0') * 100 + (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)'-') { goto ERROR; } var month = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)'-') { goto ERROR; } var day = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)'T') { goto ERROR; } var hour = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)':') { goto ERROR; } var minute = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)':') { goto ERROR; } var second = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); var ticks = 0; if (i < str.Length && str[i] == '.') { i++; // *7. if (!(i < str.Length) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 1000000; i++; if (!(i < str.Length) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 100000; i++; if (!(i < str.Length) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 10000; i++; if (!(i < str.Length) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 1000; i++; if (!(i < str.Length) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 100; i++; if (!(i < str.Length) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 10; i++; if (!(i < str.Length) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 1; i++; // others, lack of precision while (i < +str.Length && IntegerConverter.IsNumber(str[i])) { i++; } } END_TICKS: if ((i >= str.Length || str[i] != '-') && str[i] != '+') { return(new DateTimeOffset(year, month, day, hour, minute, second, TimeSpan.Zero).AddTicks(ticks)); } { if (!(i + 5 < str.Length)) { goto ERROR; } var minus = str[i++] == '-'; var h = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); i++; var m = (str[i++] - (byte)'0') * 10 + (str[i] - (byte)'0'); var offset = new TimeSpan(h, m, 0); if (minus) { offset = offset.Negate(); } return(new DateTimeOffset(year, month, day, hour, minute, second, offset).AddTicks(ticks)); } ERROR: #if SPAN_BUILTIN throw new InvalidOperationException("invalid datetime format. value:" + StringEncoding.Utf8.GetString(str)); #else unsafe { fixed(byte *ptr = &str[0]) { throw new InvalidOperationException("invalid datetime format. value:" + StringEncoding.Utf8.GetString(ptr, str.Length)); } } #endif }
public static DateTime DeserializeStatic(ref JsonReader reader, JsonSerializerOptions options) { var str = reader.ReadNotNullStringSegmentRaw(); var i = 0; switch (str.Length) { // YYYY case 4: { var y = (str[i++] - (byte)'0') * 1000 + (str[i++] - (byte)'0') * 100 + (str[i++] - (byte)'0') * 10 + (str[i] - (byte)'0'); return(new DateTime(y, 1, 1)); } // YYYY-MM case 7: { var y = (str[i++] - (byte)'0') * 1000 + (str[i++] - (byte)'0') * 100 + (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)'-') { goto ERROR; } var m = (str[i++] - (byte)'0') * 10 + (str[i] - (byte)'0'); return(new DateTime(y, m, 1)); } // YYYY-MM-DD case 10: { var y = (str[i++] - (byte)'0') * 1000 + (str[i++] - (byte)'0') * 100 + (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)'-') { goto ERROR; } var m = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)'-') { goto ERROR; } var d = (str[i++] - (byte)'0') * 10 + (str[i] - (byte)'0'); return(new DateTime(y, m, d)); } } // range-first section requires 19 if (str.Length < 19) { goto ERROR; } var year = (str[i++] - (byte)'0') * 1000 + (str[i++] - (byte)'0') * 100 + (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)'-') { goto ERROR; } var month = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)'-') { goto ERROR; } var day = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)'T') { goto ERROR; } var hour = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)':') { goto ERROR; } var minute = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); if (str[i++] != (byte)':') { goto ERROR; } var second = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); var ticks = 0; if (i < str.Length && str[i] == '.') { i++; // *7. if (!(i < str.Length) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 1000000; i++; if (!(i < str.Length) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 100000; i++; if (!(i < str.Length) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 10000; i++; if (!(i < str.Length) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 1000; i++; if (!(i < str.Length) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 100; i++; if (!(i < str.Length) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 10; i++; if (!(i < str.Length) || !IntegerConverter.IsNumber(str[i])) { goto END_TICKS; } ticks += (str[i] - (byte)'0') * 1; i++; // others, lack of precision while (i < str.Length && IntegerConverter.IsNumber(str[i])) { i++; } } END_TICKS: var kind = DateTimeKind.Unspecified; if (i < str.Length && str[i] == 'Z') { kind = DateTimeKind.Utc; } else if (i < str.Length && str[i] == '-' || str[i] == '+') { if (!(i + 5 < str.Length)) { goto ERROR; } var minus = str[i++] == '-'; var h = (str[i++] - (byte)'0') * 10 + (str[i++] - (byte)'0'); i++; var m = (str[i++] - (byte)'0') * 10 + (str[i] - (byte)'0'); var offset = new TimeSpan(h, m, 0); if (minus) { offset = offset.Negate(); } return(new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc).AddTicks(ticks).Subtract(offset).ToLocalTime()); } return(new DateTime(year, month, day, hour, minute, second, kind).AddTicks(ticks)); ERROR: #if SPAN_BUILTIN throw new InvalidOperationException("invalid datetime format. value:" + StringEncoding.Utf8.GetString(str)); #else throw new InvalidOperationException("invalid datetime format."); #endif }