コード例 #1
0
		private static bool Lex(DateTimeParse.DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi)
		{
			dtok.dtt = DateTimeParse.DTT.Unk;
			TokenType tokenType;
			int num;
			str.GetRegularToken(out tokenType, out num, dtfi);
			switch (tokenType)
			{
				case TokenType.NumberToken:
				case TokenType.YearNumberToken:
				{
					if (raw.numCount == 3 || num == -1)
					{
						result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
						return false;
					}
					if (dps == DateTimeParse.DS.T_NNt && str.Index < str.len - 1)
					{
						char c = str.Value[str.Index];
						if (c == '.')
						{
							DateTimeParse.ParseFraction(ref str, out raw.fraction);
						}
					}
					if ((dps == DateTimeParse.DS.T_NNt || dps == DateTimeParse.DS.T_Nt) && str.Index < str.len - 1 && !DateTimeParse.HandleTimeZone(ref str, ref result))
					{
						return false;
					}
					dtok.num = num;
					if (tokenType != TokenType.YearNumberToken)
					{
						int index;
						char current;
						TokenType separatorToken;
						TokenType tokenType2 = separatorToken = str.GetSeparatorToken(dtfi, out index, out current);
						if (separatorToken > TokenType.SEP_YearSuff)
						{
							if (separatorToken <= TokenType.SEP_HourSuff)
							{
								if (separatorToken == TokenType.SEP_MonthSuff || separatorToken == TokenType.SEP_DaySuff)
								{
									dtok.dtt = DateTimeParse.DTT.NumDatesuff;
									dtok.suffix = tokenType2;
									break;
								}
								if (separatorToken != TokenType.SEP_HourSuff)
								{
									goto IL_52A;
								}
							}
							else
							{
								if (separatorToken <= TokenType.SEP_SecondSuff)
								{
									if (separatorToken != TokenType.SEP_MinuteSuff && separatorToken != TokenType.SEP_SecondSuff)
									{
										goto IL_52A;
									}
								}
								else
								{
									if (separatorToken == TokenType.SEP_LocalTimeMark)
									{
										dtok.dtt = DateTimeParse.DTT.NumLocalTimeMark;
										raw.AddNumber(dtok.num);
										break;
									}
									if (separatorToken != TokenType.SEP_DateOrOffset)
									{
										goto IL_52A;
									}
									if (DateTimeParse.dateParsingStates[(int)dps][4] == DateTimeParse.DS.ERROR && DateTimeParse.dateParsingStates[(int)dps][3] > DateTimeParse.DS.ERROR)
									{
										str.Index = index;
										str.m_current = current;
										dtok.dtt = DateTimeParse.DTT.NumSpace;
									}
									else
									{
										dtok.dtt = DateTimeParse.DTT.NumDatesep;
									}
									raw.AddNumber(dtok.num);
									break;
								}
							}
							dtok.dtt = DateTimeParse.DTT.NumTimesuff;
							dtok.suffix = tokenType2;
							break;
						}
						if (separatorToken <= TokenType.SEP_Am)
						{
							if (separatorToken == TokenType.SEP_End)
							{
								dtok.dtt = DateTimeParse.DTT.NumEnd;
								raw.AddNumber(dtok.num);
								break;
							}
							if (separatorToken == TokenType.SEP_Space)
							{
								dtok.dtt = DateTimeParse.DTT.NumSpace;
								raw.AddNumber(dtok.num);
								break;
							}
							if (separatorToken != TokenType.SEP_Am)
							{
								goto IL_52A;
							}
						}
						else
						{
							if (separatorToken <= TokenType.SEP_Date)
							{
								if (separatorToken != TokenType.SEP_Pm)
								{
									if (separatorToken != TokenType.SEP_Date)
									{
										goto IL_52A;
									}
									dtok.dtt = DateTimeParse.DTT.NumDatesep;
									raw.AddNumber(dtok.num);
									break;
								}
							}
							else
							{
								if (separatorToken == TokenType.SEP_Time)
								{
									dtok.dtt = DateTimeParse.DTT.NumTimesep;
									raw.AddNumber(dtok.num);
									break;
								}
								if (separatorToken != TokenType.SEP_YearSuff)
								{
									goto IL_52A;
								}
								dtok.num = dtfi.Calendar.ToFourDigitYear(num);
								dtok.dtt = DateTimeParse.DTT.NumDatesuff;
								dtok.suffix = tokenType2;
								break;
							}
						}
						if (raw.timeMark != DateTimeParse.TM.NotSet)
						{
							result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
							break;
						}
						raw.timeMark = ((tokenType2 == TokenType.SEP_Am) ? DateTimeParse.TM.AM : DateTimeParse.TM.PM);
						dtok.dtt = DateTimeParse.DTT.NumAmpm;
						raw.AddNumber(dtok.num);
						if ((dps == DateTimeParse.DS.T_NNt || dps == DateTimeParse.DS.T_Nt) && !DateTimeParse.HandleTimeZone(ref str, ref result))
						{
							return false;
						}
						break;
						IL_52A:
						result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
						return false;
					}
					if (raw.year == -1)
					{
						raw.year = num;
						int index;
						char current;
						TokenType separatorToken2;
						TokenType tokenType2 = separatorToken2 = str.GetSeparatorToken(dtfi, out index, out current);
						if (separatorToken2 > TokenType.SEP_YearSuff)
						{
							if (separatorToken2 <= TokenType.SEP_HourSuff)
							{
								if (separatorToken2 == TokenType.SEP_MonthSuff || separatorToken2 == TokenType.SEP_DaySuff)
								{
									goto IL_26A;
								}
								if (separatorToken2 != TokenType.SEP_HourSuff)
								{
									goto IL_28E;
								}
							}
							else
							{
								if (separatorToken2 != TokenType.SEP_MinuteSuff && separatorToken2 != TokenType.SEP_SecondSuff)
								{
									if (separatorToken2 != TokenType.SEP_DateOrOffset)
									{
										goto IL_28E;
									}
									if (DateTimeParse.dateParsingStates[(int)dps][13] == DateTimeParse.DS.ERROR && DateTimeParse.dateParsingStates[(int)dps][12] > DateTimeParse.DS.ERROR)
									{
										str.Index = index;
										str.m_current = current;
										dtok.dtt = DateTimeParse.DTT.YearSpace;
										return true;
									}
									dtok.dtt = DateTimeParse.DTT.YearDateSep;
									return true;
								}
							}
							dtok.dtt = DateTimeParse.DTT.NumTimesuff;
							dtok.suffix = tokenType2;
							return true;
						}
						if (separatorToken2 <= TokenType.SEP_Am)
						{
							if (separatorToken2 == TokenType.SEP_End)
							{
								dtok.dtt = DateTimeParse.DTT.YearEnd;
								return true;
							}
							if (separatorToken2 == TokenType.SEP_Space)
							{
								dtok.dtt = DateTimeParse.DTT.YearSpace;
								return true;
							}
							if (separatorToken2 != TokenType.SEP_Am)
							{
								goto IL_28E;
							}
						}
						else
						{
							if (separatorToken2 != TokenType.SEP_Pm)
							{
								if (separatorToken2 == TokenType.SEP_Date)
								{
									dtok.dtt = DateTimeParse.DTT.YearDateSep;
									return true;
								}
								if (separatorToken2 != TokenType.SEP_YearSuff)
								{
									goto IL_28E;
								}
								goto IL_26A;
							}
						}
						if (raw.timeMark == DateTimeParse.TM.NotSet)
						{
							raw.timeMark = ((tokenType2 == TokenType.SEP_Am) ? DateTimeParse.TM.AM : DateTimeParse.TM.PM);
							dtok.dtt = DateTimeParse.DTT.YearSpace;
							return true;
						}
						result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
						return true;
						IL_26A:
						dtok.dtt = DateTimeParse.DTT.NumDatesuff;
						dtok.suffix = tokenType2;
						return true;
						IL_28E:
						result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
						return false;
					}
					result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
					return false;
				}
				case TokenType.Am:
				case TokenType.Pm:
				{
					if (raw.timeMark != DateTimeParse.TM.NotSet)
					{
						result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
						return false;
					}
					raw.timeMark = (DateTimeParse.TM)num;
					break;
				}
				case TokenType.MonthToken:
				{
					if (raw.month != -1)
					{
						result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
						return false;
					}
					int index;
					char current;
					TokenType separatorToken3 = str.GetSeparatorToken(dtfi, out index, out current);
					if (separatorToken3 <= TokenType.SEP_Space)
					{
						if (separatorToken3 == TokenType.SEP_End)
						{
							dtok.dtt = DateTimeParse.DTT.MonthEnd;
							goto IL_786;
						}
						if (separatorToken3 == TokenType.SEP_Space)
						{
							dtok.dtt = DateTimeParse.DTT.MonthSpace;
							goto IL_786;
						}
					}
					else
					{
						if (separatorToken3 == TokenType.SEP_Date)
						{
							dtok.dtt = DateTimeParse.DTT.MonthDatesep;
							goto IL_786;
						}
						if (separatorToken3 == TokenType.SEP_DateOrOffset)
						{
							if (DateTimeParse.dateParsingStates[(int)dps][8] == DateTimeParse.DS.ERROR && DateTimeParse.dateParsingStates[(int)dps][7] > DateTimeParse.DS.ERROR)
							{
								str.Index = index;
								str.m_current = current;
								dtok.dtt = DateTimeParse.DTT.MonthSpace;
								goto IL_786;
							}
							dtok.dtt = DateTimeParse.DTT.MonthDatesep;
							goto IL_786;
						}
					}
					result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
					return false;
					IL_786:
					raw.month = num;
					break;
				}
				case TokenType.EndOfString:
				{
					dtok.dtt = DateTimeParse.DTT.End;
					break;
				}
				case TokenType.DayOfWeekToken:
				{
					if (raw.dayOfWeek != -1)
					{
						result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
						return false;
					}
					raw.dayOfWeek = num;
					dtok.dtt = DateTimeParse.DTT.DayOfWeek;
					break;
				}
				case TokenType.TimeZoneToken:
				{
					if ((result.flags & ParseFlags.TimeZoneUsed) != (ParseFlags)0)
					{
						result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
						return false;
					}
					dtok.dtt = DateTimeParse.DTT.TimeZone;
					result.flags |= ParseFlags.TimeZoneUsed;
					result.timeZoneOffset = new TimeSpan(0L);
					result.flags |= ParseFlags.TimeZoneUtc;
					break;
				}
				case TokenType.EraToken:
				{
					if (result.era == -1)
					{
						result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
						return false;
					}
					result.era = num;
					dtok.dtt = DateTimeParse.DTT.Era;
					break;
				}
				case TokenType.UnknownToken:
				{
					if (char.IsLetter(str.m_current))
					{
						result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_UnknowDateTimeWord", str.Index);
						return false;
					}
					if (Environment.GetCompatibilityFlag(CompatibilityFlag.DateTimeParseIgnorePunctuation) && (result.flags & ParseFlags.CaptureOffset) == (ParseFlags)0)
					{
						str.GetNext();
						return true;
					}
					if ((str.m_current == '-' || str.m_current == '+') && (result.flags & ParseFlags.TimeZoneUsed) == (ParseFlags)0)
					{
						int index2 = str.Index;
						if (DateTimeParse.ParseTimeZone(ref str, ref result.timeZoneOffset))
						{
							result.flags |= ParseFlags.TimeZoneUsed;
							return true;
						}
						str.Index = index2;
					}
					if (DateTimeParse.VerifyValidPunctuation(ref str))
					{
						return true;
					}
					result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
					return false;
				}
				case TokenType.HebrewNumber:
				{
					int index;
					char current;
					if (num < 100)
					{
						dtok.num = num;
						raw.AddNumber(dtok.num);
						TokenType separatorToken4 = str.GetSeparatorToken(dtfi, out index, out current);
						if (separatorToken4 <= TokenType.SEP_Space)
						{
							if (separatorToken4 == TokenType.SEP_End)
							{
								dtok.dtt = DateTimeParse.DTT.NumEnd;
								break;
							}
							if (separatorToken4 != TokenType.SEP_Space)
							{
								goto IL_695;
							}
						}
						else
						{
							if (separatorToken4 != TokenType.SEP_Date)
							{
								if (separatorToken4 != TokenType.SEP_DateOrOffset)
								{
									goto IL_695;
								}
								if (DateTimeParse.dateParsingStates[(int)dps][4] == DateTimeParse.DS.ERROR && DateTimeParse.dateParsingStates[(int)dps][3] > DateTimeParse.DS.ERROR)
								{
									str.Index = index;
									str.m_current = current;
									dtok.dtt = DateTimeParse.DTT.NumSpace;
									break;
								}
								dtok.dtt = DateTimeParse.DTT.NumDatesep;
								break;
							}
						}
						dtok.dtt = DateTimeParse.DTT.NumDatesep;
						break;
						IL_695:
						result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
						return false;
					}
					if (raw.year != -1)
					{
						result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
						return false;
					}
					raw.year = num;
					TokenType separatorToken5 = str.GetSeparatorToken(dtfi, out index, out current);
					if (separatorToken5 != TokenType.SEP_End)
					{
						if (separatorToken5 != TokenType.SEP_Space)
						{
							if (separatorToken5 == TokenType.SEP_DateOrOffset)
							{
								if (DateTimeParse.dateParsingStates[(int)dps][12] > DateTimeParse.DS.ERROR)
								{
									str.Index = index;
									str.m_current = current;
									dtok.dtt = DateTimeParse.DTT.YearSpace;
									break;
								}
							}
							result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
							return false;
						}
						dtok.dtt = DateTimeParse.DTT.YearSpace;
					}
					else
					{
						dtok.dtt = DateTimeParse.DTT.YearEnd;
					}
					break;
				}
				case TokenType.JapaneseEraToken:
				{
					result.calendar = JapaneseCalendar.GetDefaultInstance();
					dtfi = DateTimeFormatInfo.GetJapaneseCalendarDTFI();
					if (result.era == -1)
					{
						result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
						return false;
					}
					result.era = num;
					dtok.dtt = DateTimeParse.DTT.Era;
					break;
				}
				case TokenType.TEraToken:
				{
					result.calendar = TaiwanCalendar.GetDefaultInstance();
					dtfi = DateTimeFormatInfo.GetTaiwanCalendarDTFI();
					if (result.era == -1)
					{
						result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
						return false;
					}
					result.era = num;
					dtok.dtt = DateTimeParse.DTT.Era;
					break;
				}
			}
			return true;
		}
