datetimeparser.cs

来自「没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没」· CS 代码 · 共 604 行

CS
604
字号
/* * DateTimeParser.cs - Implementation of the *		"System.Private.DateTimeFormat.DateTimeParser" class. * * Copyright (C) 2003  Southern Storm Software, Pty Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */namespace System.Private.DateTimeFormat{using System.Globalization;using System.Text;internal sealed class DateTimeParser{	// Skip white space in a string.	private static void SkipWhite(String s, ref int posn)			{				while(posn < s.Length && Char.IsWhiteSpace(s[posn]))				{					++posn;				}			}	// Parse a decimal number from a string.	private static int ParseNumber(String s, ref int posn, int maxDigits)			{				int value;				// The first character must be a decimal digit.				if(s[posn] < '0' || s[posn] > '9')				{					throw new FormatException();				}				value = (int)(s[posn++] - '0');				// Recognize additional digits.				while(maxDigits > 1 && posn < s.Length && s[posn] >= '0'				      && s[posn] <= '9')				{					value = (value * 10) + (int)(s[posn++] - '0');					--maxDigits;				}				// Return the value to the caller.				return value;			}	// Parse a particular string.	private static void ParseString(String s, ref int posn, String value)			{				if((s.Length - posn) < value.Length)				{					throw new FormatException();				}				if(String.Compare(s, posn, value, 0, value.Length,								  false, CultureInfo.CurrentCulture) != 0)				{					throw new FormatException();				}				posn += value.Length;			}	// Parse one of the strings in an array.	private static int ParseOneOf(String s, ref int posn, String[] values)			{				int maxlen = 0;				int found = 0;				int index;				CultureInfo culture = CultureInfo.CurrentCulture;				for(index = 0; index < values.Length; ++index)				{					if((s.Length - posn) < values[index].Length)					{						continue;					}					else if(values[index].Length == 0)					{						continue;					}					if(String.Compare(s, posn, values[index], 0,									  values[index].Length, false,									  culture) == 0)					{						if(found == 0 || values[index].Length > maxlen)						{							found = index + 1;							maxlen = values[index].Length;						}					}				}				if(found == 0)				{					throw new FormatException();				}				posn += maxlen;				return found;			}	// Parse an era name.	private static int ParseEra(String s, ref int posn,								Calendar calendar, DateTimeFormatInfo info)			{				// Get the list of eras from the calendar.				int[] eras = calendar.Eras;				// Convert the eras into era names.				String[] eraNames = new String [eras.Length];				int index;				for(index = 0; index < eras.Length; ++index)				{					eraNames[index] = info.GetEraName(eras[index]);				}				// Parse the era value using the strings we just got.				return ParseOneOf(s, ref posn, eraNames);			}	// Parse a timezone designator.	private static int ParseTimeZone(String s, ref int posn)			{				int sign = 1;				int hour, minute;				// Process the sign of the timezone;				if(posn < s.Length)				{					if(s[posn] == '-')					{						sign = -1;						++posn;					}					else if(s[posn] == '+')					{						++posn;					}				}				// Parse the hour portion of the timezone.				hour = ParseNumber(s, ref posn, 2);				// Parse the minute portion if there is a ':' separator.				if(posn < s.Length && s[posn] == ':')				{					++posn;					minute = ParseNumber(s, ref posn, 2);				}				else				{					minute = 0;				}				// Return the final timezone value.				return sign * (hour * 60 + minute);			}	// Try parsing a DateTime value with a specific format.	// Throws "FormatException" if the parse failed.	private static DateTime TryParse(String s, String format,						      		 DateTimeFormatInfo info,						      		 DateTimeStyles style)			{				int posn, sposn;				char ch;				int count;				Calendar calendar = CultureInfo.CurrentCulture.Calendar;				// Clear the parse information.				int year = 0;				int month = 0;				int day = 0;				int hour = 0;				int minute = 0;				int second = 0;				int fractions = 0;				int era = Calendar.CurrentEra;				int ampm = -1;				int timezone = 0;				// Parse the contents of the string.				posn = 0;				sposn = 0;				while(posn < format.Length && sposn < s.Length)				{					// Extract the next format character plus its count.					ch = format[posn++];					if(ch == ' ')					{						// White space is required in this position.						if(!Char.IsWhiteSpace(s[sposn]))						{							throw new FormatException();						}						++sposn;						SkipWhite(s, ref sposn);						if(sposn >= s.Length)						{							break;						}						continue;					}					else if((style & DateTimeStyles.AllowInnerWhite) != 0)					{						// White space is allowed between all components.						SkipWhite(s, ref sposn);						if(sposn >= s.Length)						{							break;						}					}					count = 1;					switch(ch)					{						case 'd': case 'm': case 'M': case 'y':						case 'g': case 'h': case 'H': case 's':						case 'f': case 't': case 'z':						{							while(posn < format.Length &&								  format[posn] == ch)							{								++posn;								++count;							}						}						break;						case ':':						{							// Looking for the time separator.							ParseString(s, ref sposn, info.TimeSeparator);							continue;						}						// Not reached.						case '/':						{							// Looking for the date separator.							ParseString(s, ref sposn, info.DateSeparator);							continue;						}						// Not reached.						case '%':						{							// Used to escape custom patterns that would							// otherwise look like single-letter formats.							continue;						}						// Not reached.						case '\\':						{							// Escape the next character.							if(posn < format.Length)							{								ch = format[posn++];								if(s[sposn++] != ch)								{									throw new FormatException();								}							}							else							{								throw new FormatException();							}							continue;						}						// Not reached.						case '\'':						{							// Quoted text.							while(posn < format.Length)							{								ch = format[posn++];								if(ch == '\'')								{									break;								}								if(s[sposn++] != ch)								{									throw new FormatException();								}							}							continue;						}						// Not reached.						default:						{							// Literal character.							if(s[sposn++] != ch)							{								throw new FormatException();							}							continue;						}						// Not reached.					}					// Process the format character.					switch(ch)					{						case 'd':						{							// Parse the day or weekday.  We discard weekdays							// because they don't add anything to the value.							if(count == 1 || count == 2)							{								day = ParseNumber(s, ref sposn, 2);							}							else if(count == 3)							{								ParseOneOf(s, ref sposn,										   info.AbbreviatedDayNames);							}							else							{								ParseOneOf(s, ref sposn, info.DayNames);							}						}						break;						case 'M':						{							// Parse the month.							if(count == 1 || count == 2)							{								month = ParseNumber(s, ref sposn, 2);							}							else if(count == 3)							{								month = ParseOneOf(s, ref sposn,										   info.AbbreviatedMonthNames);							}							else							{								month = ParseOneOf(s, ref sposn,										   		   info.MonthNames);							}						}						break;						case 'y':						{							// Parse the year.							if(count == 1 || count == 2)							{								year = calendar.ToFourDigitYear									(ParseNumber(s, ref sposn, 2));							}							else							{								year = ParseNumber(s, ref sposn, 4);							}						}						break;						case 'g':						{							// Parse an era name.							era = ParseEra(s, ref sposn, calendar, info);						}						break;						case 'h':						{							// Parse the hour in 12-hour format.							hour = ParseNumber(s, ref sposn, 2);						}						break;						case 'H':						{							// Parse the hour in 24-hour format.							hour = ParseNumber(s, ref sposn, 2);						}						break;						case 'm':						{							// Parse the minute.							minute = ParseNumber(s, ref sposn, 2);						}						break;						case 's':						{							// Parse the second.							second = ParseNumber(s, ref sposn, 2);						}						break;						case 'f':						{							// Parse fractions of a second.							fractions = ParseNumber(s, ref sposn,													Int32.MaxValue);							while(count < 7)							{								fractions *= 10;								++count;							}						}						break;						case 't':						{							// Parse an AM/PM designator.							if(count == 1)							{								ampm = ParseOneOf									(s, ref sposn, new String[]										{info.AMDesignator[0].ToString(),										 info.PMDesignator[0].ToString()});							}							else							{								ampm = ParseOneOf									(s, ref sposn, new String[]										{info.AMDesignator,										 info.PMDesignator});							}						}						break;						case 'z':						{							// Parse the timezone indicator.							timezone = ParseTimeZone(s, ref sposn);						}						break;					}				}				// At this point, we need to be at the end of both				// the format string and the parse string.  If we				// aren't then the parse failed.				if(posn < format.Length || sposn < s.Length)				{					throw new FormatException();				}				// Build the final DateTime value and return it.				if(ampm == 1)				{					if(hour == 12)					{						hour = 0;					}				}				else if(ampm == 2)				{					if(hour < 12)					{						hour += 12;					}				}				if(year == 0 && month == 0 && day == 0)				{					if((style & DateTimeStyles.NoCurrentDateDefault) == 0)					{						DateTime now = DateTime.Now;						year = calendar.GetYear(now);						month = calendar.GetMonth(now);						day = calendar.GetDayOfMonth(now);					}					else					{						// Use Gregorian 01/01/0001 as the date portion.						return new DateTime							(1, 1, 1, hour, minute, second, fractions / 10000);					}				}				else if(day == 0)				{					// Probably a "year month" format.					day = 1;				}				DateTime value;				try				{					value = calendar.ToDateTime						(year, month, day, hour, minute, second,						 fractions / 10000, era);				}				catch(Exception)				{					// The calendar didn't like the date/time value,					// so assume that it could not be parsed correctly.					throw new FormatException();				}				if((style & DateTimeStyles.AdjustToUniversal) != 0)				{					value = value.ToUniversalTime();				}				return value;			}	// Parse a DateTime value, using exact format information.	public static DateTime ParseExact(String s, String[] formats,									  IFormatProvider provider,									  DateTimeStyles style)			{				DateTimeFormatInfo info;				int posn;				// Validate the parameters.				if(s == null)				{					throw new ArgumentNullException("s");				}				if(formats == null)				{					throw new ArgumentNullException("formats");				}				for(posn = 0; posn < formats.Length; ++posn)				{					if(formats[posn] == null)					{						throw new ArgumentNullException							("formats[" + posn.ToString() + "]");					}					else if(formats[posn] == String.Empty)					{						throw new FormatException(_("Format_Empty"));					}				}				// Get the date time format information from the provider.				info = DateTimeFormatInfo.GetInstance(provider);				// Strip white space from the incoming string.				if((style & DateTimeStyles.AllowLeadingWhite) != 0)				{					s = s.TrimStart(null);				}				if((style & DateTimeStyles.AllowTrailingWhite) != 0)				{					s = s.TrimEnd(null);				}				if(s == String.Empty)				{					throw new FormatException						(_("ArgRange_StringNonEmpty"));				}				// Process each of the formats in turn.  We may need				// to recursively re-enter ParseExact if single-letter				// format characters are used within the list.				for(posn = 0; posn < formats.Length; ++posn)				{					try					{						if(formats[posn].Length == 1)						{							return ParseExact								(s, info.GetAllDateTimePatterns										(formats[posn][0]), info, style);						}						else						{							return TryParse								(s, formats[posn], info, style);						}					}					catch(FormatException)					{						// Didn't match this format.  Try the next one.					}				}				// If we get here, then we were unable to parse the string.				throw new FormatException(_("Format_DateTime"));			}	// Parse a DateTime value, using any format type.	public static DateTime Parse(String s, IFormatProvider provider,								 DateTimeStyles style)			{				DateTimeFormatInfo info;				info = DateTimeFormatInfo.GetInstance(provider);				return ParseExact					(s, info.GetAllDateTimePatterns(), info, style);			}}; // class DateTimeParser}; // namespace System.Private.DateTimeFormat

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?