Ejemplo n.º 1
0
        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
        }
Ejemplo n.º 2
0
        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
        }
Ejemplo n.º 3
0
        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
        }