コード例 #2
0
ファイル: DateTimeParse.cs プロジェクト: ChuangYang/coreclr
        [System.Security.SecuritySafeCritical]  // auto-generated
        private static Boolean Lex(DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi, DateTimeStyles styles)
        {

            TokenType tokenType;
            int tokenValue;
            int indexBeforeSeparator;
            char charBeforeSeparator;

            TokenType sep;
            dtok.dtt = DTT.Unk;     // Assume the token is unkown.

            str.GetRegularToken(out tokenType, out tokenValue, dtfi);

#if _LOGGING
            // Builds with _LOGGING defined (x86dbg, amd64chk, etc) support tracing
            // Set the following internal-only/unsupported environment variables to enable DateTime tracing to the console:
            //
            // COMPlus_LogEnable=1
            // COMPlus_LogToConsole=1
            // COMPlus_LogLevel=9
            // COMPlus_ManagedLogFacility=0x00001000
            if (_tracingEnabled) {
                BCLDebug.Trace("DATETIME", "[DATETIME] Lex({0})\tpos:{1}({2}), {3}, DS.{4}", Hex(str.Value),
                               str.Index, Hex(str.m_current), tokenType, dps);
            }
#endif // _LOGGING

            // Look at the regular token.
            switch (tokenType) {
                case TokenType.NumberToken:
                case TokenType.YearNumberToken:
                    if (raw.numCount == 3 || tokenValue == -1) {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        LexTraceExit("0010", dps);
                        return false;
                    }
                    //
                    // This is a digit.
                    //
                    // If the previous parsing state is DS.T_NNt (like 12:01), and we got another number,
                    // so we will have a terminal state DS.TX_NNN (like 12:01:02).
                    // If the previous parsing state is DS.T_Nt (like 12:), and we got another number,
                    // so we will have a terminal state DS.TX_NN (like 12:01).
                    //
                    // Look ahead to see if the following character is a decimal point or timezone offset.
                    // This enables us to parse time in the forms of:
                    //  "11:22:33.1234" or "11:22:33-08".
                    if (dps == DS.T_NNt) {
                        if ((str.Index < str.len - 1)) {
                            char nextCh = str.Value[str.Index];
                            if (nextCh == '.') {
                                // While ParseFraction can fail, it just means that there were no digits after
                                // the dot. In this case ParseFraction just removes the dot. This is actually
                                // valid for cultures like Albanian, that join the time marker to the time with
                                // with a dot: e.g. "9:03.MD"
                                ParseFraction(ref str, out raw.fraction);
                            }
                        }
                    }
                    if (dps == DS.T_NNt || dps == DS.T_Nt) {
                        if ((str.Index < str.len - 1)) {
                            if (false == HandleTimeZone(ref str, ref result))
                            {
                                LexTraceExit("0020 (value like \"12:01\" or \"12:\" followed by a non-TZ number", dps);
                                return false;
                            }
                        }                        
                    }

                    dtok.num = tokenValue;
                    if (tokenType == TokenType.YearNumberToken)
                    {
                        if (raw.year == -1)
                        {
                            raw.year = tokenValue;
                            //
                            // If we have number which has 3 or more digits (like "001" or "0001"),
                            // we assume this number is a year. Save the currnet raw.numCount in
                            // raw.year.
                            //
                            switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator)) {
                                case TokenType.SEP_End:
                                    dtok.dtt     = DTT.YearEnd;
                                    break;
                                case TokenType.SEP_Am:
                                case TokenType.SEP_Pm:
                                    if (raw.timeMark == TM.NotSet) {
                                        raw.timeMark = (sep == TokenType.SEP_Am ? TM.AM : TM.PM);
                                        dtok.dtt    = DTT.YearSpace;
                                    } else {
                                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                        LexTraceExit("0030 (TM.AM/TM.PM Happened more than 1x)", dps);
                                    }
                                    break;
                                case TokenType.SEP_Space:
                                    dtok.dtt    = DTT.YearSpace;
                                    break;
                                case TokenType.SEP_Date:
                                    dtok.dtt     = DTT.YearDateSep;
                                    break;
                                case TokenType.SEP_Time:
                                    if (!raw.hasSameDateAndTimeSeparators)
                                    {
                                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                        LexTraceExit("0040 (Invalid separator after number)", dps);
                                        return false;
                                    }

                                    // we have the date and time separators are same and getting a year number, then change the token to YearDateSep as 
                                    // we are sure we are not parsing time.
                                    dtok.dtt = DTT.YearDateSep;
                                    break;
                                case TokenType.SEP_DateOrOffset:
                                    // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
                                    // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
                                    if ((dateParsingStates[(int)dps][(int) DTT.YearDateSep] == DS.ERROR) 
                                        && (dateParsingStates[(int)dps][(int) DTT.YearSpace] > DS.ERROR)) {
                                        str.Index = indexBeforeSeparator;
                                        str.m_current = charBeforeSeparator;
                                        dtok.dtt = DTT.YearSpace;
                                    }
                                    else {
                                        dtok.dtt = DTT.YearDateSep;
                                    }
                                    break;                                    
                                case TokenType.SEP_YearSuff:
                                case TokenType.SEP_MonthSuff:
                                case TokenType.SEP_DaySuff:
                                    dtok.dtt    = DTT.NumDatesuff;
                                    dtok.suffix = sep;
                                    break;
                                case TokenType.SEP_HourSuff:
                                case TokenType.SEP_MinuteSuff:
                                case TokenType.SEP_SecondSuff:
                                    dtok.dtt    = DTT.NumTimesuff;
                                    dtok.suffix = sep;
                                    break;
                                default:
                                    // Invalid separator after number number.
                                    result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                    LexTraceExit("0040 (Invalid separator after number)", dps);
                                    return false;
                            }
                            //
                            // Found the token already. Return now.
                            //
                            LexTraceExit("0050 (success)", dps);
                            return true;
                        }
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        LexTraceExit("0060", dps);
                        return false;
                    }
                    switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator))
                    {
                        //
                        // Note here we check if the numCount is less than three.
                        // When we have more than three numbers, it will be caught as error in the state machine.
                        //
                        case TokenType.SEP_End:
                            dtok.dtt = DTT.NumEnd;
                            raw.AddNumber(dtok.num);
                            break;
                        case TokenType.SEP_Am:
                        case TokenType.SEP_Pm:
                            if (raw.timeMark == TM.NotSet) {
                                raw.timeMark = (sep == TokenType.SEP_Am ? TM.AM : TM.PM);
                                dtok.dtt = DTT.NumAmpm;
                                // Fix AM/PM parsing case, e.g. "1/10 5 AM"
                                if (dps == DS.D_NN 
#if !FEATURE_CORECLR
                                    && enableAmPmParseAdjustment
#endif
                                )
                                {
                                    if (!ProcessTerminaltState(DS.DX_NN, ref result, ref styles, ref raw, dtfi))
                                    {
                                        return false;
                                    }
                                }

                                raw.AddNumber(dtok.num);
                            } else {
                                result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                break;
                            }
                            if (dps == DS.T_NNt || dps == DS.T_Nt) {
                                if (false == HandleTimeZone(ref str, ref result))
                                {
                                    LexTraceExit("0070 (HandleTimeZone returned false)", dps);
                                    return false;
                                }
                            }
                            break;
                        case TokenType.SEP_Space:
                            dtok.dtt = DTT.NumSpace;
                            raw.AddNumber(dtok.num);
                            break;
                        case TokenType.SEP_Date:
                            dtok.dtt = DTT.NumDatesep;
                            raw.AddNumber(dtok.num);
                            break;
                        case TokenType.SEP_DateOrOffset:
                            // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
                            // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
                            if ((dateParsingStates[(int)dps][(int) DTT.NumDatesep] == DS.ERROR) 
                                && (dateParsingStates[(int)dps][(int) DTT.NumSpace] > DS.ERROR)) {
                                str.Index = indexBeforeSeparator;
                                str.m_current = charBeforeSeparator;
                                dtok.dtt = DTT.NumSpace;
                            }
                            else {                                
                                dtok.dtt = DTT.NumDatesep;
                            }
                            raw.AddNumber(dtok.num);
                            break;                            
                        case TokenType.SEP_Time:
                            if (raw.hasSameDateAndTimeSeparators &&
                                (dps == DS.D_Y || dps == DS.D_YN || dps == DS.D_YNd || dps == DS.D_YM || dps == DS.D_YMd))
                            {
                                // we are parsing a date and we have the time separator same as date separator, so we mark the token as date separator
                                dtok.dtt = DTT.NumDatesep;
                                raw.AddNumber(dtok.num);
                                break;
                            }
                            dtok.dtt = DTT.NumTimesep;
                            raw.AddNumber(dtok.num);
                            break;
                        case TokenType.SEP_YearSuff:
                            try {
                                dtok.num = dtfi.Calendar.ToFourDigitYear(tokenValue);
                            }
                            catch (ArgumentOutOfRangeException e) {
                                result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", e);
                                LexTraceExit("0075 (Calendar.ToFourDigitYear failed)", dps);
                                return false;
                            }   
                            dtok.dtt    = DTT.NumDatesuff;
                            dtok.suffix = sep;
                            break;
                        case TokenType.SEP_MonthSuff:
                        case TokenType.SEP_DaySuff:
                            dtok.dtt    = DTT.NumDatesuff;
                            dtok.suffix = sep;
                            break;
                        case TokenType.SEP_HourSuff:
                        case TokenType.SEP_MinuteSuff:
                        case TokenType.SEP_SecondSuff:
                            dtok.dtt    = DTT.NumTimesuff;
                            dtok.suffix = sep;
                            break;
                        case TokenType.SEP_LocalTimeMark:
                            dtok.dtt = DTT.NumLocalTimeMark;
                            raw.AddNumber(dtok.num);
                            break;
                        default:
                            // Invalid separator after number number.
                            result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                            LexTraceExit("0080", dps);
                            return false;
                    }
                    break;
                case TokenType.HebrewNumber:
                    if (tokenValue >= 100) {
                        // This is a year number
                        if (raw.year == -1) {
                            raw.year = tokenValue;
                            //
                            // If we have number which has 3 or more digits (like "001" or "0001"),
                            // we assume this number is a year. Save the currnet raw.numCount in
                            // raw.year.
                            //
                            switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator)) {
                                case TokenType.SEP_End:
                                    dtok.dtt = DTT.YearEnd;
                                    break;
                                case TokenType.SEP_Space:
                                    dtok.dtt = DTT.YearSpace;
                                    break;
                                case TokenType.SEP_DateOrOffset:
                                    // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
                                    // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
                                    if (dateParsingStates[(int)dps][(int) DTT.YearSpace] > DS.ERROR) {
                                        str.Index = indexBeforeSeparator;
                                        str.m_current = charBeforeSeparator;
                                        dtok.dtt = DTT.YearSpace;
                                        break;
                                    }
                                    goto default;
                                default:
                                    // Invalid separator after number number.
                                    result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                    LexTraceExit("0090", dps);
                                    return false;
                            }
                        } else {
                            // Invalid separator after number number.
                            result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                            LexTraceExit("0100", dps);
                            return false;
                        }
                    } else {
                        // This is a day number
                        dtok.num = tokenValue;
                        raw.AddNumber(dtok.num);

                        switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator)) {
                            //
                            // Note here we check if the numCount is less than three.
                            // When we have more than three numbers, it will be caught as error in the state machine.
                            //
                            case TokenType.SEP_End:
                                dtok.dtt = DTT.NumEnd;
                                break;
                            case TokenType.SEP_Space:
                            case TokenType.SEP_Date:
                                dtok.dtt = DTT.NumDatesep;
                                break;
                            case TokenType.SEP_DateOrOffset:
                                // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
                                // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
                                if ((dateParsingStates[(int)dps][(int) DTT.NumDatesep] == DS.ERROR) 
                                    && (dateParsingStates[(int)dps][(int) DTT.NumSpace] > DS.ERROR)) {
                                    str.Index = indexBeforeSeparator;
                                    str.m_current = charBeforeSeparator;
                                    dtok.dtt = DTT.NumSpace;
                                }
                                else {                                
                                    dtok.dtt = DTT.NumDatesep;
                                }
                                break;
                            default:
                                // Invalid separator after number number.
                                result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                LexTraceExit("0110", dps);
                                return false;
                        }
                    }
                    break;
                case TokenType.DayOfWeekToken:
                    if (raw.dayOfWeek == -1)
                    {
                        //
                        // This is a day of week name.
                        //
                        raw.dayOfWeek = tokenValue;
                        dtok.dtt = DTT.DayOfWeek;
                    } else {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        LexTraceExit("0120 (DayOfWeek seen more than 1x)", dps);
                        return false;
                    }
                    break;
                case TokenType.MonthToken:
                    if (raw.month == -1)
                    {
                        //
                        // This is a month name
                        //
                        switch(sep=str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator))
                        {
                            case TokenType.SEP_End:
                                dtok.dtt = DTT.MonthEnd;
                                break;
                            case TokenType.SEP_Space:
                                dtok.dtt = DTT.MonthSpace;
                                break;
                            case TokenType.SEP_Date:
                                dtok.dtt = DTT.MonthDatesep;
                                break;
                            case TokenType.SEP_Time:
                                if (!raw.hasSameDateAndTimeSeparators)
                                {
                                    result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                    LexTraceExit("0130 (Invalid separator after month name)", dps);
                                    return false;
                                }

                                // we have the date and time separators are same and getting a Month name, then change the token to MonthDatesep as 
                                // we are sure we are not parsing time.
                                dtok.dtt = DTT.MonthDatesep;
                                break;
                            case TokenType.SEP_DateOrOffset:
                                // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
                                // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
                                if ((dateParsingStates[(int)dps][(int) DTT.MonthDatesep] == DS.ERROR) 
                                    && (dateParsingStates[(int)dps][(int) DTT.MonthSpace] > DS.ERROR)) {
                                    str.Index = indexBeforeSeparator;
                                    str.m_current = charBeforeSeparator;
                                    dtok.dtt = DTT.MonthSpace;
                                }
                                else {                                
                                    dtok.dtt = DTT.MonthDatesep;
                                }
                                break;
                            default:
                                //Invalid separator after month name
                                result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                LexTraceExit("0130 (Invalid separator after month name)", dps);
                                return false;
                        }
                        raw.month = tokenValue;
                    }  else {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        LexTraceExit("0140 (MonthToken seen more than 1x)", dps);
                        return false;
                    }
                    break;
                case TokenType.EraToken:
                    if (result.era != -1) {
                        result.era = tokenValue;
                        dtok.dtt = DTT.Era;
                    } else {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        LexTraceExit("0150 (EraToken seen when result.era already set)", dps);
                        return false;
                    }
                    break;
                case TokenType.JapaneseEraToken:
                    // Special case for Japanese.  We allow Japanese era name to be used even if the calendar is not Japanese Calendar.
                    result.calendar = JapaneseCalendar.GetDefaultInstance();
                    dtfi = DateTimeFormatInfo.GetJapaneseCalendarDTFI();
                    if (result.era != -1) {
                        result.era = tokenValue;
                        dtok.dtt = DTT.Era;
                    } else {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        LexTraceExit("0160 (JapaneseEraToken seen when result.era already set)", dps);
                        return false;
                    }
                    break;
                case TokenType.TEraToken:
                    result.calendar = TaiwanCalendar.GetDefaultInstance();
                    dtfi = DateTimeFormatInfo.GetTaiwanCalendarDTFI();
                    if (result.era != -1) {
                        result.era = tokenValue;
                        dtok.dtt = DTT.Era;
                    } else {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        LexTraceExit("0170 (TEraToken seen when result.era already set)", dps);
                        return false;
                    }
                    break;
                case TokenType.TimeZoneToken:
                    //
                    // This is a timezone designator
                    //
                    // NOTENOTE : for now, we only support "GMT" and "Z" (for Zulu time).
                    //
                    if ((result.flags & ParseFlags.TimeZoneUsed) != 0) {
                        // Should not have two timezone offsets.
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        LexTraceExit("0180 (seen GMT or Z more than 1x)", dps);
                        return false;
                    }
                    dtok.dtt = DTT.TimeZone;
                    result.flags |= ParseFlags.TimeZoneUsed;
                    result.timeZoneOffset = new TimeSpan(0);
                    result.flags |= ParseFlags.TimeZoneUtc;
                    break;
                case TokenType.EndOfString:
                    dtok.dtt = DTT.End;
                    break;
                case TokenType.DateWordToken:
                case TokenType.IgnorableSymbol:
                    // Date words and ignorable symbols can just be skipped over
                    break;
                case TokenType.Am:
                case TokenType.Pm:
                    if (raw.timeMark == TM.NotSet) {
                        raw.timeMark = (TM)tokenValue;
                    } else {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        LexTraceExit("0190 (AM/PM timeMark already set)", dps);
                        return false;
                    }
                    break;
                case TokenType.UnknownToken:
                    if (Char.IsLetter(str.m_current)) {
                        result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_UnknowDateTimeWord",  str.Index);
                        LexTraceExit("0200", dps);
                        return (false);
                    }

