Example #1
0
        protected bool ParseDateTime(string s, DateTimePart part)
        {
            ParseContext context = new ParseContext(s);

            bool bDatePart = ( part & DateTimePart.Date ) != 0;
            bool bTimePart = ( part & DateTimePart.Time ) != 0;

            int year = 0, month = 0, day = 0;
            int hour = 0, minute = 0;
            double second = 0;

            eTZ = ETZ.Missing;
            offsetTZ = 0;

            if ( bDatePart )
            {
                // parse date
                bool bNegative = context.CheckAndAdvance( '-' );

                if ( (part & DateTimePart.Year ) != 0 )
                {
                    int digits = 0;
                    int temp = 0;
                    while ( context.ReadDigitAndAdvance( ref temp, 1, 9 ) )
                    {
                        year = year * 10 + temp;
                        digits += 1;
                        temp = 0;
                        if (digits >= 8) // overflow
                            return false;
                    }
                    if ( digits < 4 ) // invalid.
                        return false;
                    if ( digits > 4 && year < 10000 )
                        return false;
                    if (bNegative)
                        year = -year;
                }

                if ( (part & ( DateTimePart.Month | DateTimePart.Day )) != 0 )
                {
                    if ( !context.CheckAndAdvance( '-' ) ) return false;

                    if ( ( part & DateTimePart.Month ) != 0 )
                    {
                        if ( !context.ReadDigitAndAdvance( ref month, 10, 1 ) ) return false;
                        if ( !context.ReadDigitAndAdvance( ref month, 1, month < 10 ? 9 : 2 ) ) return false;
                        if ( month == 0 ) return false;
                    }

                    if ( ( part & DateTimePart.Day ) != 0 )
                    {
                        if ( !context.CheckAndAdvance(  '-') ) return false;

                        int maxFirstDigit = month != 2 ? 3 : 2;

                        // complicate things by making them complicated.
                        if ( !context.ReadDigitAndAdvance( ref day, 10, maxFirstDigit ) ) return false;
                        if ( !context.ReadDigitAndAdvance( ref day, 1, 9 ) ) return false;
                        if ( day == 0 || day > 31 ) return false;

                        if ( ( part & DateTimePart.Month ) != 0 )
                        {
                            bool b1 = month <= 7;
                            bool b2 = ( month & 1 ) == 0;

                            // month 1, 3, 5, 7, 8, 10, 12
                            if ( b1 == b2 && day > 30 )
                                return false;

                            // february.
                            if ( month == 2 && day > 29 )
                                return false;

                            // leap years.
                            if ( month == 2 && ( part & DateTimePart.Year ) != 0 &&
                                ( year % 4 != 0 || year % 100 == 0 ) && year % 400 != 0 &&
                                day > 28 )
                                return false;
                        }
                    }
                }

                if ( bTimePart )
                {
                    // a 'T' must follow
                    if ( !context.CheckAndAdvance( 'T') ) return false;
                }
            }

            if ( bTimePart )
            {
                // check format here

                // hour from 0 to 2
                if ( !context.ReadDigitAndAdvance( ref hour, 10, 2 ) ) return false;
                if ( !context.ReadDigitAndAdvance( ref hour, 1, hour < 20 ? 9 : 4 ) ) return false;
                if ( !context.CheckAndAdvance( ':' ) ) return false;
                int maxFirstDigit = hour == 24 ? 0 : 5;
                int maxSecondDigit = hour == 24 ? 0 : 9;
                if ( !context.ReadDigitAndAdvance( ref minute, 10, maxFirstDigit ) ) return false;
                if ( !context.ReadDigitAndAdvance( ref minute, 1, maxSecondDigit ) ) return false;
                if ( !context.CheckAndAdvance( ':' ) ) return false;
                int secondInt = 0;
                if ( !context.ReadDigitAndAdvance( ref secondInt, 10, maxFirstDigit ) ) return false;
                if ( !context.ReadDigitAndAdvance( ref secondInt, 1, maxSecondDigit ) ) return false;

                second = secondInt;

                if ( context.CheckAndAdvance( '.' ) )
                {
                    // fraction. do whatever seems fit.
                    int val = 0;
                    int digits = 0;
                    while ( context.ReadDigitAndAdvance( ref val, 1, 9) )
                    {
                        val *= 10;
                        digits += 1;
                        if ( digits >= 8 ) // precision loss - ignore
                            break;
                    }

                    if ( digits == 0 )
                        return false;

                    second += val * Math.Pow( 10.0, -digits - 1 );

                    // skip any further digits.
                    while ( context.ReadDigitAndAdvance( ref val, 0, 9) )
                        ;
                }
            }

            // timezone
            if ( context.CheckAndAdvance('Z') )
            {
                // timezone specified, it is UTC.
                eTZ = ETZ.UTC;
                offsetTZ = 0;
            }
            else if ( context.Check('+') || context.Check('-' ) )
            {
                // timezone offset, in hour:minute format
                bool bNegative = context.Check('-');
                context.Advance();

                // do not check the hour part, for those who are obscure.
                int temp = 0;
                if ( !context.ReadDigitAndAdvance( ref temp, 600, 9 ) ) return false;
                if ( !context.ReadDigitAndAdvance( ref temp, 60, 9 ) ) return false;
                if ( !context.CheckAndAdvance( ':' ) ) return false;
                if ( !context.ReadDigitAndAdvance( ref temp, 10, 5 ) ) return false;
                if ( !context.ReadDigitAndAdvance( ref temp, 1, 9 ) ) return false;

                eTZ = ETZ.Offset;
                offsetTZ = bNegative ? -temp : temp;
            }

            if ( context.IsValid() )
                return false;

            // C# specific
            if (year <= 0) year = 1;
            if (month == 0) month = 1;
            bool badjust = false;
            if (hour == 24)
            {
                hour = 0;
                badjust = true;
            }
            if (day == 0) day = 1;
            try {
                myValue = new System.DateTime(year, month, day, hour, minute, (int)second,
                    (int)(second * 1000) % 1000);
                if (badjust)
                    myValue.AddDays(1);
            }
            catch
            {
                return false;
            }
            return true;
        }
