public DateTimeOffset Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver) { var str = reader.ReadStringSegmentUnsafe(); var array = str.Array; var i = str.Offset; var len = str.Count; var to = str.Offset + str.Count; // YYYY if (len == 4) { var y = (array[i++] - (byte)'0') * 1000 + (array[i++] - (byte)'0') * 100 + (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); return(new DateTimeOffset(y, 1, 1, 0, 0, 0, TimeSpan.Zero)); } // YYYY-MM if (len == 7) { var y = (array[i++] - (byte)'0') * 1000 + (array[i++] - (byte)'0') * 100 + (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'-') { goto ERROR; } var m = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); return(new DateTimeOffset(y, m, 1, 0, 0, 0, TimeSpan.Zero)); } // YYYY-MM-DD if (len == 10) { var y = (array[i++] - (byte)'0') * 1000 + (array[i++] - (byte)'0') * 100 + (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'-') { goto ERROR; } var m = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'-') { goto ERROR; } var d = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); return(new DateTimeOffset(y, m, d, 0, 0, 0, TimeSpan.Zero)); } // range-first section requires 19 if (array.Length < 19) { goto ERROR; } var year = (array[i++] - (byte)'0') * 1000 + (array[i++] - (byte)'0') * 100 + (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'-') { goto ERROR; } var month = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'-') { goto ERROR; } var day = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)'T') { goto ERROR; } var hour = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)':') { goto ERROR; } var minute = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)':') { goto ERROR; } var second = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); int ticks = 0; if (i < to && array[i] == '.') { i++; // *7. if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1000000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 100000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 10000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 100; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 10; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1; i++; // others, lack of precision while (i < to && NumberConverter.IsNumber(array[i])) { i++; } } END_TICKS: if (i < to && array[i] == '-' || array[i] == '+') { if (!(i + 5 < to)) { goto ERROR; } var minus = array[i++] == '-'; var h = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); i++; var m = (array[i++] - (byte)'0') * 10 + (array[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)); } return(new DateTimeOffset(year, month, day, hour, minute, second, TimeSpan.Zero).AddTicks(ticks)); ERROR: throw new InvalidOperationException("invalid datetime format. value:" + StringEncoding.UTF8.GetString(str.Array, str.Offset, str.Count)); }
public TimeSpan Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver) { var str = reader.ReadStringSegmentUnsafe(); var array = str.Array; var i = str.Offset; var len = str.Count; var to = str.Offset + str.Count; // check day exists bool hasDay = false; { bool foundDot = false; bool foundColon = false; for (int j = i; j < str.Count; j++) { if (array[j] == '.') { if (foundColon) { break; } foundDot = true; } else if (array[j] == ':') { if (foundDot) { hasDay = true; } foundColon = true; } } } // check sign var minus = false; if (array[i] == '-') { minus = true; i++; } var day = 0; if (hasDay) { var poolArray = JsonSerializer.MemoryPool.Rent(); try { for (; array[i] != '.'; i++) { poolArray[day++] = array[i]; } day = new JsonReader(poolArray).ReadInt32(); i++; // skip '.' } finally { JsonSerializer.MemoryPool.Return(poolArray); } } var hour = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)':') { goto ERROR; } var minute = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); if (array[i++] != (byte)':') { goto ERROR; } var second = (array[i++] - (byte)'0') * 10 + (array[i++] - (byte)'0'); int ticks = 0; if (i < to && array[i] == '.') { i++; // *7. if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1000000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 100000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 10000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1000; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 100; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 10; i++; if (!(i < to) || !NumberConverter.IsNumber(array[i])) { goto END_TICKS; } ticks += (array[i] - (byte)'0') * 1; i++; // others, lack of precision while (i < to && NumberConverter.IsNumber(array[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: throw new InvalidOperationException("invalid datetime format. value:" + StringEncoding.UTF8.GetString(str.Array, str.Offset, str.Count)); }