#if !FEATURE_CORECLR                    
                    // If DateTimeParseIgnorePunctuation is defined, we want to have the V1.1 behavior of just
                    // ignoring any unrecognized punctuation and moving on to the next character
                    if (Environment.GetCompatibilityFlag(CompatibilityFlag.DateTimeParseIgnorePunctuation) && ((result.flags & ParseFlags.CaptureOffset) == 0)) {
                        str.GetNext();
                        LexTraceExit("0210 (success)", dps);
                        return true;
                    }
#endif // FEATURE_CORECLR
                    
                    if ((str.m_current == '-' || str.m_current == '+') && ((result.flags & ParseFlags.TimeZoneUsed) == 0)) {
                        Int32 originalIndex = str.Index;
                        if (ParseTimeZone(ref str, ref result.timeZoneOffset)) {
                            result.flags |= ParseFlags.TimeZoneUsed;
                            LexTraceExit("0220 (success)", dps);
                            return true;
                        }
                        else {
                            // Time zone parse attempt failed. Fall through to punctuation handling.
                            str.Index = originalIndex;
                        }                                                
                    }
                    
                    // Visual Basic implements string to date conversions on top of DateTime.Parse:
                    //   CDate("#10/10/95#")
                    //
                    if (VerifyValidPunctuation(ref str)) {
                        LexTraceExit("0230 (success)", dps);
                        return true;                                
                    }

                    result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                    LexTraceExit("0240", dps);
                    return false;
            }

            LexTraceExit("0250 (success)", dps);
            return true;
        }
コード例 #3
0
		private static bool ProcessDateTimeSuffix(ref DateTimeResult result, ref DateTimeRawInfo raw, ref DateTimeToken dtok)
		{
			TokenType suffix = dtok.suffix;
			if (suffix <= TokenType.SEP_DaySuff)
			{
				if (suffix != TokenType.SEP_YearSuff)
				{
					if (suffix != TokenType.SEP_MonthSuff)
					{
						if (suffix == TokenType.SEP_DaySuff)
						{
							if ((result.flags & ParseFlags.HaveDay) != (ParseFlags)0)
							{
								return false;
							}
							result.flags |= ParseFlags.HaveDay;
							result.Day = dtok.num;
						}
					}
					else
					{
						if ((result.flags & ParseFlags.HaveMonth) != (ParseFlags)0)
						{
							return false;
						}
						result.flags |= ParseFlags.HaveMonth;
						result.Month = (raw.month = dtok.num);
					}
				}
				else
				{
					if ((result.flags & ParseFlags.HaveYear) != (ParseFlags)0)
					{
						return false;
					}
					result.flags |= ParseFlags.HaveYear;
					result.Year = (raw.year = dtok.num);
				}
			}
			else
			{
				if (suffix != TokenType.SEP_HourSuff)
				{
					if (suffix != TokenType.SEP_MinuteSuff)
					{
						if (suffix == TokenType.SEP_SecondSuff)
						{
							if ((result.flags & ParseFlags.HaveSecond) != (ParseFlags)0)
							{
								return false;
							}
							result.flags |= ParseFlags.HaveSecond;
							result.Second = dtok.num;
						}
					}
					else
					{
						if ((result.flags & ParseFlags.HaveMinute) != (ParseFlags)0)
						{
							return false;
						}
						result.flags |= ParseFlags.HaveMinute;
						result.Minute = dtok.num;
					}
				}
				else
				{
					if ((result.flags & ParseFlags.HaveHour) != (ParseFlags)0)
					{
						return false;
					}
					result.flags |= ParseFlags.HaveHour;
					result.Hour = dtok.num;
				}
			}
			return true;
		}
コード例 #4
0
ファイル: DateTimeParse.cs プロジェクト: ChuangYang/coreclr
        //
        // A date suffix is found, use this method to put the number into the result.
        //
        private static bool ProcessDateTimeSuffix(ref DateTimeResult result, ref DateTimeRawInfo raw, ref DateTimeToken dtok)
        {
            switch (dtok.suffix)
            {
                case TokenType.SEP_YearSuff:
                    if ((result.flags & ParseFlags.HaveYear) != 0) {
                        return false;
                    }
                    result.flags |= ParseFlags.HaveYear;
                    result.Year = raw.year = dtok.num;
                    break;
                case TokenType.SEP_MonthSuff:
                    if ((result.flags & ParseFlags.HaveMonth) != 0) {
                        return false;
                    }
                    result.flags |= ParseFlags.HaveMonth;
                    result.Month= raw.month = dtok.num;
                    break;
                case TokenType.SEP_DaySuff:
                    if ((result.flags & ParseFlags.HaveDay) != 0) {
                        return false;
                    }
                    result.flags |= ParseFlags.HaveDay;
                    result.Day  = dtok.num;
                    break;
                case TokenType.SEP_HourSuff:
                    if ((result.flags & ParseFlags.HaveHour) != 0) {
                        return false;
                    }
                    result.flags |= ParseFlags.HaveHour;
                    result.Hour = dtok.num;
                    break;
                case TokenType.SEP_MinuteSuff:
                    if ((result.flags & ParseFlags.HaveMinute) != 0) {
                        return false;
                    }
                    result.flags |= ParseFlags.HaveMinute;
                    result.Minute = dtok.num;
                    break;
                case TokenType.SEP_SecondSuff:
                    if ((result.flags & ParseFlags.HaveSecond) != 0) {
                        return false;
                    }
                    result.flags |= ParseFlags.HaveSecond;
                    result.Second = dtok.num;
                    break;
            }
            return true;

        }
コード例 #5
0
ファイル: DateTimeParse.cs プロジェクト: ChuangYang/coreclr
        [System.Security.SecuritySafeCritical]  // auto-generated
        internal static bool TryParse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles, ref DateTimeResult result) {
            if (s == null) {
                result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "s");
                return false;
            }
            if (s.Length == 0) {
                result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                return false;
            }

            Contract.Assert(dtfi != null, "dtfi == null");

#if _LOGGING
            DTFITrace(dtfi);