Example #2
0
        bool ParseDateTime(string s, DateTimePart part)
        {
            ParseContext context = new ParseContext(s);

            bool bDatePart = (part & DateTimePart.Date) != 0;
            bool bTimePart = (part & DateTimePart.Time) != 0;

            int    year = 0, month = 0, day = 0;
            int    hour = 0, minute = 0;
            double second = 0;

            timezone = NoTimezone;

            if (bDatePart)
            {
                // parse date
                bool bNegative = context.CheckAndAdvance('-');

                if ((part & DateTimePart.Year) != 0)
                {
                    int digits = 0;
                    int temp   = 0;
                    while (context.ReadDigitAndAdvance(ref temp, 1, 9))
                    {
                        year    = year * 10 + temp;
                        digits += 1;
                        temp    = 0;
                        if (digits >= 8)                         // overflow
                        {
                            return(false);
                        }
                    }
                    if (digits < 4)                       // invalid.
                    {
                        return(false);
                    }
                    if (digits > 4 && year < 10000)
                    {
                        return(false);
                    }
                    if (bNegative)
                    {
                        year = -year;
                    }
                }

                if ((part & (DateTimePart.Month | DateTimePart.Day)) != 0)
                {
                    if (!context.CheckAndAdvance('-'))
                    {
                        return(false);
                    }

                    if ((part & DateTimePart.Month) != 0)
                    {
                        if (!context.ReadDigitAndAdvance(ref month, 10, 1))
                        {
                            return(false);
                        }
                        if (!context.ReadDigitAndAdvance(ref month, 1, month < 10 ? 9 : 2))
                        {
                            return(false);
                        }
                        if (month == 0)
                        {
                            return(false);
                        }
                    }

                    if ((part & DateTimePart.Day) != 0)
                    {
                        if (!context.CheckAndAdvance('-'))
                        {
                            return(false);
                        }

                        int maxFirstDigit = month != 2 ? 3 : 2;

                        // complicate things by making them complicated.
                        if (!context.ReadDigitAndAdvance(ref day, 10, maxFirstDigit))
                        {
                            return(false);
                        }
                        if (!context.ReadDigitAndAdvance(ref day, 1, 9))
                        {
                            return(false);
                        }
                        if (day == 0 || day > 31)
                        {
                            return(false);
                        }

                        if ((part & DateTimePart.Month) != 0)
                        {
                            bool b1 = month <= 7;
                            bool b2 = (month & 1) == 0;

                            // month 1, 3, 5, 7, 8, 10, 12
                            if (b1 == b2 && day > 30)
                            {
                                return(false);
                            }

                            // february.
                            if (month == 2 && day > 29)
                            {
                                return(false);
                            }

                            // leap years.
                            if (month == 2 && (part & DateTimePart.Year) != 0 &&
                                (year % 4 != 0 || year % 100 == 0) && year % 400 != 0 &&
                                day > 28)
                            {
                                return(false);
                            }
                        }
                    }
                }

                if (bTimePart)
                {
                    // a 'T' must follow
                    if (!context.CheckAndAdvance('T'))
                    {
                        return(false);
                    }
                }
            }

            if (bTimePart)
            {
                // check format here

                // hour from 0 to 2
                if (!context.ReadDigitAndAdvance(ref hour, 10, 2))
                {
                    return(false);
                }
                if (!context.ReadDigitAndAdvance(ref hour, 1, hour < 20 ? 9 : 4))
                {
                    return(false);
                }
                if (!context.CheckAndAdvance(':'))
                {
                    return(false);
                }
                int maxFirstDigit  = hour == 24 ? 0 : 5;
                int maxSecondDigit = hour == 24 ? 0 : 9;
                if (!context.ReadDigitAndAdvance(ref minute, 10, maxFirstDigit))
                {
                    return(false);
                }
                if (!context.ReadDigitAndAdvance(ref minute, 1, maxSecondDigit))
                {
                    return(false);
                }
                if (!context.CheckAndAdvance(':'))
                {
                    return(false);
                }
                int secondInt = 0;
                if (!context.ReadDigitAndAdvance(ref secondInt, 10, maxFirstDigit))
                {
                    return(false);
                }
                if (!context.ReadDigitAndAdvance(ref secondInt, 1, maxSecondDigit))
                {
                    return(false);
                }

                second = secondInt;

                if (context.CheckAndAdvance('.'))
                {
                    // fraction. do whatever seems fit.
                    int val    = 0;
                    int digits = 0;
                    while (context.ReadDigitAndAdvance(ref val, 1, 9))
                    {
                        val    *= 10;
                        digits += 1;
                        if (digits >= 8)                           // precision loss - ignore
                        {
                            break;
                        }
                    }

                    if (digits == 0)
                    {
                        return(false);
                    }

                    second += val * System.Math.Pow(10.0, -digits - 1);

                    // skip any further digits.
                    while (context.ReadDigitAndAdvance(ref val, 0, 9))
                    {
                        ;
                    }
                }
            }

            // timezone
            if (context.CheckAndAdvance('Z'))
            {
                // timezone specified, it is UTC.
                timezone = 0;
            }
            else if (context.Check('+') || context.Check('-'))
            {
                // timezone offset, in hour:minute format
                bool bNegative = context.Check('-');
                context.Advance();

                // do not check the hour part, for those who are obscure.
                int temp = 0;
                if (!context.ReadDigitAndAdvance(ref temp, 600, 9))
                {
                    return(false);
                }
                if (!context.ReadDigitAndAdvance(ref temp, 60, 9))
                {
                    return(false);
                }
                if (!context.CheckAndAdvance(':'))
                {
                    return(false);
                }
                if (!context.ReadDigitAndAdvance(ref temp, 10, 5))
                {
                    return(false);
                }
                if (!context.ReadDigitAndAdvance(ref temp, 1, 9))
                {
                    return(false);
                }

                timezone = (short)(bNegative ? -temp : temp);
            }

            if (context.IsValid())
            {
                return(false);
            }

            // C# specific
            if (year <= 0)
            {
                year = 1;
            }
            if (month == 0)
            {
                month = 1;
            }
            bool badjust = false;

            if (hour == 24)
            {
                hour    = 0;
                badjust = true;
            }
            if (day == 0)
            {
                day = 1;
            }
            if ((part & DateTimePart.Year) == 0 && month == 2 && day == 29)
            {
                year = 4;
            }
            try
            {
                myValue = new System.DateTime(year, month, day, hour, minute, (int)second,
                                              (int)(second * 1000) % 1000);
                if (badjust)
                {
                    myValue.AddDays(1);
                }
            }
            catch
            {
                return(false);
            }
            return(true);
        }