#endif

            DateTime time;
            //
            // First try the predefined format.
            //

            DS dps             = DS.BEGIN;     // Date Parsing State.
            bool reachTerminalState = false;

            DateTimeToken   dtok    = new DateTimeToken();      // The buffer to store the parsing token.
            dtok.suffix = TokenType.SEP_Unk;
            DateTimeRawInfo raw     = new DateTimeRawInfo();    // The buffer to store temporary parsing information.
            unsafe {
                Int32 * numberPointer = stackalloc Int32[3];
                raw.Init(numberPointer);
            }
            raw.hasSameDateAndTimeSeparators = dtfi.DateSeparator.Equals(dtfi.TimeSeparator, StringComparison.Ordinal);

            result.calendar = dtfi.Calendar;
            result.era = Calendar.CurrentEra;

            //
            // The string to be parsed. Use a __DTString wrapper so that we can trace the index which
            // indicates the begining of next token.
            //
            __DTString str = new __DTString(s, dtfi);

            str.GetNext();

            //
            // The following loop will break out when we reach the end of the str.
            //
            do {
                //
                // Call the lexer to get the next token.
                //
                // If we find a era in Lex(), the era value will be in raw.era.
                if (!Lex(dps, ref str, ref dtok, ref raw, ref result, ref dtfi, styles))
                {
                    TPTraceExit("0000", dps);
                    return false;
                }

                //
                // If the token is not unknown, process it.
                // Otherwise, just discard it.
                //
                if (dtok.dtt != DTT.Unk)
                {
                    //
                    // Check if we got any CJK Date/Time suffix.
                    // Since the Date/Time suffix tells us the number belongs to year/month/day/hour/minute/second,
                    // store the number in the appropriate field in the result.
                    //
                    if (dtok.suffix != TokenType.SEP_Unk)
                    {
                        if (!ProcessDateTimeSuffix(ref result, ref raw, ref dtok)) {
                            result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                            TPTraceExit("0010", dps);
                            return false;
                        }

                        dtok.suffix = TokenType.SEP_Unk;  // Reset suffix to SEP_Unk;
                    }

                    if (dtok.dtt == DTT.NumLocalTimeMark) {
                        if (dps == DS.D_YNd || dps == DS.D_YN) {
                            // Consider this as ISO 8601 format:
                            // "yyyy-MM-dd'T'HH:mm:ss"                 1999-10-31T02:00:00
                            TPTraceExit("0020", dps);
                            return (ParseISO8601(ref raw, ref str, styles, ref result));
                        }
                        else {
                            result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                            TPTraceExit("0030", dps);
                            return false;
                        }
                    }

                    if (raw.hasSameDateAndTimeSeparators)
                    {
                        if (dtok.dtt == DTT.YearEnd || dtok.dtt == DTT.YearSpace || dtok.dtt == DTT.YearDateSep)
                        {
                            // When time and date separators are same and we are hitting a year number while the first parsed part of the string was recognized 
                            // as part of time (and not a date) DS.T_Nt, DS.T_NNt then change the state to be a date so we try to parse it as a date instead
                            if (dps == DS.T_Nt)
                            {
                                dps = DS.D_Nd;
                            }
                            if (dps == DS.T_NNt)
                            {
                                dps = DS.D_NNd;
                            }
                        }

                        bool atEnd = str.AtEnd();
                        if (dateParsingStates[(int)dps][(int)dtok.dtt] == DS.ERROR || atEnd)
                        {
                            switch (dtok.dtt)
                            {
                                // we have the case of Serbia have dates in forms 'd.M.yyyy.' so we can expect '.' after the date parts. 
                                // changing the token to end with space instead of Date Separator will avoid failing the parsing.

                                case DTT.YearDateSep: dtok.dtt = atEnd ? DTT.YearEnd : DTT.YearSpace; break;
                                case DTT.NumDatesep: dtok.dtt = atEnd ? DTT.NumEnd : DTT.NumSpace; break;
                                case DTT.NumTimesep: dtok.dtt = atEnd ? DTT.NumEnd : DTT.NumSpace; break;
                                case DTT.MonthDatesep: dtok.dtt = atEnd ? DTT.MonthEnd : DTT.MonthSpace; break;
                            }
                        }
                    }

                    //
                    // Advance to the next state, and continue
                    //
                    dps = dateParsingStates[(int)dps][(int)dtok.dtt];
                    
                    if (dps == DS.ERROR)
                    {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        TPTraceExit("0040 (invalid state transition)", dps);
                        return false;
                    }
                    else if (dps > DS.ERROR)
                    {
                        if ((dtfi.FormatFlags & DateTimeFormatFlags.UseHebrewRule) != 0) {
                            if (!ProcessHebrewTerminalState(dps, ref result, ref styles, ref raw, dtfi)) {
                                TPTraceExit("0050 (ProcessHebrewTerminalState)", dps);
                                return false;
                            }
                        } else {
                            if (!ProcessTerminaltState(dps, ref result, ref styles, ref raw, dtfi)) {
                                TPTraceExit("0060 (ProcessTerminaltState)", dps);
                                return false;
                            }
                        }
                        reachTerminalState = true;

                        //
                        // If we have reached a terminal state, start over from DS.BEGIN again.
                        // For example, when we parsed "1999-12-23 13:30", we will reach a terminal state at "1999-12-23",
                        // and we start over so we can continue to parse "12:30".
                        //
                        dps = DS.BEGIN;
                    }
                }
            } while (dtok.dtt != DTT.End && dtok.dtt != DTT.NumEnd && dtok.dtt != DTT.MonthEnd);

            if (!reachTerminalState) {
                result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                TPTraceExit("0070 (did not reach terminal state)", dps);
                return false;
            }

            AdjustTimeMark(dtfi, ref raw);
            if (!AdjustHour(ref result.Hour, raw.timeMark)) {
                result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                TPTraceExit("0080 (AdjustHour)", dps);
                return false;
            }

            // Check if the parased string only contains hour/minute/second values.
            bool bTimeOnly = (result.Year == -1 && result.Month == -1 && result.Day == -1);

            //
            // Check if any year/month/day is missing in the parsing string.
            // If yes, get the default value from today's date.
            //
            if (!CheckDefaultDateTime(ref result, ref result.calendar, styles)) {
                TPTraceExit("0090 (failed to fill in missing year/month/day defaults)", dps);
                return false;
            }

            if (!result.calendar.TryToDateTime(result.Year, result.Month, result.Day,
                    result.Hour, result.Minute, result.Second, 0, result.era, out time)) {
                result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
                TPTraceExit("0100 (result.calendar.TryToDateTime)", dps);
                return false;
            }
            if (raw.fraction > 0) {
                time = time.AddTicks((long)Math.Round(raw.fraction * Calendar.TicksPerSecond));
            }

            //
            // We have to check day of week before we adjust to the time zone.
            // Otherwise, the value of day of week may change after adjustting to the time zone.
            //
            if (raw.dayOfWeek != -1) {
                //
                // Check if day of week is correct.
                //
                if (raw.dayOfWeek != (int)result.calendar.GetDayOfWeek(time)) {
                    result.SetFailure(ParseFailureKind.Format, "Format_BadDayOfWeek", null);
                    TPTraceExit("0110 (dayOfWeek check)", dps);
                    return false;
                }
            }

            result.parsedDate = time;

            if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly)) {
                TPTraceExit("0120 (DetermineTimeZoneAdjustments)", dps);
                return false;
            }
            TPTraceExit("0130 (success)", dps);
            return true;
        }
コード例 #6
0
            //
            // This is the lexer. Check the character at the current index, and put the found token in dtok and
            // some raw date/time information in raw.
            //
            private static Boolean Lex(
                DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi, DateTimeStyles styles)
            {
                TokenType tokenType;
                int tokenValue;
                int indexBeforeSeparator;
                char charBeforeSeparator;

                TokenType sep;
                dtok.dtt = DTT.Unk;     // Assume the token is unkown.

                str.GetRegularToken(out tokenType, out tokenValue, dtfi);


                // Look at the regular token.
                switch (tokenType)
                {
                    case TokenType.NumberToken:
                    case TokenType.YearNumberToken:
                        if (raw.numCount == 3 || tokenValue == -1)
                        {
                            result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                            return false;
                        }
                        //
                        // This is a digit.
                        //
                        // If the previous parsing state is DS.T_NNt (like 12:01), and we got another number,
                        // so we will have a terminal state DS.TX_NNN (like 12:01:02).
                        // If the previous parsing state is DS.T_Nt (like 12:), and we got another number,
                        // so we will have a terminal state DS.TX_NN (like 12:01).
                        //
                        // Look ahead to see if the following character is a decimal point or timezone offset.
                        // This enables us to parse time in the forms of:
                        //  "11:22:33.1234" or "11:22:33-08".
                        if (dps == DS.T_NNt)
                        {
                            if ((str.Index < str.len - 1))
                            {
                                char nextCh = str.Value[str.Index];
                                if (nextCh == '.')
                                {
                                    // While ParseFraction can fail, it just means that there were no digits after
                                    // the dot. In this case ParseFraction just removes the dot. This is actually
                                    // valid for cultures like Albanian, that join the time marker to the time with
                                    // with a dot: e.g. "9:03.MD"
                                    ParseFraction(ref str, out raw.fraction);
                                }
                            }
                        }
                        if (dps == DS.T_NNt || dps == DS.T_Nt)
                        {
                            if ((str.Index < str.len - 1))
                            {
                                if (false == HandleTimeZone(ref str, ref result))
                                {
                                    return false;
                                }
                            }
                        }

                        dtok.num = tokenValue;
                        if (tokenType == TokenType.YearNumberToken)
                        {
                            if (raw.year == -1)
                            {
                                raw.year = tokenValue;
                                //
                                // If we have number which has 3 or more digits (like "001" or "0001"),
                                // we assume this number is a year. Save the currnet raw.numCount in
                                // raw.year.
                                //
                                switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator))
                                {
                                    case TokenType.SEP_End:
                                        dtok.dtt = DTT.YearEnd;
                                        break;
                                    case TokenType.SEP_Am:
                                    case TokenType.SEP_Pm:
                                        if (raw.timeMark == TM.NotSet)
                                        {
                                            raw.timeMark = (sep == TokenType.SEP_Am ? TM.AM : TM.PM);
                                            dtok.dtt = DTT.YearSpace;
                                        }
                                        else
                                        {
                                            result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                                        }
                                        break;
                                    case TokenType.SEP_Space:
                                        dtok.dtt = DTT.YearSpace;
                                        break;
                                    case TokenType.SEP_Date:
                                        dtok.dtt = DTT.YearDateSep;
                                        break;
                                    case TokenType.SEP_Time:
                                        if (!raw.hasSameDateAndTimeSeparators)
                                        {
                                            result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                                            return false;
                                        }

                                        // we have the date and time separators are same and getting a year number, then change the token to YearDateSep as 
                                        // we are sure we are not parsing time.
                                        dtok.dtt = DTT.YearDateSep;
                                        break;
                                    case TokenType.SEP_DateOrOffset:
                                        // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
                                        // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
                                        if ((DateParsingStates(dps, DTT.YearDateSep) == DS.ERROR)
                                            && (DateParsingStates(dps, DTT.YearSpace) > DS.ERROR))
                                        {
                                            str.Index = indexBeforeSeparator;
                                            str.m_current = charBeforeSeparator;
                                            dtok.dtt = DTT.YearSpace;
                                        }
                                        else
                                        {
                                            dtok.dtt = DTT.YearDateSep;
                                        }
                                        break;
                                    case TokenType.SEP_YearSuff:
                                    case TokenType.SEP_MonthSuff:
                                    case TokenType.SEP_DaySuff:
                                        dtok.dtt = DTT.NumDatesuff;
                                        dtok.suffix = sep;
                                        break;
                                    case TokenType.SEP_HourSuff:
                                    case TokenType.SEP_MinuteSuff:
                                    case TokenType.SEP_SecondSuff:
                                        dtok.dtt = DTT.NumTimesuff;
                                        dtok.suffix = sep;
                                        break;
                                    default:
                                        // Invalid separator after number number.
                                        result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                                        return false;
                                }
                                return true;
                            }
                            result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                            return false;
                        }
                        switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator))
                        {
                            //
                            // Note here we check if the numCount is less than three.
                            // When we have more than three numbers, it will be caught as error in the state machine.
                            //
                            case TokenType.SEP_End:
                                dtok.dtt = DTT.NumEnd;
                                raw.AddNumber(dtok.num);
                                break;
                            case TokenType.SEP_Am:
                            case TokenType.SEP_Pm:
                                if (raw.timeMark == TM.NotSet)
                                {
                                    raw.timeMark = (sep == TokenType.SEP_Am ? TM.AM : TM.PM);
                                    dtok.dtt = DTT.NumAmpm;
                                    // Fix AM/PM parsing case, e.g. "1/10 5 AM"
                                    if (dps == DS.D_NN)
                                    {
                                        if (!ProcessTerminaltState(DS.DX_NN, ref result, ref styles, ref raw, dtfi))
                                        {
                                            return false;
                                        }
                                    }

                                    raw.AddNumber(dtok.num);
                                }
                                else
                                {
                                    result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                                    break;
                                }
                                if (dps == DS.T_NNt || dps == DS.T_Nt)
                                {
                                    if (false == HandleTimeZone(ref str, ref result))
                                    {
                                        return false;
                                    }
                                }
                                break;
                            case TokenType.SEP_Space:
                                dtok.dtt = DTT.NumSpace;
                                raw.AddNumber(dtok.num);
                                break;
                            case TokenType.SEP_Date:
                                dtok.dtt = DTT.NumDatesep;
                                raw.AddNumber(dtok.num);
                                break;
                            case TokenType.SEP_DateOrOffset:
                                // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
                                // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
                                if ((DateParsingStates(dps, DTT.NumDatesep) == DS.ERROR)
                                    && (DateParsingStates(dps, DTT.NumSpace) > DS.ERROR))
                                {
                                    str.Index = indexBeforeSeparator;
                                    str.m_current = charBeforeSeparator;
                                    dtok.dtt = DTT.NumSpace;
                                }
                                else
                                {
                                    dtok.dtt = DTT.NumDatesep;
                                }
                                raw.AddNumber(dtok.num);
                                break;
                            case TokenType.SEP_Time:
                                if (raw.hasSameDateAndTimeSeparators &&
                                    (dps == DS.D_Y || dps == DS.D_YN || dps == DS.D_YNd || dps == DS.D_YM || dps == DS.D_YMd))
                                {
                                    // we are parsing a date and we have the time separator same as date separator, so we mark the token as date separator
                                    dtok.dtt = DTT.NumDatesep;
                                    raw.AddNumber(dtok.num);
                                    break;
                                }
                                dtok.dtt = DTT.NumTimesep;
                                raw.AddNumber(dtok.num);
                                break;
                            case TokenType.SEP_YearSuff:
                                dtok.num = dtfi.Calendar.ToFourDigitYear(tokenValue);
                                dtok.dtt = DTT.NumDatesuff;
                                dtok.suffix = sep;
                                break;
                            case TokenType.SEP_MonthSuff:
                            case TokenType.SEP_DaySuff:
                                dtok.dtt = DTT.NumDatesuff;
                                dtok.suffix = sep;
                                break;
                            case TokenType.SEP_HourSuff:
                            case TokenType.SEP_MinuteSuff:
                            case TokenType.SEP_SecondSuff:
                                dtok.dtt = DTT.NumTimesuff;
                                dtok.suffix = sep;
                                break;
                            case TokenType.SEP_LocalTimeMark:
                                dtok.dtt = DTT.NumLocalTimeMark;
                                raw.AddNumber(dtok.num);
                                break;
                            default:
                                // Invalid separator after number number.
                                result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                                return false;
                        }
                        break;
                    case TokenType.HebrewNumber:
                        if (tokenValue >= 100)
                        {
                            // This is a year number
                            if (raw.year == -1)
                            {
                                raw.year = tokenValue;
                                //
                                // If we have number which has 3 or more digits (like "001" or "0001"),
                                // we assume this number is a year. Save the currnet raw.numCount in
                                // raw.year.
                                //
                                switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator))
                                {
                                    case TokenType.SEP_End:
                                        dtok.dtt = DTT.YearEnd;
                                        break;
                                    case TokenType.SEP_Space:
                                        dtok.dtt = DTT.YearSpace;
                                        break;
                                    case TokenType.SEP_DateOrOffset:
                                        // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
                                        // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
                                        if (DateParsingStates(dps, DTT.YearSpace) > DS.ERROR)
                                        {
                                            str.Index = indexBeforeSeparator;
                                            str.m_current = charBeforeSeparator;
                                            dtok.dtt = DTT.YearSpace;
                                            break;
                                        }
                                        goto default;
                                    default:
                                        // Invalid separator after number number.
                                        result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                                        return false;
                                }
                            }
                            else
                            {
                                // Invalid separator after number number.
                                result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                                return false;
                            }
                        }
                        else
                        {
                            // This is a day number
                            dtok.num = tokenValue;
                            raw.AddNumber(dtok.num);

                            switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator))
                            {
                                //
                                // Note here we check if the numCount is less than three.
                                // When we have more than three numbers, it will be caught as error in the state machine.
                                //
                                case TokenType.SEP_End:
                                    dtok.dtt = DTT.NumEnd;
                                    break;
                                case TokenType.SEP_Space:
                                case TokenType.SEP_Date:
                                    dtok.dtt = DTT.NumDatesep;
                                    break;
                                case TokenType.SEP_DateOrOffset:
                                    // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
                                    // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
                                    if ((DateParsingStates(dps, DTT.NumDatesep) == DS.ERROR)
                                        && (DateParsingStates(dps, DTT.NumSpace) > DS.ERROR))
                                    {
                                        str.Index = indexBeforeSeparator;
                                        str.m_current = charBeforeSeparator;
                                        dtok.dtt = DTT.NumSpace;
                                    }
                                    else
                                    {
                                        dtok.dtt = DTT.NumDatesep;
                                    }
                                    break;
                                default:
                                    // Invalid separator after number number.
                                    result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                                    return false;
                            }
                        }
                        break;
                    case TokenType.DayOfWeekToken:
                        if (raw.dayOfWeek == -1)
                        {
                            //
                            // This is a day of week name.
                            //
                            raw.dayOfWeek = tokenValue;
                            dtok.dtt = DTT.DayOfWeek;
                        }
                        else
                        {
                            result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                            return false;
                        }
                        break;
                    case TokenType.MonthToken:
                        if (raw.month == -1)
                        {
                            //
                            // This is a month name
                            //
                            switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator))
                            {
                                case TokenType.SEP_End:
                                    dtok.dtt = DTT.MonthEnd;
                                    break;
                                case TokenType.SEP_Space:
                                    dtok.dtt = DTT.MonthSpace;
                                    break;
                                case TokenType.SEP_Date:
                                    dtok.dtt = DTT.MonthDatesep;
                                    break;
                                case TokenType.SEP_Time:
                                    if (!raw.hasSameDateAndTimeSeparators)
                                    {
                                        result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                                        return false;
                                    }

                                    // we have the date and time separators are same and getting a Month name, then change the token to MonthDatesep as 
                                    // we are sure we are not parsing time.
                                    dtok.dtt = DTT.MonthDatesep;
                                    break;
                                case TokenType.SEP_DateOrOffset:
                                    // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
                                    // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
                                    if ((DateParsingStates(dps, DTT.MonthDatesep) == DS.ERROR)
                                        && (DateParsingStates(dps, DTT.MonthSpace) > DS.ERROR))
                                    {
                                        str.Index = indexBeforeSeparator;
                                        str.m_current = charBeforeSeparator;
                                        dtok.dtt = DTT.MonthSpace;
                                    }
                                    else
                                    {
                                        dtok.dtt = DTT.MonthDatesep;
                                    }
                                    break;
                                default:
                                    //Invalid separator after month name
                                    result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                                    return false;
                            }
                            raw.month = tokenValue;
                        }
                        else
                        {
                            result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                            return false;
                        }
                        break;
                    case TokenType.EraToken:
                        if (result.era != -1)
                        {
                            result.era = tokenValue;
                            dtok.dtt = DTT.Era;
                        }
                        else
                        {
                            result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                            return false;
                        }
                        break;
                    case TokenType.JapaneseEraToken:
                        throw new NotSupportedException();
                    case TokenType.TEraToken:
                        throw new NotSupportedException();
                    case TokenType.TimeZoneToken:
                        //
                        // This is a timezone designator
                        //
                        // NOTENOTE : for now, we only support "GMT" and "Z" (for Zulu time).
                        //
                        if ((result.flags & ParseFlags.TimeZoneUsed) != 0)
                        {
                            // Should not have two timezone offsets.
                            result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                            return false;
                        }
                        dtok.dtt = DTT.TimeZone;
                        result.flags |= ParseFlags.TimeZoneUsed;
                        result.timeZoneOffset = new TimeSpan(0);
                        result.flags |= ParseFlags.TimeZoneUtc;
                        break;
                    case TokenType.EndOfString:
                        dtok.dtt = DTT.End;
                        break;
                    case TokenType.DateWordToken:
                    case TokenType.IgnorableSymbol:
                        // Date words and ignorable symbols can just be skipped over
                        break;
                    case TokenType.Am:
                    case TokenType.Pm:
                        if (raw.timeMark == TM.NotSet)
                        {
                            raw.timeMark = (TM)tokenValue;
                        }
                        else
                        {
                            result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                            return false;
                        }
                        break;
                    case TokenType.UnknownToken:
                        if (Char.IsLetter(str.m_current))
                        {
                            result.SetFailure(ParseFailureKind.FormatWithParameter, SR.Format_UnknowDateTimeWord, str.Index);
                            return (false);
                        }


                        if ((str.m_current == '-' || str.m_current == '+') && ((result.flags & ParseFlags.TimeZoneUsed) == 0))
                        {
                            Int32 originalIndex = str.Index;
                            if (ParseTimeZone(ref str, ref result.timeZoneOffset))
                            {
                                result.flags |= ParseFlags.TimeZoneUsed;
                                return true;
                            }
                            else
                            {
                                // Time zone parse attempt failed. Fall through to punctuation handling.
                                str.Index = originalIndex;
                            }
                        }

                        // Visual Basic implements string to date conversions on top of DateTime.Parse:
                        //   CDate("#10/10/95#")
                        //
                        if (VerifyValidPunctuation(ref str))
                        {
                            return true;
                        }

                        result.SetFailure(ParseFailureKind.Format, SR.Format_BadDateTime, null);
                        return false;
                }
                return true;
            }
コード例 #7
0
        [System.Security.SecuritySafeCritical]  // auto-generated
        private static Boolean Lex(
#if !FEATURE_CORECLR
            DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi, DateTimeStyles styles)
コード例 #8
0
ファイル: DateTimeParse.cs プロジェクト: randomize/VimConfig
        private static bool Lex(DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi)
        {
            TokenType type;
            int num;
            int num2;
            char ch;
            TokenType type2;
            dtok.dtt = DTT.Unk;
            str.GetRegularToken(out type, out num, dtfi);
            switch (type)
            {
                case TokenType.NumberToken:
                case TokenType.YearNumberToken:
                    if ((raw.numCount != 3) && (num != -1))
                    {
                        if ((dps == DS.T_NNt) && (str.Index < (str.len - 1)))
                        {
                            char ch2 = str.Value[str.Index];
                            if (ch2 == '.')
                            {
                                ParseFraction(ref str, out raw.fraction);
                            }
                        }
                        if (((dps == DS.T_NNt) || (dps == DS.T_Nt)) && (str.Index < (str.len - 1)))
                        {
                            char c = str.Value[str.Index];
                            int num3 = 0;
                            while (char.IsWhiteSpace(c) && ((str.Index + num3) < (str.len - 1)))
                            {
                                num3++;
                                c = str.Value[str.Index + num3];
                            }
                            switch (c)
                            {
                                case '+':
                                case '-':
                                    str.Index += num3;
                                    if ((result.flags & ParseFlags.TimeZoneUsed) != 0)
                                    {
                                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                        return false;
                                    }
                                    result.flags |= ParseFlags.TimeZoneUsed;
                                    if (!ParseTimeZone(ref str, ref result.timeZoneOffset))
                                    {
                                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                        return false;
                                    }
                                    break;
                            }
                        }
                        dtok.num = num;
                        if (type != TokenType.YearNumberToken)
                        {
                            switch ((type2 = str.GetSeparatorToken(dtfi, out num2, out ch)))
                            {
                                case TokenType.SEP_End:
                                    dtok.dtt = DTT.NumEnd;
                                    raw.AddNumber(dtok.num);
                                    goto Label_0A1E;

                                case TokenType.SEP_Space:
                                    dtok.dtt = DTT.NumSpace;
                                    raw.AddNumber(dtok.num);
                                    goto Label_0A1E;

                                case TokenType.SEP_Am:
                                case TokenType.SEP_Pm:
                                    if (raw.timeMark == TM.NotSet)
                                    {
                                        raw.timeMark = (type2 == TokenType.SEP_Am) ? TM.AM : TM.PM;
                                        dtok.dtt = DTT.NumAmpm;
                                        raw.AddNumber(dtok.num);
                                    }
                                    else
                                    {
                                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                    }
                                    goto Label_0A1E;

                                case TokenType.SEP_Time:
                                    dtok.dtt = DTT.NumTimesep;
                                    raw.AddNumber(dtok.num);
                                    goto Label_0A1E;

                                case TokenType.SEP_YearSuff:
                                    dtok.num = dtfi.Calendar.ToFourDigitYear(num);
                                    dtok.dtt = DTT.NumDatesuff;
                                    dtok.suffix = type2;
                                    goto Label_0A1E;

                                case TokenType.SEP_Date:
                                    dtok.dtt = DTT.NumDatesep;
                                    raw.AddNumber(dtok.num);
                                    goto Label_0A1E;

                                case TokenType.SEP_MonthSuff:
                                case TokenType.SEP_DaySuff:
                                    dtok.dtt = DTT.NumDatesuff;
                                    dtok.suffix = type2;
                                    goto Label_0A1E;

                                case TokenType.SEP_HourSuff:
                                case TokenType.SEP_MinuteSuff:
                                case TokenType.SEP_SecondSuff:
                                    dtok.dtt = DTT.NumTimesuff;
                                    dtok.suffix = type2;
                                    goto Label_0A1E;

                                case TokenType.SEP_LocalTimeMark:
                                    dtok.dtt = DTT.NumLocalTimeMark;
                                    raw.AddNumber(dtok.num);
                                    goto Label_0A1E;

                                case TokenType.SEP_DateOrOffset:
                                    if ((dateParsingStates[(int) dps][4] == DS.ERROR) && (dateParsingStates[(int) dps][3] > DS.ERROR))
                                    {
                                        str.Index = num2;
                                        str.m_current = ch;
                                        dtok.dtt = DTT.NumSpace;
                                    }
                                    else
                                    {
                                        dtok.dtt = DTT.NumDatesep;
                                    }
                                    raw.AddNumber(dtok.num);
                                    goto Label_0A1E;
                            }
                            result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                            return false;
                        }
                        if (raw.year != -1)
                        {
                            result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                            return false;
                        }
                        raw.year = num;
                        switch ((type2 = str.GetSeparatorToken(dtfi, out num2, out ch)))
                        {
                            case TokenType.SEP_Pm:
                            case TokenType.SEP_Am:
                                if (raw.timeMark == TM.NotSet)
                                {
                                    raw.timeMark = (type2 == TokenType.SEP_Am) ? TM.AM : TM.PM;
                                    dtok.dtt = DTT.YearSpace;
                                }
                                else
                                {
                                    result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                }
                                goto Label_0354;

                            case TokenType.SEP_Date:
                                dtok.dtt = DTT.YearDateSep;
                                goto Label_0354;

                            case TokenType.SEP_YearSuff:
                            case TokenType.SEP_MonthSuff:
                            case TokenType.SEP_DaySuff:
                                dtok.dtt = DTT.NumDatesuff;
                                dtok.suffix = type2;
                                goto Label_0354;

                            case TokenType.SEP_End:
                                dtok.dtt = DTT.YearEnd;
                                goto Label_0354;

                            case TokenType.SEP_Space:
                                dtok.dtt = DTT.YearSpace;
                                goto Label_0354;

                            case TokenType.SEP_HourSuff:
                            case TokenType.SEP_MinuteSuff:
                            case TokenType.SEP_SecondSuff:
                                dtok.dtt = DTT.NumTimesuff;
                                dtok.suffix = type2;
                                goto Label_0354;

                            case TokenType.SEP_DateOrOffset:
                                if ((dateParsingStates[(int) dps][13] == DS.ERROR) && (dateParsingStates[(int) dps][12] > DS.ERROR))
                                {
                                    str.Index = num2;
                                    str.m_current = ch;
                                    dtok.dtt = DTT.YearSpace;
                                }
                                else
                                {
                                    dtok.dtt = DTT.YearDateSep;
                                }
                                goto Label_0354;
                        }
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                    return false;

                case TokenType.Am:
                case TokenType.Pm:
                    if (raw.timeMark != TM.NotSet)
                    {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    raw.timeMark = (TM) num;
                    break;

                case TokenType.MonthToken:
                {
                    if (raw.month != -1)
                    {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    TokenType type8 = type2 = str.GetSeparatorToken(dtfi, out num2, out ch);
                    if (type8 > TokenType.SEP_Space)
                    {
                        switch (type8)
                        {
                            case TokenType.SEP_Date:
                                dtok.dtt = DTT.MonthDatesep;
                                goto Label_0823;

                            case TokenType.SEP_DateOrOffset:
                                if ((dateParsingStates[(int) dps][8] == DS.ERROR) && (dateParsingStates[(int) dps][7] > DS.ERROR))
                                {
                                    str.Index = num2;
                                    str.m_current = ch;
                                    dtok.dtt = DTT.MonthSpace;
                                }
                                else
                                {
                                    dtok.dtt = DTT.MonthDatesep;
                                }
                                goto Label_0823;
                        }
                    }
                    else
                    {
                        switch (type8)
                        {
                            case TokenType.SEP_End:
                                dtok.dtt = DTT.MonthEnd;
                                goto Label_0823;

                            case TokenType.SEP_Space:
                                dtok.dtt = DTT.MonthSpace;
                                goto Label_0823;
                        }
                    }
                    result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                    return false;
                }
                case TokenType.EndOfString:
                    dtok.dtt = DTT.End;
                    break;

                case TokenType.DayOfWeekToken:
                    if (raw.dayOfWeek != -1)
                    {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    raw.dayOfWeek = num;
                    dtok.dtt = DTT.DayOfWeek;
                    break;

                case TokenType.TimeZoneToken:
                    dtok.dtt = DTT.TimeZone;
                    result.flags |= ParseFlags.TimeZoneUsed;
                    result.timeZoneOffset = new TimeSpan(0L);
                    result.flags |= ParseFlags.TimeZoneUtc;
                    break;

                case TokenType.EraToken:
                    if (result.era == -1)
                    {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    result.era = num;
                    dtok.dtt = DTT.Era;
                    break;

                case TokenType.UnknownToken:
                    if (!char.IsLetter(str.m_current))
                    {
                        if (Environment.GetCompatibilityFlag(CompatibilityFlag.DateTimeParseIgnorePunctuation) && ((result.flags & ParseFlags.CaptureOffset) == 0))
                        {
                            str.GetNext();
                            return true;
                        }
                        if (((str.m_current == '-') || (str.m_current == '+')) && ((result.flags & ParseFlags.TimeZoneUsed) == 0))
                        {
                            int index = str.Index;
                            if (ParseTimeZone(ref str, ref result.timeZoneOffset))
                            {
                                result.flags |= ParseFlags.TimeZoneUsed;
                                return true;
                            }
                            str.Index = index;
                        }
                        if (VerifyValidPunctuation(ref str))
                        {
                            return true;
                        }
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_UnknowDateTimeWord", str.Index);
                    return false;

                case TokenType.HebrewNumber:
                    if (num < 100)
                    {
                        dtok.num = num;
                        raw.AddNumber(dtok.num);
                        switch ((type2 = str.GetSeparatorToken(dtfi, out num2, out ch)))
                        {
                            case TokenType.SEP_Date:
                            case TokenType.SEP_Space:
                                dtok.dtt = DTT.NumDatesep;
                                goto Label_0A1E;

                            case TokenType.SEP_DateOrOffset:
                                if ((dateParsingStates[(int) dps][4] == DS.ERROR) && (dateParsingStates[(int) dps][3] > DS.ERROR))
                                {
                                    str.Index = num2;
                                    str.m_current = ch;
                                    dtok.dtt = DTT.NumSpace;
                                }
                                else
                                {
                                    dtok.dtt = DTT.NumDatesep;
                                }
                                goto Label_0A1E;

                            case TokenType.SEP_End:
                                dtok.dtt = DTT.NumEnd;
                                goto Label_0A1E;
                        }
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    if (raw.year != -1)
                    {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    raw.year = num;
                    switch ((type2 = str.GetSeparatorToken(dtfi, out num2, out ch)))
                    {
                        case TokenType.SEP_End:
                            dtok.dtt = DTT.YearEnd;
                            goto Label_0A1E;

                        case TokenType.SEP_Space:
                            dtok.dtt = DTT.YearSpace;
                            goto Label_0A1E;

                        case TokenType.SEP_DateOrOffset:
                            if (dateParsingStates[(int) dps][12] > DS.ERROR)
                            {
                                str.Index = num2;
                                str.m_current = ch;
                                dtok.dtt = DTT.YearSpace;
                                goto Label_0A1E;
                            }
                            break;
                    }
                    result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                    return false;

                case TokenType.JapaneseEraToken:
                    result.calendar = JapaneseCalendar.GetDefaultInstance();
                    dtfi = DateTimeFormatInfo.GetJapaneseCalendarDTFI();
                    if (result.era == -1)
                    {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    result.era = num;
                    dtok.dtt = DTT.Era;
                    break;

                case TokenType.TEraToken:
                    result.calendar = TaiwanCalendar.GetDefaultInstance();
                    dtfi = DateTimeFormatInfo.GetTaiwanCalendarDTFI();
                    if (result.era == -1)
                    {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    result.era = num;
                    dtok.dtt = DTT.Era;
                    break;
            }
            goto Label_0A1E;
        Label_0354:
            return true;
        Label_0823:
            raw.month = num;
        Label_0A1E:
            return true;
        }
コード例 #9
0
ファイル: DateTimeParse.cs プロジェクト: randomize/VimConfig
 internal static unsafe bool TryParse(string s, DateTimeFormatInfo dtfi, DateTimeStyles styles, ref DateTimeResult result)
 {
     DateTime time;
     if (s == null)
     {
         result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "s");
         return false;
     }
     if (s.Length == 0)
     {
         result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
         return false;
     }
     DS bEGIN = DS.BEGIN;
     bool flag = false;
     DateTimeToken dtok = new DateTimeToken {
         suffix = TokenType.SEP_Unk
     };
     DateTimeRawInfo raw = new DateTimeRawInfo();
     int* numberBuffer = stackalloc int[3];
     raw.Init(numberBuffer);
     result.calendar = dtfi.Calendar;
     result.era = 0;
     __DTString str = new __DTString(s, dtfi);
     str.GetNext();
     do
     {
         if (!Lex(bEGIN, ref str, ref dtok, ref raw, ref result, ref dtfi))
         {
             return false;
         }
         if (dtok.dtt != DTT.Unk)
         {
             if (dtok.suffix != TokenType.SEP_Unk)
             {
                 if (!ProcessDateTimeSuffix(ref result, ref raw, ref dtok))
                 {
                     result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                     return false;
                 }
                 dtok.suffix = TokenType.SEP_Unk;
             }
             if (dtok.dtt == DTT.NumLocalTimeMark)
             {
                 switch (bEGIN)
                 {
                     case DS.D_YNd:
                     case DS.D_YN:
                         return ParseISO8601(ref raw, ref str, styles, ref result);
                 }
                 result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                 return false;
             }
             bEGIN = dateParsingStates[(int) bEGIN][(int) dtok.dtt];
             if (bEGIN == DS.ERROR)
             {
                 result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                 return false;
             }
             if (bEGIN > DS.ERROR)
             {
                 if ((dtfi.FormatFlags & DateTimeFormatFlags.UseHebrewRule) != DateTimeFormatFlags.None)
                 {
                     if (!ProcessHebrewTerminalState(bEGIN, ref result, ref styles, ref raw, dtfi))
                     {
                         return false;
                     }
                 }
                 else if (!ProcessTerminaltState(bEGIN, ref result, ref styles, ref raw, dtfi))
                 {
                     return false;
                 }
                 flag = true;
                 bEGIN = DS.BEGIN;
             }
         }
     }
     while (((dtok.dtt != DTT.End) && (dtok.dtt != DTT.NumEnd)) && (dtok.dtt != DTT.MonthEnd));
     if (!flag)
     {
         result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
         return false;
     }
     AdjustTimeMark(dtfi, ref raw);
     if (!AdjustHour(ref result.Hour, raw.timeMark))
     {
         result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
         return false;
     }
     bool bTimeOnly = ((result.Year == -1) && (result.Month == -1)) && (result.Day == -1);
     if (!CheckDefaultDateTime(ref result, ref result.calendar, styles))
     {
         return false;
     }
     if (!result.calendar.TryToDateTime(result.Year, result.Month, result.Day, result.Hour, result.Minute, result.Second, 0, result.era, out time))
     {
         result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
         return false;
     }
     if (raw.fraction > 0.0)
     {
         time = time.AddTicks((long) Math.Round((double) (raw.fraction * 10000000.0)));
     }
     if ((raw.dayOfWeek != -1) && (raw.dayOfWeek != result.calendar.GetDayOfWeek(time)))
     {
         result.SetFailure(ParseFailureKind.Format, "Format_BadDayOfWeek", null);
         return false;
     }
     result.parsedDate = time;
     if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly))
     {
         return false;
     }
     return true;
 }
コード例 #10
0
        //
        // This is the lexer. Check the character at the current index, and put the found token in dtok and
        // some raw date/time information in raw.
        //
        private static Boolean Lex(
            DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi) {

            TokenType tokenType;
            int tokenValue;

            TokenType sep;
            dtok.dtt = DTT.Unk;     // Assume the token is unkown.

            str.GetRegularToken(out tokenType, out tokenValue, dtfi);

            // Look at the regular token.
            switch (tokenType) {
                case TokenType.NumberToken:
                case TokenType.YearNumberToken:
                    if (raw.numCount == 3 || tokenValue == -1) {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    //
                    // This is a digit.
                    //
                    // If the previous parsing state is DS.T_NNt (like 12:01), and we got another number,
                    // so we will have a terminal state DS.TX_NNN (like 12:01:02).
                    // If the previous parsing state is DS.T_Nt (like 12:), and we got another number,
                    // so we will have a terminal state DS.TX_NN (like 12:01).
                    //
                    // Look ahead to see if the following character is a decimal point or timezone offset.
                    // This enables us to parse time in the forms of:
                    //  "11:22:33.1234" or "11:22:33-08".
                    if (dps == DS.T_NNt) {
                        if ((str.Index < str.len - 1)) {
                            char nextCh = str.Value[str.Index];
                            if (nextCh == '.') {
                                // While ParseFraction can fail, it just means that there were no digits after
                                // the dot. In this case ParseFraction just swallows the dot. This is actually
                                // valid for cultures like Albanian, that join the time marker to the time with
                                // with a dot: e.g. "9:03.MD"
                                ParseFraction(ref str, out raw.fraction);
                            }
                        }
                    }
                    if (dps == DS.T_NNt || dps == DS.T_Nt) {
                        if ((str.Index < str.len - 1)) {
                            char nextCh = str.Value[str.Index];
                            // Skip whitespace, but don't update the index unless we find a time zone marker
                            int whitespaceCount = 0;
                            while (Char.IsWhiteSpace(nextCh) && str.Index + whitespaceCount < str.len - 1) {
                                whitespaceCount++;
                                nextCh = str.Value[str.Index + whitespaceCount];
                            }
                            if (nextCh == '+' || nextCh == '-') {
                                str.Index += whitespaceCount;
                                if ((result.flags & ParseFlags.TimeZoneUsed) != 0) {
                                    // Should not have two timezone offsets.
                                    result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                    return false;
                                }
                                result.flags |= ParseFlags.TimeZoneUsed;
                                if (!ParseTimeZone(ref str, ref result.timeZoneOffset)) {
                                    result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                    return false;
                                }
                            }
                        }
                    }

                    dtok.num = tokenValue;
                    if (tokenType == TokenType.YearNumberToken)
                    {
                        if (raw.year == -1)
                        {
                            raw.year = tokenValue;
                            //
                            // If we have number which has 3 or more digits (like "001" or "0001"),
                            // we assume this number is a year. Save the currnet raw.numCount in
                            // raw.year.
                            //
                            switch (sep = str.GetSeparatorToken(dtfi)) {
                                case TokenType.SEP_End:
                                    dtok.dtt     = DTT.YearEnd;
                                    break;
                                case TokenType.SEP_Am:
                                case TokenType.SEP_Pm:
                                    if (raw.timeMark == TM.NotSet) {
                                        raw.timeMark = (sep == TokenType.SEP_Am ? TM.AM : TM.PM);
                                        dtok.dtt    = DTT.YearSpace;
                                    } else {
                                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                    }
                                    break;
                                case TokenType.SEP_Space:
                                    dtok.dtt    = DTT.YearSpace;
                                    break;
                                case TokenType.SEP_Date:
                                    dtok.dtt     = DTT.YearDateSep;
                                    break;
                                case TokenType.SEP_YearSuff:
                                case TokenType.SEP_MonthSuff:
                                case TokenType.SEP_DaySuff:
                                    dtok.dtt    = DTT.NumDatesuff;
                                    dtok.suffix = sep;
                                    break;
                                case TokenType.SEP_HourSuff:
                                case TokenType.SEP_MinuteSuff:
                                case TokenType.SEP_SecondSuff:
                                    dtok.dtt    = DTT.NumTimesuff;
                                    dtok.suffix = sep;
                                    break;
                                default:
                                    // Invalid separator after number number.
                                    result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                    return false;
                            }
                            //
                            // Found the token already. Return now.
                            //
                            return true;
                        }
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    switch (sep = str.GetSeparatorToken(dtfi))
                    {
                        //
                        // Note here we check if the numCount is less than three.
                        // When we have more than three numbers, it will be caught as error in the state machine.
                        //
                        case TokenType.SEP_End:
                            dtok.dtt = DTT.NumEnd;
                            raw.AddNumber(dtok.num);
                            break;
                        case TokenType.SEP_Am:
                        case TokenType.SEP_Pm:
                            if (raw.timeMark == TM.NotSet) {
                                raw.timeMark = (sep == TokenType.SEP_Am ? TM.AM : TM.PM);
                                dtok.dtt = DTT.NumAmpm;
                                raw.AddNumber(dtok.num);
                            } else {
                                result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                            }
                            break;
                        case TokenType.SEP_Space:
                            dtok.dtt = DTT.NumSpace;
                            raw.AddNumber(dtok.num);
                            break;
                        case TokenType.SEP_Date:
                            dtok.dtt = DTT.NumDatesep;
                            raw.AddNumber(dtok.num);
                            break;
                        case TokenType.SEP_Time:
                            if ((result.flags & ParseFlags.TimeZoneUsed) == 0) {
                                dtok.dtt = DTT.NumTimesep;
                                raw.AddNumber(dtok.num);
                            } else {
                                // If we already got timezone, there should be no
                                // time separator again.
                                result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                return false;
                            }
                            break;
                        case TokenType.SEP_YearSuff:
                            dtok.num = dtfi.Calendar.ToFourDigitYear(tokenValue);
                            dtok.dtt    = DTT.NumDatesuff;
                            dtok.suffix = sep;
                            break;
                        case TokenType.SEP_MonthSuff:
                        case TokenType.SEP_DaySuff:
                            dtok.dtt    = DTT.NumDatesuff;
                            dtok.suffix = sep;
                            break;
                        case TokenType.SEP_HourSuff:
                        case TokenType.SEP_MinuteSuff:
                        case TokenType.SEP_SecondSuff:
                            dtok.dtt    = DTT.NumTimesuff;
                            dtok.suffix = sep;
                            break;
                        case TokenType.SEP_LocalTimeMark:
                            dtok.dtt = DTT.NumLocalTimeMark;
                            raw.AddNumber(dtok.num);
                            break;
                        default:
                            // Invalid separator after number number.
                            result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                            return false;
                    }
                    break;
                case TokenType.HebrewNumber:
                    if (tokenValue >= 100) {
                        // This is a year number
                        if (raw.year == -1) {
                            raw.year = tokenValue;
                            //
                            // If we have number which has 3 or more digits (like "001" or "0001"),
                            // we assume this number is a year. Save the currnet raw.numCount in
                            // raw.year.
                            //
                            switch (sep = str.GetSeparatorToken(dtfi)) {
                                case TokenType.SEP_End:
                                    dtok.dtt = DTT.YearEnd;
                                    break;
                                case TokenType.SEP_Space:
                                    dtok.dtt = DTT.YearSpace;
                                    break;
                                default:
                                    // Invalid separator after number number.
                                    result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                    return false;
                            }
                        } else {
                            // Invalid separator after number number.
                            result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                            return false;
                        }
                    } else {
                        // This is a day number
                        dtok.num = tokenValue;
                        raw.AddNumber(dtok.num);

                        switch (sep = str.GetSeparatorToken(dtfi)) {
                            //
                            // Note here we check if the numCount is less than three.
                            // When we have more than three numbers, it will be caught as error in the state machine.
                            //
                            case TokenType.SEP_End:
                                dtok.dtt = DTT.NumEnd;
                                break;
                            case TokenType.SEP_Space:
                            case TokenType.SEP_Date:
                                dtok.dtt = DTT.NumDatesep;
                                break;
                            default:
                                // Invalid separator after number number.
                                result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                return false;
                        }
                    }
                    break;
                case TokenType.DayOfWeekToken:
                    if (raw.dayOfWeek == -1)
                    {
                        //
                        // This is a day of week name.
                        //
                        raw.dayOfWeek = tokenValue;
                        dtok.dtt = DTT.DayOfWeek;
                    } else {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    break;
                case TokenType.MonthToken:
                    if (raw.month == -1)
                    {
                        //
                        // This is a month name
                        //
                        switch(sep=str.GetSeparatorToken(dtfi))
                        {
                            case TokenType.SEP_End:
                                dtok.dtt = DTT.MonthEnd;
                                break;
                            case TokenType.SEP_Space:
                                dtok.dtt = DTT.MonthSpace;
                                break;
                            case TokenType.SEP_Date:
                                dtok.dtt = DTT.MonthDatesep;
                                break;
                            default:
                                //Invalid separator after month name
                                result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                                return false;
                        }
                        raw.month = tokenValue;
                    }  else {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    break;
                case TokenType.EraToken:
                    if (result.era != -1) {
                        result.era = tokenValue;
                        dtok.dtt = DTT.Era;
                    } else {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    break;
                case TokenType.JapaneseEraToken:
                    // Special case for Japanese.  We allow Japanese era name to be used even if the calendar is not Japanese Calendar.
                    result.calendar = JapaneseCalendar.GetDefaultInstance();
                    dtfi = DateTimeFormatInfo.GetJapaneseCalendarDTFI();
                    if (result.era != -1) {
                        result.era = tokenValue;
                        dtok.dtt = DTT.Era;
                    } else {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    break;
                case TokenType.TEraToken:
                    // Special case for Taiwan.
                    result.calendar = TaiwanCalendar.GetDefaultInstance();
                    dtfi = DateTimeFormatInfo.GetTaiwanCalendarDTFI();
                    if (result.era != -1) {
                        result.era = tokenValue;
                        dtok.dtt = DTT.Era;
                    } else {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    break;
                case TokenType.TimeZoneToken:
                    //
                    dtok.dtt = DTT.TimeZone;
                    result.flags |= ParseFlags.TimeZoneUsed;
                    result.timeZoneOffset = new TimeSpan(0);
                    result.flags |= ParseFlags.TimeZoneUtc;
                    break;
                case TokenType.EndOfString:
                    dtok.dtt = DTT.End;
                    break;
                case TokenType.DateWordToken:
                case TokenType.IgnorableSymbol:
                    // Date words and ignorable symbols can just be skipped over
                    break;
                case TokenType.Am:
                case TokenType.Pm:
                    if (raw.timeMark == TM.NotSet) {
                        raw.timeMark = (TM)tokenValue;
                    } else {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    break;
                case TokenType.UnknownToken:
                    if (Char.IsLetter(str.m_current)) {
                        result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_UnknowDateTimeWord",  str.Index);
                        return (false);
                    }
                    else {
                        // If DateTimeParseIgnorePunctuation is defined, we want to have the V1.1 behavior of just
                        // ignoring any unrecognized punctuation and moving on to the next character
                        if (Environment.GetCompatibilityFlag(CompatibilityFlag.DateTimeParseIgnorePunctuation)) {
                            str.GetNext();
                            return true;
                        }
                        else {
                            if (VerifyValidPunctuation(ref str)) {
                                return true;                                
                            }
                        }
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;                    
                    }
            }

            return true;
        }
コード例 #11
0
        //
        // This is the real method to do the parsing work.
        //
        internal static bool TryParse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles, ref DateTimeResult result) {
            if (s == null) {
                result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "s");
                return false;
            }
            if (s.Length == 0) {
                result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                return false;
            }

            BCLDebug.Assert(dtfi != null, "dtfi == null");

            DateTime time;
            //
            // First try the predefined format.
            //

            DS dps             = DS.BEGIN;     // Date Parsing State.
            bool reachTerminalState = false;

            DateTimeToken   dtok    = new DateTimeToken();      // The buffer to store the parsing token.
            dtok.suffix = TokenType.SEP_Unk;
            DateTimeRawInfo raw     = new DateTimeRawInfo();    // The buffer to store temporary parsing information.
            unsafe {
                Int32 * numberPointer = stackalloc Int32[3];
                raw.Init(numberPointer);
            }
            result.calendar = dtfi.Calendar;
            result.era = Calendar.CurrentEra;

            //
            // The string to be parsed. Use a __DTString wrapper so that we can trace the index which
            // indicates the begining of next token.
            //
            __DTString str = new __DTString(s, dtfi);

            str.GetNext();

            //
            // The following loop will break out when we reach the end of the str.
            //
            do {
                //
                // Call the lexer to get the next token.
                //
                // If we find a era in Lex(), the era value will be in raw.era.
                if (!Lex(dps, ref str, ref dtok, ref raw, ref result, ref dtfi)) {
                    return false;
                }

                //
                // If the token is not unknown, process it.
                // Otherwise, just discard it.
                //
                if (dtok.dtt != DTT.Unk)
                {
                    //
                    // Check if we got any CJK Date/Time suffix.
                    // Since the Date/Time suffix tells us the number belongs to year/month/day/hour/minute/second,
                    // store the number in the appropriate field in the result.
                    //
                    if (dtok.suffix != TokenType.SEP_Unk)
                    {
                        if (!ProcessDateTimeSuffix(ref result, ref raw, ref dtok)) {
                            result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                            return false;
                        }

                        dtok.suffix = TokenType.SEP_Unk;  // Reset suffix to SEP_Unk;
                    }

                    if (dtok.dtt == DTT.NumLocalTimeMark) {
                        if (dps == DS.D_YNd || dps == DS.D_YN) {
                            return (ParseISO8601(ref raw, ref str, styles, ref result));
                        }
                        else {
                            result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                            return false;
                        }
                    }

                    //
                    // Advance to the next state, and continue
                    //
                    dps = dateParsingStates[(int)dps][(int)dtok.dtt];
                    
                    if (dps == DS.ERROR)
                    {
                        result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                        return false;
                    }
                    else if (dps > DS.ERROR)
                    {
                        if ((dtfi.FormatFlags & DateTimeFormatFlags.UseHebrewRule) != 0) {
                            if (!ProcessHebrewTerminalState(dps, ref result, ref raw, dtfi)) {
                                return false;
                            }
                        } else {
                            if (!ProcessTerminaltState(dps, ref result, ref raw, dtfi)) {
                                return false;
                            }
                        }
                        reachTerminalState = true;

                        //
                        // If we have reached a terminal state, start over from DS.BEGIN again.
                        // For example, when we parsed "1999-12-23 13:30", we will reach a terminal state at "1999-12-23",
                        // and we start over so we can continue to parse "12:30".
                        //
                        dps = DS.BEGIN;
                    }
                }
            } while (dtok.dtt != DTT.End && dtok.dtt != DTT.NumEnd && dtok.dtt != DTT.MonthEnd);

            if (!reachTerminalState) {
                result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                return false;
            }

            AdjustTimeMark(dtfi, ref raw);
            if (!AdjustHour(ref result.Hour, raw.timeMark)) {
                result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
                return false;
            }

            // Check if the parased string only contains hour/minute/second values.
            bool bTimeOnly = (result.Year == -1 && result.Month == -1 && result.Day == -1);

            //
            // Check if any year/month/day is missing in the parsing string.
            // If yes, get the default value from today's date.
            //
            CheckDefaultDateTime(ref result, ref result.calendar, styles);

            if (!result.calendar.TryToDateTime(result.Year, result.Month, result.Day,
                    result.Hour, result.Minute, result.Second, 0, result.era, out time)) {
                result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
                return false;
            }
            if (raw.fraction > 0) {
                time = time.AddTicks((long)Math.Round(raw.fraction * Calendar.TicksPerSecond));
            }

            //
            // We have to check day of week before we adjust to the time zone.
            // Otherwise, the value of day of week may change after adjustting to the time zone.
            //
            if (raw.dayOfWeek != -1) {
                //
                // Check if day of week is correct.
                //
                if (raw.dayOfWeek != (int)result.calendar.GetDayOfWeek(time)) {
                    result.SetFailure(ParseFailureKind.Format, "Format_BadDayOfWeek", null);
                    return false;
                }
            }

            result.parsedDate = time;

            if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly)) {
                return false;
            }

            return true;
        }
コード例 #12
0
ファイル: datetimeparse.cs プロジェクト: ArildF/masters
        //
        // This is the lexer. Check the character at the current index, and put the found token in dtok and
        // some raw date/time information in raw.
        //
        private static void Lex(
            int dps, __DTString str, DateTimeToken dtok, DateTimeRawInfo raw, DateTimeResult result, ref DateTimeFormatInfo dtfi) {
            
            int sep;
            dtok.dtt = DTT_Unk;     // Assume the token is unkown.

            //
            // Skip any white spaces.
            //
            if (!str.SkipWhiteSpaceComma()) {
                //
                // SkipWhiteSpaceComma() will return true when end of string is reached.
                //
                dtok.dtt = DTT_End;
                return;
            }

            char ch = str.GetChar();
            if (Char.IsLetter(ch))
            {
                //
                // This is a letter.
                //

                int month, dayOfWeek, era, timeMark;

                //
                // Check if this is a beginning of a month name.
                // And check if this is a day of week name.
                //
                if (raw.month == -1 && (month = GetMonthNumber(str, dtfi)) >= 1)
                {
                    //
                    // This is a month name
                    //
                    switch(sep=GetSeparator(str, raw, dtfi))
                    {
                        case SEP_End:
                            dtok.dtt = DTT_MonthEnd;
                            break;
                        case SEP_Space:
                            dtok.dtt = DTT_MonthSpace;
                            break;
                        case SEP_Date:
                            dtok.dtt = DTT_MonthDatesep;
                            break;
                        default:
                            //Invalid separator after month name
                            throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                    }
                    raw.month = month;
                }
                else if (raw.dayOfWeek == -1 && (dayOfWeek = GetDayOfWeekNumber(str, dtfi)) >= 0)
                {
                    //
                    // This is a day of week name.
                    //
                    raw.dayOfWeek = dayOfWeek;
                    dtok.dtt = DTT_DayOfWeek;
                    //
                    // Discard the separator.
                    //
                    GetSeparator(str, raw, dtfi);
                }
                else if (GetTimeZoneName(str))
                {
                    //
                    // This is a timezone designator
                    //
                    // NOTENOTE                     : for now, we only support "GMT" and "Z" (for Zulu time).
                    //
                    dtok.dtt = DTT_TimeZone;
                    result.timeZoneUsed = true;
                    result.timeZoneOffset = new TimeSpan(0);
                } else if ((raw.era == -1) && ((era = GetEra(str, result, ref dtfi)) != -1)) {
                    raw.era = era;
                    dtok.dtt = DTT_Era;
                } else if (raw.timeMark == -1 && (timeMark = GetTimeMark(str, dtfi)) != -1) {
                    raw.timeMark = timeMark;
                    GetSeparator(str, raw, dtfi);
                } else {
                    //
                    // Not a month name, not a day of week name. Check if this is one of the
                    // known date words. This is used to deal case like Spanish cultures, which
                    // uses 'de' in their Date string.
                    // 
                    //                    
                    if (!str.MatchWords(dtfi.DateWords)) {
                        throw new FormatException(
                            String.Format(Environment.GetResourceString("Format_UnknowDateTimeWord"), str.Index));
                    }                    
                    GetSeparator(str, raw, dtfi);                    
                }
            } else if (Char.IsDigit(ch)) {
                if (raw.numCount == 3) {
                    throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                }
                //
                // This is a digit.
                //
                int number = ch - '0';

                int digitCount = 1;

                //
                // Collect other digits.
                //
                while (str.GetNextDigit())
                {
                    number = number * 10 + str.GetDigit();
                    digitCount++;
                }

                // If the previous parsing state is DS_T_NNt (like 12:01), and we got another number,
                // so we will have a terminal state DS_TX_NNN (like 12:01:02).
                // If the previous parsing state is DS_T_Nt (like 12:), and we got another number,
                // so we will have a terminal state DS_TX_NN (like 12:01:02).
                //
                // Look ahead to see if the following character is a decimal point or timezone offset.
                // This enables us to parse time in the forms of:
                //  "11:22:33.1234" or "11:22:33-08".
                if (dps == DS_T_NNt || dps == DS_T_Nt) {
                    char nextCh;
                    if ((str.Index < str.len - 1)) {
                        nextCh = str.Value[str.Index];
                        switch (nextCh) {                        
                            case '.':
                                if (dps == DS_T_NNt) {
                                    // Yes, advance to the next character.
                                    str.Index++;
                                    // Collect the second fraction.
                                    raw.fraction = ParseFraction(str);
                                }
                                break;
                            case '+':
                            case '-':
                                if (result.timeZoneUsed) {
                                    // Should not have two timezone offsets.
                                    throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                                }
                                result.timeZoneUsed = true;
                                result.timeZoneOffset = ParseTimeZone(str, nextCh);
                                break;
                        }
                    }
                }
                
                if (number >= 0)
                {
                    dtok.num = number;
                    if (digitCount >= 3)
                    {
                        if (raw.year == -1)
                        {
                            raw.year = number;
                            //
                            // If we have number which has 3 or more digits (like "001" or "0001"),
                            // we assume this number is a year. Save the currnet raw.numCount in
                            // raw.year.
                            //
                            switch (sep = GetSeparator(str, raw, dtfi))
                            {
                                case SEP_End:
                                    dtok.dtt     = DTT_YearEnd;
                                    break;
                                case SEP_Am:
                                case SEP_Pm:
                                case SEP_Space:
                                    dtok.dtt    = DTT_YearSpace;
                                    break;
                                case SEP_Date:
                                    dtok.dtt     = DTT_YearDateSep;
                                    break;
                                case SEP_YearSuff:
                                case SEP_MonthSuff:
                                case SEP_DaySuff:
                                    dtok.dtt    = DTT_NumDatesuff;
                                    dtok.suffix = sep;
                                    break;
                                case SEP_HourSuff:
                                case SEP_MinuteSuff:
                                case SEP_SecondSuff:
                                    dtok.dtt    = DTT_NumTimesuff;
                                    dtok.suffix = sep;
                                    break;
                                default:
                                    // Invalid separator after number number.
                                    throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                            }
                            //
                            // Found the token already. Let's bail.
                            //
                            return;
                        }
                        throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                    }
                } else
                {
                    //
                    // number is overflowed.
                    //
                    throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                }

                switch (sep = GetSeparator(str, raw, dtfi))
                {
                    //
                    // Note here we check if the numCount is less than three.
                    // When we have more than three numbers, it will be caught as error in the state machine.
                    //
                    case SEP_End:
                        dtok.dtt = DTT_NumEnd;
                        raw.num[raw.numCount++] = dtok.num;
                        break;
                    case SEP_Am:
                    case SEP_Pm:
                        dtok.dtt = DTT_NumAmpm;
                        raw.num[raw.numCount++] = dtok.num;
                        break;
                    case SEP_Space:
                        dtok.dtt = DTT_NumSpace;
                        raw.num[raw.numCount++] = dtok.num;
                        break;
                    case SEP_Date:
                        dtok.dtt = DTT_NumDatesep;
                        raw.num[raw.numCount++] = dtok.num;
                        break;
                    case SEP_Time:
                        if (!result.timeZoneUsed) {
                            dtok.dtt = DTT_NumTimesep;
                            raw.num[raw.numCount++] = dtok.num;
                        } else {
                            // If we already got timezone, there should be no
                            // time separator again.
                            throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                        }
                        break;
                    case SEP_YearSuff:
                        dtok.num = dtfi.Calendar.ToFourDigitYear(number);
                        dtok.dtt    = DTT_NumDatesuff;
                        dtok.suffix = sep;
                        break;
                    case SEP_MonthSuff:
                    case SEP_DaySuff:
                        dtok.dtt    = DTT_NumDatesuff;
                        dtok.suffix = sep;
                        break;
                    case SEP_HourSuff:
                    case SEP_MinuteSuff:
                    case SEP_SecondSuff:
                        dtok.dtt    = DTT_NumTimesuff;
                        dtok.suffix = sep;
                        break;
                    case SEP_LocalTimeMark:
                        dtok.dtt = DTT_NumLocalTimeMark;
                        raw.num[raw.numCount++] = dtok.num;
                        break;
                    default:
                        // Invalid separator after number number.
                        throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                }
            }
            else
            {
                //
                // Not a letter, not a digit. Just ignore it.
                //
                str.Index++;
            }
            return;
        }
コード例 #13
0
ファイル: datetimeparse.cs プロジェクト: ArildF/masters
        //
        // This is the real method to do the parsing work.
        //
        internal static DateTime Parse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles) {
            if (s == null) {
                throw new ArgumentNullException("s",
                    Environment.GetResourceString("ArgumentNull_String"));
            }
            if (s.Length == 0) {
                throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
            }            
            if (dtfi == null) {
                dtfi = DateTimeFormatInfo.CurrentInfo;
            }
        
            DateTime time;
            //
            // First try the predefined format.
            //
        
            int dps             = DS_BEGIN;     // Date Parsing State.
            bool reachTerminalState = false;

            DateTimeResult result = new DateTimeResult();       // The buffer to store the parsing result.
            DateTimeToken   dtok    = new DateTimeToken();      // The buffer to store the parsing token.
            DateTimeRawInfo raw     = new DateTimeRawInfo();    // The buffer to store temporary parsing information.
            result.calendar = dtfi.Calendar;

            //
            // The string to be parsed. Use a __DTString wrapper so that we can trace the index which
            // indicates the begining of next token.
            //
            __DTString str = new __DTString(s);

            str.GetNext();

            //
            // The following loop will break out when we reach the end of the str.
            //
            do {
                //
                // Call the lexer to get the next token.
                //
                // If we find a era in Lex(), the era value will be in raw.era.
                Lex(dps, str, dtok, raw, result, ref dtfi);

                //
                // If the token is not unknown, process it.
                // Otherwise, just discard it.
                //
                if (dtok.dtt != DTT_Unk)
                {
                    //
                    // Check if we got any CJK Date/Time suffix.
                    // Since the Date/Time suffix tells us the number belongs to year/month/day/hour/minute/second,
                    // store the number in the appropriate field in the result.
                    //
                    if (dtok.suffix != SEP_Unk)
                    {
                        ProcessDateTimeSuffix(result, raw, dtok);
                        dtok.suffix = SEP_Unk;  // Reset suffix to SEP_Unk;
                    }


                    if (dps == DS_D_YN && dtok.dtt == DTT_NumLocalTimeMark) {
                            // Consider this as ISO 8601 format:
                            // "yyyy-MM-dd'T'HH:mm:ss"                 1999-10-31T02:00:00
                            return (ParseISO8601(raw, str, styles));
                    }

                    //
                    // Advance to the next state, and continue
                    //
                    dps = dateParsingStates[dps][dtok.dtt];

                    if (dps == DS_ERROR)
                    {
                        BCLDebug.Trace("NLS", "DateTimeParse.DoParse(): dps is DS_ERROR");
                        throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
                    }
                    else if (dps > DS_ERROR)
                    {
                        ProcessTerminaltState(dps, result, raw, dtfi);
                        reachTerminalState = true;

                        //
                        // If we have reached a terminal state, start over from DS_BEGIN again.
                        // For example, when we parsed "1999-12-23 13:30", we will reach a terminal state at "1999-12-23",
                        // and we start over so we can continue to parse "12:30".
                        //
                        dps = DS_BEGIN;
                    }
                }
            } while (dtok.dtt != DTT_End && dtok.dtt != DTT_NumEnd && dtok.dtt != DTT_MonthEnd);

            if (!reachTerminalState) {
                BCLDebug.Trace("NLS", "DateTimeParse.DoParse(): terminal state is not reached");
                throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
            }

            // Check if the parased string only contains hour/minute/second values.
            bool bTimeOnly = (result.Year == -1 && result.Month == -1 && result.Day == -1);
            
            //
            // Check if any year/month/day is missing in the parsing string.
            // If yes, get the default value from today's date.
            //
            CheckDefaultDateTime(result, ref result.calendar, styles);

            try {
                if (raw.era == -1) {
                    raw.era = Calendar.CurrentEra;
                }
                time = result.calendar.ToDateTime(result.Year, result.Month, result.Day, 
                    result.Hour, result.Minute, result.Second, 0, raw.era);
                if (raw.fraction > 0) {
                    time = time.AddTicks((long)Math.Round(raw.fraction * Calendar.TicksPerSecond));
                }
            } catch (Exception)
            {
                BCLDebug.Trace("NLS", "DateTimeParse.DoParse(): time is bad");
                throw new FormatException(Environment.GetResourceString("Format_BadDateTime"));
            } 

            //
            // NOTENOTE                     :
            // We have to check day of week before we adjust to the time zone.
            // Otherwise, the value of day of week may change after adjustting to the time zone.
            //
            if (raw.dayOfWeek != -1) {
                //
                // Check if day of week is correct.
                //
                if (raw.dayOfWeek != (int)result.calendar.GetDayOfWeek(time)) {
                    BCLDebug.Trace("NLS", "DateTimeParse.DoParse(): day of week is not correct");
                    throw new FormatException(Environment.GetResourceString("Format_BadDayOfWeek"));
                }
            }

            if (result.timeZoneUsed) {
                time = AdjustTimeZone(time, result.timeZoneOffset, styles, bTimeOnly);
            }
            
            return (time);
        }
コード例 #14
0
ファイル: datetimeparse.cs プロジェクト: ArildF/masters
 //
 // A date suffix is found, use this method to put the number into the result.
 //
 private static void ProcessDateTimeSuffix(DateTimeResult result, DateTimeRawInfo raw, DateTimeToken dtok)
 {
     switch (dtok.suffix)
     {
         case SEP_YearSuff:
             result.Year = raw.year = dtok.num;
             break;
         case SEP_MonthSuff:
             result.Month= raw.month = dtok.num;
             break;
         case SEP_DaySuff:
             result.Day  = dtok.num;
             break;
         case SEP_HourSuff:
             result.Hour = dtok.num;
             break;
         case SEP_MinuteSuff:
             result.Minute = dtok.num;
             break;
         case SEP_SecondSuff:
             result.Second = dtok.num;
             break;
     }
 }