System.directory

xiaoxiao2021-03-06  195

/ / == ==

//

//

// Copyright (C) 2002 Microsoft Corporation. All Rights Reserved.

//

// the use and distribution terms for this Software Are Contained in The File

// Named license.txt, Which can be found in the root of this distribution.

// by using this software in any fashion, you are agreeing to be bound by the

// Terms of this license.

//

// You Must Not Remove this Notice, or Any Other, from this software.

//

//

/ / == - ==

//

// Class: DateTimeParse

//

//

// purpose: this class is called by datetime to parse a date / time string.

//

// Date: July 8, 1999

//

Namespace system {

Using system;

Using system.text;

USING SYSTEM.GLOBALIZATION;

Using system.threading;

Using system.collections;

/ *

Notenote:

There Are Some Nasty Cases in The Parsing of Date / Time:

0x438 fo (Country: Faeroe Islands, LANGUGE: FAEROESE)

Locale_stime = [.]

Locale_stimeFor = [HH.MM.SS]

Locale_sdate = [-]

Locale_sshortdate = [DD-MM-YYYY]

Locale_slongdate = [d. Mmmm yyyy]

The Time Separator is ".", However, IT Also Has A "." In the long date format.

0x437: (Country: Georgia, LANGUGE: Georgian)

Short date: dd.mm.yy

Long Date: YYYY ???? DD MM, DDDD

.

0x0404: (Country: taiwan, languge: Chinese)

Locale_stimeformat = [TT HH: mm: SS]

When General Date Is Used, The Pattern Is "YYYY / M / D TTH: MM: SS". Note That The "TT" is after "YYYY / M / D".

And this is different from motult.

0x0437: (Country: Georgia, LANGUGE: Georgian)

Short date: dd.mm.yy

Long Date: YYYY ???? DD MM, DDDD

0x0456:

* /

/ *

* /

// this class contains Only Static Members and does Not Require The Serializable Attribute.

Internal

Class datetimeparse {

Private static string alternativedomDateseparator = "-";

Private static datetimeformatinfo invariantinfo = datetimeformatinfo.invariantinfo;

//

// this is used to cache the limited amount Month Names of the invariant culture.

//

Private static string [] invariantMonthnames = null;

Private static string [] invariantabbrevmonthnames = null;

//

// this is used to cache the thinger-canceled day names of the invariant culture.

//

Private static string [] invariantdayNames = null;

Private static string [] invariantabbrevdaynames = null;

Private static string invariantamdesignator = invariantIntinfo.amdesignator;

Private static string invariantpmdesignator = invariantinfo.pmdesignator;

Private static datetimeformatinfo m_jajpdtfi = NULL;

Private static datetimeformatinfo m_zhtwdtfi = NULL;

Internal Static DateTime Parsexact (String S, String Format, DateTimeFormatinfo DTFI, DateTimeStyles Style) {

IF (s == null || Format == null) {

Throw new argumentnullexception ((s == null? "s": "format"),

Environment.getResourceString ("argumentnull_string"))));

}

IF (s.length == 0) {

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

IF (Format.length == 0) {

Throw new formatexception (Environment.GetResourceString ("Format_badFormatspecifier));

}

IF (DTFI == Null)

{

DTFI = DateTimeFormatinfo.currentInfo;

}

DateTime Result;

IF (DostrictParse (S, Format, Style, DTFI, TRUE, OUT RESULT) {

Return (Result);

}

//

// this is Just Used to Keep Compiler Happy.// This Is Because Dostrike () Alwyas Does Either:

// 1. Return True OR

// 2. Throw Exceptions if there is error in paarsing.

// So We will never get here.

//

Return (New DateTime ());

}

Internal static bool parseexactmultiple (string s, string [] Formats,

DateTimeformatinfo DTFI, DateTimeStyles Style, Out DateTime Result) {

IF (s == null || Formats == null) {

Throw new argumentnullexception ((s == NULL? "S": "formats"),

Environment.getResourceString ("argumentnull_string"))));

}

IF (s.length == 0) {

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

IF (Formats.Length == 0) {

Throw new formatexception (Environment.GetResourceString ("Format_badFormatspecifier));

}

IF (DTFI == NULL) {

DTFI = DateTimeFormatinfo.currentInfo;

}

//

// do a loop through the provided formats and see if we can parse succesfully in

// one of the formats.

//

For (int i = 0; i

IF (Formats [i] == NULL || Formats [i] .length == 0) {

Throw new formatexception (Environment.GetResourceString ("Format_badFormatspecifier));

}

IF (DostrictParse (S, Formats [I], Style, DTFI, False, Out Result) {

Return (TRUE);

}

}

Result = new datetime (0);

Return (False);

}

//

// Separator Types

//

Private const INT SEP_UNK = 0; // Unknown Separetor.

Private const INT SEP_END = 1; // The end of the parsing string.

Private const INT SEP_SPACE = 2; // Whitespace (Including CommA).

Private const INT SEP_AM = 3; // AM TIMEMARK.

Private const INT SEP_PM = 4; // PM Timemark.Private const INT SEP_DATE = 5; // Date Separe.

Private const INT SEP_TIME = 6; // Time Separator.

Private const INT SEP_YEARSUFF = 7; // Chinese / japanese / Korean year suffix.

Private const INT SEP_MONTHSUFF = 8; // Chinese / Japanese / Korean Month Suffix.

Private const INT SEP_DAYSUFF = 9; // Chinese / Japanese / Korean Day SUFFIX.

Private const INT SEP_HOURSUFF = 10; // Chinese / japanese / Korean Hour Suffix.

Private const INT SEP_MINUTESUFF = 11; // Chinese / japanese / Korean Minute SUFFIX.

Private const INT SEP_SECONDSUFF = 12; // chinese / japanese / Korean second suffix.

Private const INT SEP_LOCALTIMEMARK = 13; // 't'

Private const INT SEP_MAX = 14;

// Date Token Types (DTT_ *)

//

// Following is the set of tokens what can be generated from a date

// String. NOTICE That The Legal Set of Trailing Separators Have Been

// folded in with the date number, and month name tokens. this set

// of tokens is chosen to reduce the number of date parse states.

//

Private const INT DTT_END = 0; // '/ 0'

Private const Int DTT_NUMEND = 1; // Num [] * [/ 0]

Private const INT DTT_NUMAMPM = 2; // Num [] ampm

Private const Int DTT_NUMSPACE = 3; // Num [] ^ [DSEP | TSEP | '0 /']

Private const INT DTT_NUMDATESEP = 4; // Num [] * DSEP

Private const INT DTT_NUMTIMESEP = 5; // Num [] * TSEP

Private const Int DTT_MONTHEND = 6; // Month [] * '/ 0'

Private const Int DTT_MONTHSPACE = 7; // Month [] ^ [DSEP | TSEP | '/ 0']

Private const INT DTT_MONTHDATESEP = 8; // Month [] * DSEP

Private const Int dtt_numdateSUFF = 9; // Month [] * DSUFFPRIVATE const INT DTT_NUMTIMESUFF = 10; // Month [] * TSUFF

Private const Int dtt_dayofweek = 11; // days of week name

Private const Int DTT_YEARSPACE = 12; // Year ^ [DSEP | TSEP | '0 /']

Private const Int dtt_yeardatesep = 13; // year DSEP

Private const Int DTT_Yerend = 14; // Year ['/ 0']

Private const Int dtt_timezone = 15; // Timezone Name

PRIVATE const INT DTT_ERA = 16; // Era Name

Private constimail = 17; // Num 'Z'

// when add a new token which will be in the

// State Table, Add IT After DTT_NUMLOCALTIMEMARK.

Private const Int dtt_unk = 18; // unknown

Private const Int DTT_NUMLOCALTIMEMARK = 19; // Num 'T'

Private const Int DTT_MAX = 20; // Marker

Private const INTTM_AM = 0;

Private const INTTM_PM = 1;

//

// Year / Month / Day Suffixes

//

Private const string cjkyearsuff = "/ u5e74";

Private const string cjkmonthsuff = "/ u6708";

Private const string cjkdaysuff = "/ u65e5";

Private const string koreanyearsuff = "/ ub144";

Private const string Koreanmonthsuff = "/ uc6d4";

Private const string KoreandAysuff = "/ uc77c";

Private const string cjkhaiff = "/ u6642";

Private const string chinesehoursuff = "/ u65f6";

Private const string cjkminutesuff = "/ u5206";

Private const string cjksecondsuff = "/ u79d2";

Private const string Localtimemark = "t"; //

// DateTime Parsing State Enumeration (DS_ *)

//

Private const Int ds_begin = 0;

Private const Int ds_n = 1; // Have ONE NUMBER

Private const Int ds_nn = 2; // Have Two Numbers

// The folload area know to be part of a date

Private const Int DS_D_ND = 3; // Date String: Have Number Followed by Date Separetor

Private const INT DS_D_NN = 4; // Date String: Have Two Numbers

Private const Int DS_D_NND = 5; // Date String: Have Two Numbers Followed by Date Separator

Private const Int DS_D_M = 6; // Date String: Have A Month

PRIVATE CONST INT DS_D_MN = 7; // Date String: Have A Month and A Number

Private const INT DS_D_NM = 8; // Date String: Have a Number and A Month

Private const Int DS_D_MND = 9; // Date String: Have a month and number backed by date sepator

Private const INT DS_D_NDS = 10; // Date String: Have ONE NUMBER FOLLOWED A DATE SUFFIX.

Private const INT DS_D_Y = 11; // Date String: Have a year.

Private const Int DS_D_YN = 12; // Date String: Have a year and a number

Private const Int DS_D_YM = 13; // Date String: Have a year and a month

Private const Int DS_D_S = 14; // Have Numbers Followed by a date suffix.

Private const INT DS_T_S = 15; // Have Numbers Followed by a time suffix.

// the folowing area known to be part of a time

Private const Int DS_T_NT = 16; // Have Num Followed by Time Separator

Private const Int DS_T_NNT = 17; // Have Two Numbers Followed by Time Separator

PRIVATE CONST INT DS_ERROR = 18;

// The folload is Terminal State. Thase All Have an Action

// Associated with them; and transition back to ds_begin.

Private const Int DS_DX_NN = 19; // days from two Numbers

Private const Int DS_DX_NNN = 20; // days from three Numbers

Private const Int DS_DX_MN = 21; // days from month and one number

Private const INT DS_DX_NM = 22; // days from month and one number

Private const Int DS_DX_MNN = 23; // days from month and two Numbers

Private const INT DS_DX_DS = 24; // a set of date suffixed numbers.

PRIVATE CONST INT DS_DX_DSN = 25; // Day from date suffixes and one number.

Private const INT DS_DX_NDS = 26; // day from one number and date suffixes.

Private const Int ds_dx_nnds = 27; // days from one number and date suffixes.

Private const Int DS_DX_YNN = 28; // Date String: Have a year and two Number

Private const Int DS_DX_YMN = 29; // Date String: Have a year, a month, and a number.

Private const Int DS_DX_YN = 30; // Date String: Have a year and one number

Private const Int ds_dx_ym = 31; // Date String: Have a year, a month.

Private const Int DS_TX_N = 32; // Time from One Number (Must Have Ampm)

Private const Int DS_TX_NN = 33; // Time from Two Numbers

Private const Int DS_TX_NNN = 34; // Time from Three Numbers

Private const INT DS_TX_TS = 35; // a set of time suffixed number.

PRIVATE CONST INT DS_DX_NNY = 36;

Private const Int ds_max = 37; // marker: end of enum

//

// Note: The Following State Machine Table Is Dependent on The Order of The Folk

// ds_ and dtt_ enumerations.//

// for Each Non Terminal State, The Following Table Defines The Next State

// for Each Given Date Token Type.

//

// DTT_END DTT_NUMEND DTT_NUMAMPM DTT_NUMSPACE

// DTT_NUMDAYSEP

// DTT_NUMTIMESEP

// DTT_MONTHEND DTT_MONTHSPACE

// DTT_MONTHDSEP

// dtt_numdatesisuff

// DTT_NUMTIMESUFF DTT_DAYOFWEEK

// DTT_YearSpace

// DTT_YEARDATESEP

// dtt_yerend,

// DTT_TIMEZONE

// DTT_ERA DTT_UTCTIMEMARKPRIVATETIC INT [] [] DateParsingStates = {

// ds_begin // DS_BEGIN

NEW INT [] {DS_BEGIN, DS_ERROR, DS_TX_N, DS_N, DS_D_ND, DS_T_NT, DS_ERROR, DS_D_M, DS_D_M, DS_D_S, DS_T_S, DS_BEGIN, DS_D_Y, DS_D_Y, DS_ERROR, DS_BEGIN, DS_BEGIN, DS_ERROR},

// ds_n // ds_n

NEW INT [] {DS_ERROR, DS_DX_NN, DS_ERROR, DS_NN, DS_D_NND, DS_ERROR, DS_DX_NM, DS_D_NM, DS_D_MND, DS_D_NDS, DS_ERROR, DS_N, DS_D_YN, DS_D_YN, DS_DX_YN, DS_N, DS_N, DS_ERROR},

// ds_nn // ds_nn

new int [] {DS_DX_NN, DS_DX_NNN, DS_TX_N, DS_DX_NNN, DS_ERROR, DS_T_Nt, DS_DX_MNN, DS_DX_MNN, DS_ERROR, DS_ERROR, DS_T_S, DS_NN, DS_DX_NNY, DS_ERROR, DS_DX_NNY, DS_NN, DS_NN, DS_ERROR},

// DS_D_ND / / DS_D_ND

// new int [] {DS_ERROR, DS_DX_NN, DS_ERROR, DS_D_NN, DS_D_NNd, DS_ERROR, DS_DX_MN, DS_D_MN, DS_D_MNd, DS_ERROR, DS_ERROR, DS_D_Nd, DS_D_YN, DS_D_YN, DS_DX_YN, DS_ERROR, DS_D_Nd, DS_ERROR},

new int [] {DS_ERROR, DS_DX_NN, DS_ERROR, DS_D_NN, DS_D_NNd, DS_ERROR, DS_DX_NM, DS_D_MN, DS_D_MNd, DS_ERROR, DS_ERROR, DS_D_Nd, DS_D_YN, DS_D_YN, DS_DX_YN, DS_ERROR, DS_D_Nd, DS_ERROR}, // DS_D_NN // DS_D_NN

new int [] {DS_DX_NN, DS_DX_NNN, DS_TX_N, DS_DX_NNN, DS_ERROR, DS_T_Nt, DS_DX_MNN, DS_DX_MNN, DS_ERROR, DS_DX_DS, DS_T_S, DS_D_NN, DS_DX_NNY, DS_ERROR, DS_DX_NNY, DS_ERROR, DS_D_NN, DS_ERROR},

// DS_D_NND / / DS_D_NND

new int [] {DS_ERROR, DS_DX_NNN, DS_DX_NNN, DS_DX_NNN, DS_DX_NNN, DS_ERROR, DS_DX_MNN, DS_DX_MNN, DS_ERROR, DS_DX_DS, DS_ERROR, DS_D_NNd, DS_DX_NNY, DS_ERROR, DS_DX_NNY, DS_ERROR, DS_D_NNd, DS_ERROR},

// DS_D_M / / DS_D_M

NEW INT [] {DS_ERROR, DS_DX_MN, DS_ERROR, DS_D_MN, DS_D_MND, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_D_M, DS_D_YM, DS_D_YM, DS_DX_YM, DS_ERROR, DS_D_M, DS_ERROR},

// DS_D_MN / / DS_D_MN

new int [] {DS_DX_MN, DS_DX_MNN, DS_DX_MNN, DS_DX_MNN, DS_DX_MNN, DS_T_Nt, DS_ERROR, DS_ERROR, DS_ERROR, DS_DX_DS, DS_T_S, DS_D_MN, DS_DX_YMN, DS_DX_YMN, DS_DX_YMN, DS_ERROR, DS_D_MN, DS_ERROR},

// DS_D_NM / / DS_D_NM

new int [] {DS_DX_NM, DS_DX_MNN, DS_DX_MNN, DS_DX_MNN, DS_ERROR, DS_T_Nt, DS_ERROR, DS_ERROR, DS_ERROR, DS_DX_DS, DS_T_S, DS_D_NM, DS_DX_YMN, DS_ERROR, DS_DX_YMN, DS_ERROR, DS_D_NM, DS_ERROR}, // DS_D_MNd // DS_D_MNd

// new int [] {DS_ERROR, DS_DX_MNN, DS_ERROR, DS_DX_MNN, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_D_MNd, DS_DX_YMN, DS_ERROR, DS_DX_YMN, DS_ERROR, DS_D_MNd, DS_ERROR},

new int [] {DS_DX_MN, DS_DX_MNN, DS_ERROR, DS_DX_MNN, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_D_MNd, DS_DX_YMN, DS_ERROR, DS_DX_YMN, DS_ERROR, DS_D_MNd, DS_ERROR},

// ds_d_nds, // ds_d_nds,

new int [] {DS_DX_NDS, DS_DX_NNDS, DS_DX_NNDS, DS_DX_NNDS, DS_ERROR, DS_T_Nt, DS_ERROR, DS_ERROR, DS_ERROR, DS_D_NDS, DS_T_S, DS_D_NDS, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_D_NDS, DS_ERROR},

// DS_D_Y / / DS_D_Y

NEW INT [] {DS_ERROR, DS_ERROR, DS_ERROR, DS_D_YN, DS_D_YN, DS_ERROR, DS_DX_YM, DS_D_YM, DS_D_YM, DS_D_YM, DS_ERROR, DS_D_Y, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_D_Y, DS_ERROR},

// DS_D_YN / / DS_D_YN

new int [] {DS_ERROR, DS_DX_YNN, DS_DX_YNN, DS_DX_YNN, DS_DX_YNN, DS_ERROR, DS_DX_YMN, DS_DX_YMN, DS_ERROR, DS_ERROR, DS_ERROR, DS_D_YN, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_D_YN, DS_ERROR}, // DS_D_YM // DS_D_YM

new int [] {DS_DX_YM, DS_DX_YMN, DS_DX_YMN, DS_DX_YMN, DS_DX_YMN, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_D_YM, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_D_YM, DS_ERROR},

// DS_D_S // DS_D_S

NEW INT [] {DS_DX_DS, DS_DX_DSN, DS_TX_N, DS_T_NT, DS_ERROR, DS_T_NT, DS_ERROR, DS_ERROR, DS_ERROR, DS_D_S, DS_T_S, DS_D_S, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_D_S, DS_ERROR},

// DS_T_S // DS_T_S

NEW INT [] {DS_TX_TS, DS_TX_TS, DS_TX_TS, DS_T_NT, DS_D_ND, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_D_S, DS_T_S, DS_T_S, DS_ERROR, DS_ERROR, DS_ERROR, DS_T_S, DS_T_S, DS_T_S, DS_T_S, DS_ERROR},

// DS_T_NT / / DS_T_NT

// new int [] {DS_ERROR, DS_TX_NN, DS_TX_NN, DS_TX_NN, DS_ERROR, DS_T_NNt, DS_ERROR, DS_D_NM, DS_ERROR, DS_ERROR, DS_T_S, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_T_Nt, DS_T_Nt, DS_TX_NN},

new int [] {DS_ERROR, DS_TX_NN, DS_TX_NN, DS_TX_NN, DS_ERROR, DS_T_NNt, DS_DX_NM, DS_D_NM, DS_ERROR, DS_ERROR, DS_T_S, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_T_Nt, DS_T_Nt, DS_TX_NN}, // DS_T_NNt // DS_T_NNt

new int [] {DS_ERROR, DS_TX_NNN, DS_TX_NNN, DS_TX_NNN, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_ERROR, DS_T_S, DS_T_NNt, DS_ERROR, DS_ERROR, DS_ERROR, DS_T_NNt, DS_T_NNt, DS_TX_NNN},

}

// end numend Numampm Numspace Numdaysep NumTimesep Monthend Monthspace Monthdsep NumdateSuff NumtimeSuff Dayofweek Yearspace YeardateseP Yearend

Private const String gmtname = "gmt";

Private const string zuluname = "z";

//

// Search from the index of str at str .index to see letter the target string exissrs in the str.

//

// AllowPartialMatch: if true, the method will not check if the matching string

// is in a word boundary, and will skip to the word boundary.

// for example, it will return true for match "january" in "januaryfoo".

// if false, The matching word must be in a word boundary. So it will return

// false for matching "january" in "januaryfoo".

//

Private Static Bool Matchword (__ DTString Str, String Target, Bool AllowPartialmatch)

{

INT length = target.length;

IF (str.value.length - str.index) {

Return False;

}

IF (CultureInfo.currentculture.CompareInfo.compare (Str.Value,

Str.index,

Length,

Target,

0,

Length,

CompareOptions.Ignorecase! = 0) {

Return (False);

}

INT nextcharindex = str.index target.length; if (allowpartialmatch)

{

//

// Skip the remaining part of the word.

//

// this is to ignore special carated:

// a Few Cultures Has Suffix After MMMM, Like "FI" and "EU".

While (nextcharindex

{

IF (! char.ietter (str.value [nextcharindex))

{

Break;

}

Nextcharindex ;

}

} else {

NextCharindex

Char nextchch = str.value [nextcharindex];

IF (char.isletter (nextch) || nextch == '/ x00a1') {

// the '/ x00a1' is a very unfortunate Hack, Since

// GL-ES (0x0456) Used '/ x00a1' in their day of week names.

// and '/ x00a1' is a puctuation. This Breaks OUR

// Assumption That there is no non-letter characters

// Following a day / month name.

Return (False);

}

}

}

Str.index = nextcharindex;

Return (TRUE);

}

//

// Starting At Str.index, Check The Type of The Separetor.

//

Private Static Int GetSeparator (__ DTString Str, DateTimeRawinfo Raw, DateTimeFormatinfo DTFI) {

INT SEPARATOR = Sep_Space; // Assume The Separetor Is A Space. And try to find a better one.

//

// Check if We found any White spaces.

//

IF (! Str.skipwhitespaceComma ()) {

//

// SkipwhitespaceComma () Will Return True when End of string is reached.

//

//

// Return The Separetor AS Sep_end.

//

Return (SEP_END);

}

IF (char.isletter (str.getchar ())) {

//

// this is a beginning of a word.

//

IF (raw.timemark == -1)

{

//

// Check if this is an am Time Mark.

//

Int Timemark;

IF ((Timemark = GetTimemark (STR, DTFI))! = -1)

{

Raw.timemark = TIMEMARK ;;

RETURN (TIMEMARK == TM_AM? SEP_AM: SEP_PM);

}

}

IF (Matchword (Str, Localtimemark, False) {separator = sep_localtimemark;

Else IF (Matchword (Str, CJKYEARSUFF, FALSE) || Matchword (Str, KoreAnyEarsuff, false) {

Separator = sep_yearsuff;

}

Else IF (Str, Cjkmonthsuff, False) || Matchword (Str, KoreanMonthsuff, False))

{

Separator = SEP_MONTHSUFF;

}

Else IF (Str, Cjkdaysuff, False) || Matchword (Str, KoreAndaysuff, False)

{

Separator = sep_daysuff;

}

Else IF (MatchWord (Str, Cjkhoursuff, False) || Matchword (Str, ChineseHoursuff, False)

{

Separator = sep_hoursuff;

}

Else IF (Matchword (Str, CjkminuteSuff, False)

{

Separator = sep_minutesuff;

}

Else IF (Matchword (Str, Cjksecondsuff, False)

{

Separator = SEP_SECONDSUFF;

}

} else {

//

// NOT a letter. Check if this is a date sepator.

//

IF ((Matchword (Str, DTFI.DATESEPARATOR, FALSE) ||

(MatchWord (Str, InvariantIntinfo.dateseParator, False) ||

(MatchWord (Str, AlternativeDateSeparator, False))))

{

//

// Notenote: AlternativeDateseParetor is a Special Case Because Some Cultures

// (E.G. THE INVARIANT CULTURE) USE "/" .EVER, IN RFC Format, We Use "-" as The

// Date Separator. Therefore, We Should Check for IT.

//

Separator = sep_date;

}

//

// Check if this is a time separator.

//

Else IF ((Matchword (Str, DTFI.TIMESEPARATOR, FALSE) ||

(Matchword (STR, InvariantIntinfo.timeseparator, False))))

{

Separator = SEP_TIME;

} else if (DTFI.CULTUREID == 0x041c) {

// Special Case for SQ-Al (0x041c)

// ITS Time Pattern IS "H: mm: ss.tt"

IF (str.getchar () == '.') {

IF (raw.timemark == -1)

{

//

// Check if this is an am Time Mark.

//

Int Timemark;

Str.Index ; IF ((Timemark = GetTimemark (STR, DTFI))! = -1)

{

Raw.timemark = TIMEMARK ;;

RETURN (TIMEMARK == TM_AM? SEP_AM: SEP_PM);

}

Str.index -;

}

}

}

}

Return (separator);

}

//

// Check The Word At The Current Index To See IT Matches A Month Name.

// Return -1 if a match is not found. OtherWise, a value from 1 to 12 is returned.

//

Private static int GETMONTHNUMBER (__ DTSTRING STR, DATETIMEFORMATINFO DTFI)

{

//

// Check The Month name specified in DTFI.

//

INT I;

INT MONTHINYEAR = (DTFI.GETMONTHNAME (13) .length == 0? 12: 13);

INT MAXLEN = 0;

Int results = -1;

Int index;

String word = str.peekcurrentword ();

//

// we have to match the Month name with the longest length,

// Since There Are Cultures Which Have More Than One Month Names

// with the same prefix.

//

For (i = 1; i <= monthinyear; i ) {

String Monthname = DTFI.GETMONTHNAME (i);

IF ((INDEX = Str.comPareInfo.indexof)

Word, MonthName, CompareOptions.Ignorecase))> = 0) {

// this condition allows us to Parse the Month Name for:

// 1. The General Cases Like "YYYY MMMM DD".

// 2. Prefix in the Month Name Like: "DD '/ X05D1'mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm YYYY" (Hebrew - Israel)

Result = i;

Maxlen = Index Monthname.LENGTH;

} else IF (Str.StartSwith (Monthname, True) {

// the condition allows us to get the Month Name for Cultures

// Which Has Spaces in Their Month Names.

// E.G.G.

IF (Monthname.Length> maxlen) {

Result = i;

Maxlen = MONTHNAME.LENGTH;

}

}

}

IF (Result> -1) {

Str.index = maxlen;

Return (Result);

}

For (i = 1; i <= monthinyear; i )

{

IF (Matchword (Str, DTFI.GetabbreviatedMonthname (i), false) {

Return (i);

}

}

//

// Check the Month name in the invariant culture.

//

For (i = 1; i <= 12; i )

{

IF (MatchWord (Str, InvariantIntinfo.getMonthname (i), false)

{

Return (i);

}

}

For (i = 1; i <= 12; i )

{

IF (Matchword (Str, InvariantIntinfo.getabbreviatedMonthname (i), FALSE))

{

Return (i);

}

}

Return (-1);

}

//

// Check The Word At The Current Index To See IT Matches a day of week name.

// Return -1 if a match is not found. Otherwise, a value from 0 to 6 is returned.

//

Private static int getdayofweeknumber (__ dtstring str, datetimeformatinfo dtfi) {

//

// Check The Month name specified in DTFI.

//

Dayofweek i;

INT MAXLEN = 0;

Int results = -1;

//

// we have to match the day name with the longeest length,

// Since There Are Cultures Which Have More Than One Day of Week Names

// with the same prefix.

//

INT endindex = str.findendofcurrentword ();

String dayName = null;

For (i = dayofweek.sunday; i <= dayofweek.saturday; i ) {

DayName = dtfi.getdayname (i);

IF (str.matchspecifiedword (dayname, endindex) {

IF (DAYNAME.LENGTH> MAXLEN) {

Result = (int) i;

Maxlen = dayname.length;

}

}

}

IF (Result> -1) {

Str.index = endindex;

Return (Result);

}

For (i = dayofweek.sunday; i <= dayofweek.saturday; i )

{

IF (Matchword (STR, DTFI.GetabbreviatedDayname (i), false)

{

Return (INT) i);

}

}

//

// Check the Month name in the invariant culture.

//

For (i = dayofweek.sunday; i <= dayofweek.saturday; i )

{

IF (Matchword (Str, InvariantIntinfo.getDayName (i), false)

{

Return (INT) i);

}

}

For (i = dayofweek.sunday; i <= dayofweek.saturday; i )

{

IF (Matchword (Str, InvariantIntinfo.getabBBBREVIATEDDAYNAME (I), FALSE)

{

Return (INT) i);

}

}

Return (-1);

}

//

// Check The Word At The Current Index To See IT Matches Gmt Name or Zulu Name.

//

Private static bool gettimezonename (__ dtstring str)

{

//

//

IF (Matchword (Str, GMTNAME, FALSE) {

Return (TRUE);

}

IF (Matchword (Str, Zuluname, False) {

Return (TRUE);

}

Return (False);

}

//

// Create a Japanese DTFI Which Uses JapaneseCalendar. This is buy to pie

// Date String with Japanese Era Name Correctly Even WHEN THE Supplied DTFI

// Does Not Use Japase Calendar.

// The created instance is stored in global m_jajpdtfi.

//

Private static void getjapanesecalendardtfi () {

// Check Calendar.id Specification To Avoid A Lock Here.

IF (m_jajpdtfi == null || m_jajpdtfi.calendar.id! = Calendar.cal_japan) {

m_jajpdtfi = New CultureInfo ("JA-JP", FALSE) .DATETIMEFORMAT;

M_jajpdtfi.calendar = japanesecalendar.getDefault ();

}

}

//

// Create a Taiwan DTFI Which Uses Taiwancalendar. This is buy to pie

// Date string with Era Name Correctly Even WHEN THE Supplied DTFI

// does not use use taiwan calendar.

// The created instance is stored in global m_zhtwdtfi.

//

Private static void gettaiwancalendardtfi () {

// Check Calendar.id Specification To Avoid A Lock Here.

IF (m_zhtwdtfi == null || m_zhtwdtfi.calendar.id! = Calendar.cal_taiwan) {

m_zhtwdtfi = New CultureInfo ("ZH-TW", FALSE) .DATETIMEFORMAT;

M_zhtwdtfi.calendar = taiwancalendar.getDefaultInstance ();

}

}

Private static int getra (__ dtstring str, datetimeresult result, ref datetimeformatinfo DTFI) {int [] eras = dtfi.calendar.ras;

IF (ERAS! = null) {

String word = str.peekcurrentword ();

Int ERA;

IF ((Era = DTFI.Getera (Word)> 0) {

Str.index = word.length;

Return (ERA);

}

Switch (DTFI.CULTUREID) {

Case 0x0411:

// 0x0411 is The culture id for japanese.

IF (DTFI.CALENDAR.ID! = Calendar.cal_japan) {

// if The Calendar for DTFI Is Japanese, We Have Already

// done the check Above. No need to re-check again.

GetJapanesecalendTfi ();

IF ((Era = m_jajpdtfi.Getera (Word))> 0) {

Str.index = word.length;

Result.calendar = Japanesecalendar.getDefaultInstance ();

DTFI = m_jajpdtfi;

Return (ERA);

}

}

Break;

Case 0x0404:

// 0x0404 is The culture id for taiwan.

IF (dtfi.calendar.id! = calendar.cal_taiwan) {

GettaiwancalendardTfi ();

IF ((Era = m_zhtwdtfi.Getera (Word))> 0) {

Str.index = word.length;

Result.calendar = taiwancalendar.getDefaultInstance ();

DTFI = m_zhtwdtfi;

Return (ERA);

}

}

Break;

}

}

Return (-1);

}

Private static int gettimemark (__ dTString str, datetimeformatinfo dtfi) {

IF ((DTFI.Amdesignator.length> 0) && Matchword (Str, DTFI.Amdesignator, False) || Matchword (Str, InvariantamDesignator, False)

{

Return (TM_AM);

}

Else IF ((DTFI.Pmdesignator.Length> 0) && Matchword (Str, DTFI.PmDesignator, False) || Matchword (Str, InvariantPmdesignator, False))

{

//

// Check if this is an pm time mark.

//

Return (TM_PM);

}

Return (-1);

}

INTERNAL Static Bool Isdigit (Char CH) {

//

//How do we map full-width char

Return (CH> = '0' && ch <= '9');

/ * ================================= PARSEFRAction =============== ============

** Action: Starting At The str.index, if The Current Character Is A Digit, Parse The Remaining

** Numbers as fraction. for example, if the sub-string starting at str.index is "123", THEN

** The Method Will Return 0.123

** Returns: The Fraction Number.

** arguments:

** Str the Parsing String

** Exceptions:

============================================================================================================================================================================================================= =========================== * /

Private static double parsefraction (__ dTString str) {

Double result = 0;

Double DecimalBase = 0.1;

CHAR CH;

While (str.index <= str.len-1 && isdigit (ch = str.value [str.index])) {

Result = (CH - '0') * Decimalbase;

Decimalbase * = 0.1;

Str.Index ;

}

Return (Result);

}

/ * ================================= Parsetimezone =============== ============ ** Action: Parse the Timezone Offset in The Following Format:

** " 8", " 08", " 0800", " 0800"

** this method is buy by datetime.parse ().

** RETURns: The Timezone Offset.

** arguments:

** Str the Parsing String

** Exceptions:

** Formatexception if INVALID TIMEZONE FORMAT IS FOUND.

============================================================================================================================================================================================================= =========================== * /

Private static Timespan Parsetimezone (__ dTString str, char offsetchar) {

// The Hour / Minute Offset for Timezone.

INT HOUROFFSET = 0;

INT minuteOffset = 0;

IF (str.getnextdigit ()) {

// Get the first Digit, Try if We can Paarse Timezone in The Form of " 8".

Houroffset = str.getdigit ();

IF (str.getnextdigit ()) {

// Parsing " 18"

Houroffset * = 10;

Houroffset = str.getdigit ();

IF (str.getnext ()) {

CHAR CH;

IF (char.isdigit (ch = str.getchar ())) {

// PARSING " 1800"

// Put The Char Back, Since We Already Get The Char in The Previous GetNext () Call.

Str.index -;

IF (Parsedigits (Str, 2, True, Out MinuteOffset) {// pasedigits () Does Not Advance The Char for US, SO do It here.

Str.Index ;

} else {

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

} else if (ch == ':') {

// Parsing " 18: 00"

IF (Parsedigits (STR, 2, True, Out MinuteOffset) {

Str.Index ;

} else {

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

} else {

// NOT A DIGIT, NOT A Colon, Put this char back.

Str.index -;

}

}

}

// the next char is not a digit, so we get the timezone in the form of " 8".

} else {

// Invalid Timezone: no number after /-.

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

TimeSpan TimezoneOffset = New TimeSpan (Houroffset, MinuteOffset, 0);

IF (OffsetChar == '-') {

Timezoneoffset = timezoneoffset.negate ();

}

Return (TimezoneOffset);

}

//

// 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, __DTSTSTRING STR, DATETITOKEN 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 Separetor after Month Name

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

Raw.month = month;

}

Else if (Raw.dayofwek == -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 "for zulu time).

//

DTOK.DTT = DTT_TIMEZONE;

Result.timezoneused = true;

Result.timezoneoffset = new timeespan (0);

} else IF ((Raw.era == -1) && ((Era = getra (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 buy to deal case Like Spanish Cultures, Which

// Uses 'de' in Their Date String.

//

//

IF (! Str.matchwords) {

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 prepious paingsing 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 prepious paingsing 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 et ly the folowing 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

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 name which has 3 or more Digits (Like "001" 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_YAARDATESEP;

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 THREE.

// WHEN WE HAVE MORE 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

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_NUMLOCALTIMARK;

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;

}

Private const Int ORDER_YMD = 0; // the order of date is year / month / day.

Private const Int ORDER_MDY = 1; // The Order of Date is Month / Day / Year.

Private const Int ORDER_DMY = 2; // The Order of Date is day / month / year.

Private const Int ORDER_YDM = 3; // The Order of Date is Year / Day / Month

Private const Int ORDER_YM = 4; // Year / Month Order.

Private const Int ORDER_MY = 5; // Month / Year ORDER.

Private const Int ORDER_MD = 6; // Month / Day Order.

Private const Int ORDER_DM = 7; // day / month Order.

//

// DECIDE The year / month / day order from the datepattern.

//

// Return 0 for YMD, 1 for MDY, 2 for DMY, OtherWise -1.

//

Private static int getYearMonthdayorder (String DatePattern, DateTimeFormatinfo DTFI)

{

Int yearorder = -1;

INT MONTHORDER = -1;

INT dayorder = -1;

Int ORDERCOUNT = 0;

BOOL Inquote = false;

For (int i = 0; i

{

Char ch = datepattern [i];

IF (CH == '/' '|| CH ==' ")

{

Inquote =! Inquote;

}

IF (! inquote)

{

IF (CH == 'Y')

{

Yearorder = OrderCount ;

//

// Skip all year pattern charatrs.

//

For (; i 1

{

// do nothing here.

}

}

ELSE IF (CH == 'M')

{

Monthorder = OrderCount ;

//

// Skip all Month Pattern Characters.

//

For (; i 1

{

// do nothing here.

}

}

Else IF (CH == 'D')

{

INT patterncount = 1;

//

// Skip all day pattern characters.

//

For (; i 1

{

Patterncount ;

}

//

// Make Sure this is not "DDD" or "dddd", Which means day of week.

//

IF (Patterncount <= 2)

{

Dayorder = Ordercount ;

}

}

}

}

IF (Yearorder == 0 && Monthorder == 1 && dayorder == 2)

{

Return (ORDER_YMD);

}

IF (Monthorder == 0 && dayorder == 1 && yearorder == 2) {

Return (ORDER_MDY);

}

IF (Dayorder == 0 && Monthorder == 1 && Yearorder == 2)

{

Return (ORDER_DMY);

}

IF (Yearorder == 0 && Dayorder == 1 && Monthorder == 2)

{

Return (ORDER_YDM);

}

Throw new formatexception (String.Format (Environment.GetResourceString ("format_baddatepattern"); DatePattern);

}

//

// Decide the year / month ORDER from the pattern.

//

// Return 0 for YM, 1 for my, OtherWise -1.

//

Private Static Int GetYarmonthORDER (String Pattern, DateTimeformatinfo DTFI)

{

Int yearorder = -1;

INT MONTHORDER = -1;

Int ORDERCOUNT = 0;

BOOL Inquote = false;

For (int i = 0; i

{

Char ch = pattern [i];

IF (CH == '/' '|| CH ==' ")

{

Inquote =! Inquote;

}

IF (! inquote)

{

IF (CH == 'Y')

{

Yearorder = OrderCount ;

//

// Skip all year pattern charatrs.

//

For (; i 1

{

}

}

ELSE IF (CH == 'M')

{

Monthorder = OrderCount ;

//

// Skip all Month Pattern Characters.

//

For (; i 1

{

}

}

}

}

IF (Yearorder == 0 && Monthorder == 1)

{

Return (ORDER_YM);

}

IF (Monthorder == 0 && Yearorder == 1)

{

Return (ORDER_MY);

}

Throw new formatexception (sincevironment.get ("format_baddatepattern"), Pattern);

//

// Decide the Month / Day Order from the pattern.

//

// Return 0 for MD, 1 for DM, OtherWise -1.

//

Private static int GETMONTHDAYORDER (String Pattern, DateTimeFormatinfo DTFI)

{

INT MONTHORDER = -1;

INT dayorder = -1;

Int ORDERCOUNT = 0;

BOOL Inquote = false;

For (int i = 0; i

{

Char ch = pattern [i];

IF (CH == '/' '|| CH ==' ")

{

Inquote =! Inquote;

}

IF (! inquote)

{

IF (CH == 'D')

{

INT patterncount = 1;

//

// Skip all day pattern charatrs.

//

For (; i 1

{

Patterncount ;

}

//

// Make Sure this is not "DDD" or "dddd", Which means day of week.

//

IF (Patterncount <= 2)

{

Dayorder = Ordercount ;

}

}

ELSE IF (CH == 'M')

{

Monthorder = OrderCount ;

//

// Skip all Month Pattern Characters.

//

For (; i 1

{

}

}

}

}

IF (MonthOrder == 0 && dayorder == 1)

{

Return (ORDER_MD);

}

IF (Dayorder == 0 && Monthorder == 1)

{

Return (ORDER_DM);

}

Throw new formatexception (sincevironment.get ("Format_BaddatePattern"), Pattern);

}

Private Static Bool IsvalidMonth (DateTimeResult Result, Int Year, Int Month)

{

Return (Month> = 1 && Month <= result.calendar.getmonthsinyear (year));

//

// Notenote: this funciton assumes That year / month is the correct. So call isvalidmonth Before Calling this.

//

Private Static Bool Isvalidday (DatetimeResult Result, Int Year, Int Month, Int Day)

{

Return (day> = 1 && day <= result.calendar.getDaysinmonth (year, month));

}

//

// adjust the two-Digit year if Necessary.

//

Private static int adjuthear (DateTimeResult Result, int year)

{

IF (Year <100)

{

Year = result.calendar.tofourdigityear (year);

}

Return (Year);

}

Private Static Bool SetDateymd (DateTimeResult Result, Int Year, Int Month, Int Day)

{

IF (isvalidMont (Result, Year, Month) && Isvalidday (Result, Year, Month, DAY)

{

Result.SetDate (Year, Month, Day); // YMD

Return (TRUE);

}

Return (False);

}

Private Static Bool SetDatemdy (DateTimeResult Result, Int Month, Int Day, Int Year)

{

Return (SetD, Year, Month, DAY);

}

Private Static Bool SetDatedmy (DateTimeResult Result, Int Day, Int Month, Int Year)

{

Return (SetD, Year, Month, DAY);

}

Private static bool setdm (DateTimeResult Result, Int Year, Int Day, Int Month)

{

Return (SetD, Year, Month, DAY);

}

// processing Teriminal Case: DS_DX_NN

Private static void getdayofnn (DateTimeResult Result, DateTimeRawinfo Raw, DateTimeFormatinfo DTFI) {

INT N1 = Raw.NUM [0];

INT N2 = Raw.NUM [1];

Int year = result.calendar.getYear (datetime.now);

Int ORDER = GetMonthdayorder (DTFI.MOTHDAYPATTERN, DTFI);

IF (ORDER == Order_md)

{

IF (SetDateymd (Result, Year, N1, N2)) // MD

{

Return;

}

} else {// Order_dm

IF (SetD, Year, N2, N1)) // DM

{

Return;

}

}

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

// processing Teriminal Case: DS_DX_NNN

Private static void getdayofnnn (DateTimeResult Result, DateTimeRawinfo Raw, DateTimeFormatinfo DTFI)

{

INT N1 = Raw.NUM [0];

INT N2 = Raw.NUM [1] ;;

INT N3 = Raw.NUM [2];

Int ORDER = GetYearMonthdayorder (DTFI.ShortdatePattern, DTFI);

IF (ORDER == Order_YMD) {

IF (setDateymd (Result, AdjustYear (Result, N1), N2, N3) // YMD

{

Return;

}

} else if (order == Order_mdy) {

IF (SetDATEMDY (Result, N1, N2, Adjustyear (Result, N3))) // mdy

{

Return;

}

} else if (order == order_dmy) {

IF (SetDatedmy (Result, N1, N2, AdjustYear (Result, N3))) // DMY

{

Return;

}

} else if (Order == Order_YDM) {

IF (setd, Adjustyear (Result, N1), N2, N3) // YDM

{

Return;

}

}

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

Private Static void getDayofmn (DateTimeResult Result, DateTimeFormatinfo DTFI)

{

INT currentyear = result.calendar.getyear (datetime.now);

Result.month = raw.month;

//

// Notenote: in the case of invariant Culture,

// We will have an Ambiguous Situation WHEN We Have A String "June 11".

// it could be 11-06-01 or currentyear-06-11.

// in here, We favor currentyear-06-11 by checking the month.

//

Int monthdayorder = getMonthdayorder (DTFI.MONTHDAYPATTERN, DTFI);

IF (MontHDayOrder == Order_md)

{

IF (setd, currentyear, raw.month, raw.num [0])))

{

Return;

}

} else if (MonthDayOrder == Order_dm) {

IF (setd, currentyear, raw.month, raw.num [0])))

{

Return;

}

}

Int Yearmonthorder = getYearMonthorder (DTFI.YearMonthpattern, DTFI);

IF (YearmonthOrder == Order_my)

{

IF (isvalidmonth (result, raw.num [0], raw.month))

{

Result.Year = Raw.Num [0];

Result.day = 1;

Return;

}

}

IF (isvalidday (result, currentyear, result.month, raw.num [0])))

{

Result.Year = currentyear;

Result.day = raw.num [0];

Return;

}

IF (isvalidday (result, raw.num [0], result.mont, 1)))

{

Result.Year = Raw.Num [0];

Result.day = 1;

}

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

Private Static Void getDayOfnm ​​(DateTimeResult Result, DateTimeFormatinfo DTFI)

{

INT currentyear = result.calendar.getyear (datetime.now);

Result.month = raw.month;

// Check Month / Day First Before Checking Year / Month.

// The logic here is that people often Uses 4 Digit for Years, Which Will Be Captured by getdayofym ().

// therefore, we Assume a Number Followed by a month is generally a month / day.

Int monthdayorder = getMonthdayorder (DTFI.MONTHDAYPATTERN, DTFI);

IF (MontHDayorder == Order_dm)

{

Result.Year = currentyear;

IF (isvalidday (result, result.year, raw.month, raw.num [0]))

{

Result.day = raw.num [0];

Return;

}

}

Int Yearmonthorder = getYearMonthorder (DTFI.YearMonthpattern, DTFI);

IF (YearMonthOrder == Order_YM)

{

IF (isvalidmonth (result, raw.num [0], raw.month))

{

Result.Year = Raw.Num [0];

Result.day = 1;

Return;

}

}

//

// Notenote: in the case of invariant Culture,

// We will have an Ambiguous Situation WHEN WHEN WHEN WHEN WE HAVE A STRING "June 11" .// IT IS Ambiguous Because The Month Day Pattern IS "MMMM DD",

// and year month pattern is "mmmm, yyyy".

// there, it could be 11-06-01 or currentyear-06-11.

// in here, We favor currentyear-06-11 by checking the month.

//

IF (isvalidday (result, currentyear, result.month, raw.num [0])))

{

Result.Year = currentyear;

Result.day = raw.num [0];

Return;

}

IF (isvalidday (result, raw.num [0], result.mont, 1)))

{

Result.Year = Raw.Num [0];

Result.day = 1;

}

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

Private static void getdayofmnn (DateTimeResult Result, DateTimeRawinfo Raw, DateTimeFormatinfo DTFI)

{

INT N1 = Raw.NUM [0];

INT N2 = Raw.NUM [1];

Int ORDER = GetYearMonthdayorder (DTFI.ShortdatePattern, DTFI);

Int year;

IF (Order == Order_MDY)

{

IF (isvalidday (Result, Year = AdjustYear (Result, N2), Raw.Month, N1))

{

Result.Setdate (Year, Raw.month, N1); // MDY

Return;

}

Else if (isvalidday (result, year = adjustyear (result, n1), raw.month, n2)))

{

Result.Setdate (Year, Raw.month, N2); // YMD

Return;

}

}

Else if (ORDER == Order_YMD)

{

IF (isvalidday (result, year = adjustyear (result, n1), raw.month, n2))

{

Result.Setdate (Year, Raw.month, N2); // YMD

Return;

}

Else if (isvalidday (result, year = adjustyear (result, n2), raw.month, n1)))

{

Result.SetDate (Year, Raw.month, N1); // DMY

Return;

}

}

Else if (ORDER == Order_dmy)

{

IF (isvalidday (Result, Year = AdjustYear (Result, N2), Raw.Month, N1))

{

Result.SetDate (Year, Raw.month, N1); // DMY

Return;

}

Else if (isvalidday (result, year = adjustyear (result, n1), raw.month, n2)))

{

Result.Setdate (Year, Raw.month, N2); // YMD

Return;

}

}

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

Private Static Void getDayOfynnn (DateTimeResult Result, DateTimeFormatinfo DTFI) {

INT N1 = Raw.NUM [0];

INT N2 = Raw.NUM [1];

IF (DTFI.CULTUREID == 0x0437) {

// 0x0437 = georgian - georgia (ka-ge)

// Very Special Case for KA-GE:

// ITS short date patten is "dd.mm.yyyy" (ORDER_DMY).

// HOWEVER, ITS Long Date Pattern Is "YYYY '/ X10EC / X10DA / X10D8 / X10E1' DD MM, DDDD" (ORDER_YDM)

Int ORDER = GetYearMonthdayorder (DTFI.longdatePattern, DTFI);

IF (ORDER == Order_ydm) {

IF (SetDATEYMD (Result, Raw.year, N2, N1)) {

Return; // Year DM

}

} else {

IF (SetDATEYMD (Result, Raw.year, N1, N2)) {

Return; // Year MD

}

}

} else {

// OtherWise, Assume IT is Year / Month / Day.

IF (SetDATEYMD (Result, Raw.year, N1, N2)) {

Return; // Year MD

}

}

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

Private static void getdayofnny (DateTimeResult Result, DateTimeRawinfo Raw, DateTimeFormatinfo DTFI) {

INT N1 = Raw.NUM [0];

INT N2 = Raw.NUM [1];

Int ORDER = GetYearMonthdayorder (DTFI.ShortdatePattern, DTFI);

IF (Order == Order_MDY || ORDER == ORDER_YMD) {

IF (SetDATEYMD (Result, Raw.year, N1, N2)) {

Return; // md year

}

} else {

IF (SetDATEYMD (Result, Raw.year, N2, N1)) {

Return; // DM year

}

}

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

Private Static Void, DateTimeResult Result, DateTimeRawinfo Raw, DateTimeformatinfo DTFI {ix (setd, raw.year, raw.month, Raw.Num [0])) {

Return;

}

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

Private Static void getDayofyn (DateTimeResult Result, DateTimeRawinfo Raw, DateTimeFormatinfo DTFI)

{

IF (setd, raw.year, raw.num [0], 1))

{

Return;

}

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

Private Static Void GetdayOfym (DateTimeResult Result, DateTimeRawinfo Raw, DateTimeFormatinfo DTFI)

{

IF (setd, raw.year, raw.month, 1))

{

Return;

}

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

Private Static Void AdjustTimemark (DateTimeformatinfo DTFI, datetimerawinfo RAW) {

// Specail Case for Culture Which Uses AM as Empty String.

// E.g. AF-ZA (0x0436)

// S1159 / X0000

// s2359 nm

// in this case, IF we are Parsing a string Like "2005/09/14 12:23", We Well Assume this is in am.

IF (Raw.Timemark == -1) {

IF (DTFI.AMDesignator! = null& Dtfi.pmdesignator! = null) {

IF (dtfi.amdesignator.length == 0 && Dtfi.pmdesignator.length! = 0) {

Raw.Timemark = TM_AM;

}

IF (dtfi.pmdesignator.length == 0 && dtfi.amdesignator.length! = 0) {

Raw.Timemark = TM_PM;

}

}

}

}

//

// Adjust Hour According to the Time Mark.

//

Private Static Int Adjust Hour (datetimerawinfo raw)

{

INT Hour = Raw.NUM [0];

IF (Hour <0 || HOUR> 12)

{

Throw new formatexception (Environment.GetResourceString ("format_baddatetime");}

IF (Raw.Timemark == TM_AM)

{

Hour = (hour == 12)? 0: hour;

}

Else

{

Hour = (hour == 12)? 12: Hour 12;

}

Return (Hour);

}

Private static void gettimeOfn (DateTimeFormatinfo DTFI, DateTimeResult Result, DateTimeRawinfo Raw)

{

//

// in this case, we need a time mark. Check if SO.

//

IF (raw.timemark == -1)

{

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

AdjustTimemark (DTFI, RAW);

Result.Hour = Adjust Hour (RAW);

}

Private static void gettimeOfnn (DateTimeFormatinfo DTFI, DateTimeResult Result, DateTimeRawinfo Raw)

{

IF (Raw.Numcount <2)

{

Throw new invalidoperationException (environments);

}

AdjustTimemark (DTFI, RAW);

Result.Hour = (Raw.Timemark == - 1)? Raw.Num [0]: AdjustHour (RAW);

Result.minute = Raw.Num [1];

}

Private static void gettimeOfnnn (DateTimeFormatinfo DTFI, DateTimeResult Result, DateTimeRawinfo Raw)

{

IF (Raw.Numcount <3)

{

Throw new invalidoperationException (environments);

}

AdjustTimemark (DTFI, RAW);

Result.Hour = (Raw.Timemark == - 1)? Raw.Num [0]: AdjustHour (RAW);

Result.minute = Raw.Num [1];

Result.second = Raw.Num [2];

}

//

// Processing Terminal State: a date suffix backed by one number.

//

Private static void getdateofdsn (DateTimeResult Result, DateTimeRawinfo RAW)

{

IF (Raw.Numcount! = 1 || Result.day! = -1)

{

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

Result.day = raw.num [0];

}

Private static void getdateofnd (DateTimeResult Result, DateTimeRawnfo Raw)

{

IF (Result.Month == -1)

{

// Should Have a Month Suffix

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

IF (result.year! = -1)

{

// Aleady Has A Year SUFFIX

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

Result.Year = Raw.Num [0];

Result.day = 1;

}

Private static void getDateOfnnds (DatetimeResult Result, DateTimeRawinfo Raw, DateTimeFormatinfo DTFI)

{

Int ORDER = GetYearMonthdayorder (DTFI.ShortdatePattern, DTFI);

Switch (Order)

{

Case Order_YMD:

Break;

Case Order_MDY:

Break;

Case Order_Dmy:

if (Result.day == -1 && Result.Year == -1)

{

IF (isvalidday (result, raw.num [1], result.month, raw.num [0])))

{

Result.Year = Raw.Num [1];

Result.day = raw.num [0];

}

}

Break;

}

}

//

// 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;

}

}

//

// a Terminal State Has Been Reached, Call The Appropriate Function To Fill in The Parsing Result.

// Return True if The State Is a Terminal State.

//

Private Static Void ProcessterMinaltState (int DPS, DateTimeResult Result, DateTimeFormatinfo DTFI) {

Switch (DPS)

{

Case ds_dx_nn:

GetdayOfnn (Result, RAW, DTFI);

Break;

Case ds_dx_nnn:

GetdayOfnnn (Result, RAW, DTFI);

Break;

Case DS_DX_MN:

GetdayOfmn (Result, RAW, DTFI);

Break;

Case ds_dx_nm:

GetdayOfnm ​​(Result, RAW, DTFI);

Break;

Case DS_DX_MNN:

GetdayOfmnn (Result, RAW, DTFI);

Break;

Case DS_DX_DS:

// The result has got the correct value. No need to process.

Break;

Case DS_DX_YNN:

GetdayOfynn (Result, RAW, DTFI);

Break;

Case DS_DX_NNY:

Getdayofnny (Result, RAW, DTFI);

Break;

Case DS_DX_YMN:

GetdayOfyMn (Result, RAW, DTFI);

Break;

Case DS_DX_YN:

GetdayOfyn (Result, RAW, DTFI);

Break;

Case DS_DX_YM:

GetdayOfym (Result, RAW, DTFI);

Break;

Case DS_TX_N:

GetTimeOfn (DTFI, Result, RAW);

Break;

Case DS_TX_NN:

GetTimeOfnn (DTFI, RESULT, RAW);

Break;

Case DS_TX_NNN:

GetTimeOfnn (DTFI, RESULT, RAW);

Break;

Case DS_TX_TS:

// The result has got the correct value. No need to process.

Break;

Case DS_DX_DSN:

GetDateOfDSN (Result, RAW);

Break;

Case DS_DX_NDS:

GetDateOfnds (Result, RAW);

Break;

Case ds_dx_nnds:

GetDateOfnnds (Result, RAW, DTFI);

Break;

}

IF (DPS> DS_ERROR)

{

//

// We since the RECHED A TERMINAL STATE. RESET The RAW NUM Count.

//

Raw.Numcount = 0;

}

Return;

}

//

// this is the real method to do the paingsing.

//

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 paingsing token.

DateTimeRawinfo Raw = new datetimerawinfo (); // The buffer to store temporary paingsing information.

Result.calendar = DTFI.CALENDAR;

//

// the string to be pased. Use a __dtstring wrapper so what we can travel the index which

// indeicates the beginning of next token.

//

__Dtstring str = new __dtstring (s);

Str.getnext ();

//

// The following loop will Break out at the end by the end.

//

Do {

//

// Call the lexer to get the next token.

//

// if we find a era in lex (), The Era Value Will Be in Raw.ea.

Lex (DPS, STR, DTOK, RAW, RESULT, REF DTFI);

//

// if the token is not unknown, Process IT.

// OtherWise, Just Discard IT.

//

IF (dtok.dt! = 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_NUMLOCALTIMARK) {

// consider this as ISO 8601 Format:

// "YYYY-mm-dd't'HH: mm: ss" 1999-10-31t02: 00: 00Return (Parseiso8601 (RAW, STR, STYLES));

}

//

// advance to the next state, and continue

//

DPS = DateParsingStates [DPS] [DTOK.DTT];

IF (DPS == DS_ERROR)

{

Bcldebug.Trace ("NLS", "DateTime (): 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 pased "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.dt! = dtt_end && dtok.dt! = dtt_numend && dtok.dtt! = dtt_monthend);

IF (! REACHTERMINALSTATE) {

Bcldebug.Trace ("NLS", "DateTimeParse.Dopival (): Terminal State Is Not Reached

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

// Check if the pararated String Only Contains Hour / Minute / Second VALUES.

Bool btimeonly = (Result.Year == -1 && results == -1 && result.day == -1);

//

// Check if any year year / month / day is missing in the paarsing 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 the 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);

}

Private Static DateTime AdjustTIMEZONE (DateTime Time) {

IF (Sytles & DateTimeStyles.adjustTouniversal)! = 0) {

Return (AdjustTimezoneTouniversal (Time, TimezoneOffset);

}

Return (AdjustTimezonetolocal (Time, TimezoneOffset, Btimeonly);

}

//

// Adjust The Specified Time To Universal Time Based on The Supplied Timezone.

// E.G. When Parsing "2001/06/08 14: 00-07: 00",

// The Time IS 2001/06/08 14:00, and TimezoneOffset = -07: 00.

// the result will be "2001/06/08 21:00"

//

Private Static DateTime AdjustTimeZonetouniversal (DateTime Time, TimeSpan TimezoneOffset) {

Long Resulttyts = Time.ticks;

Resultticks - = TimezoneOffset.ticks; if (Resulttyicks <0) {

Resultticks = Calendar.ticksperday;

}

IF (Resultticks <0) {

Throw new formatexception ("format_dateoutofrange));

}

Return (New DateTime (Resultticks));

}

//

// adjust the specified time to universal time based on the support timezone,

// and then convert to local time.

// E.G. When Parsing "2001/06/08 14: 00-04: 00", And Local Timezone IS GMT-7.

// The time is 2001/06/08 14:00, and TimezoneOffset = -05: 00.

// the result will be "2001/06/08 11:00"

//

Private Static DateTime AdjustTIMEZONETOLOCAL (DateTime Time, Timespan Timezoneoffset, Bool Btimeonly) {

Long Resulttyts = Time.ticks;

// Convert to Local Ticks

IF (Resultticks

//

// this is time of day.

//

// adjust timezone.

Resultticks - = TimezoneOffset.ticks;

// if The time is time of day, use the current timezone offset.

Resultticks = timezone.currenttimezone.getutcoffset (btimeonly? DateTime.now: Time) .ticks;

IF (Resultticks <0) {

Resultticks = Calendar.ticksperday;

}

} else {

// Adjust Timezone to GMT.

Resultticks - = TimezoneOffset.ticks;

IF (Resultticks> DateTime.maxValue.ticks) {

// if the result ticks is get Than DateTime.maxValue, We can not create a datetime from this ticks.

// in this case, keep using the old code.

// this code path is buy to get around bugs 78411.

Resultticks = Timezone.currentTimezone.getutcoffset (Time) .ticks;

} else {

// Convert The Gmt Time to Local Time.

Return (New DateTime (Resultticks) .tolocalTime ());

}

}

IF (Resultticks <0) {

Throw new formatexception (Environment.getResourceString ("format_dateoutofrange));}

Return (New DateTime (Resultticks));

}

//

// Parse the iso8601 format string found during parse ();

//

//

Private Static DateTime Parseiso8601 (DateTimeRawinfo Raw, __dtstring str, datetimesteles styles) {

IF (Raw.Year <0 | Raw.Num [0] <0 || Raw.Num [1] <0) {

}

Str.index -;

Int Hour, Minute, Second;

Bool Timezoneused = false;

Timespan timezoneoffset = new timeespan ();

DateTime Time = New DateTime (0);

Double partsecond = 0;

Str.skipwhitespaces ();

Parsedigits (STR, 2, True, Out Hour);

Str.skipwhitespaces ();

IF (str.match (':')) {

Str.skipwhitespaces ();

Parsedigits (STR, 2, True, Out Minute);

Str.skipwhitespaces ();

IF (str.match (':')) {

Str.skipwhitespaces ();

Parsedigits (STR, 2, TRUE, OUT Second);

Str.skipwhitespaces ();

IF (str.getnext ()) {

CHAR CH = str.getchar ();

IF (CH == ' ' || CH == '-') {

Timezoneused = true;

TimezoneOffset = Parsetimezone (Str, Str.getChar ());

} else IF (CH == '.') {

Str.Index ; // Parsefraction Requires US to Advance to the next character.

Partsecond = PARSEFRAction (STR);

} else if (ch == 'Z' || CH == 'z') {

Timezoneused = true;

} else {

Throw new formatexception (Environment.GetResourceString ("format_baddatetime")));

}

}

Time = new datetime (Raw.year, Raw.NUM [0], Raw.Num [1], Hour, Minute, Second);

Time = Time.Addticks ((long) Math.Round (Partsecond * Calendar.tickspersecond);

IF (Timezoneused) {

Time = AdjustTimezone (Time, TimezoneOffset, Styles, False);

}

Return Time;

}

}

Throw new formatexception (Environment.GetResourceString ("format_baddatetime");}

/ * ================================= PARSEDIGITS =============== ====================

** Action: Parse the number string in __dtstring That is more formatted using

** The Following Patterns:

** "0", "00", And "000..0"

** RETURns: The Integer Value

** Arguments: str: a __dtstring. The Parsing Will Start from the

** Next Character After Str.Index.

** Exceptions: Formatexception if Error In Parsing Number.

============================================================================================================================================================================================================= ============================= * /

Private Static Bool Parsedigits (__ DTSTRING STR, INT Digitlen, Bool IsthrowExp, Out Int Result) {

Result = 0;

IF (! Str.getNextDigit ()) {

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

Result = str.getdigit ();

IF (Digitlen == 1) {

// when digitlen == 1, Wehibe to Parse Number Like "9" and "19". However,

// We Won't go beyond two digits.

//

// So Let's Look Ahead One Character To See if IT Is A Digit. If Yes, add it to result.

IF (str.getnextdigit ()) {result = result * 10 str.getdigit ();

} else {

// NOT A DIGIT, Let's Roll Back The INDEX.

Str.index -;

}

} else if (Digitlen == 2) {

IF (! Str.getNextDigit ()) {

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

Result = Result * 10 str.getdigit ();

} else {

For (int i = 1; i

IF (! Str.getNextDigit ()) {

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

Result = Result * 10 str.getdigit ();

}

}

Return (TRUE);

}

/ * ================================= PARSEFRActionExact =============== ====================

** Action: Parse the number string in __dtstring That is more formatted using

** The Following Patterns:

** "0", "00", And "000..0"

** Returns: The Fraction Value

** Arguments: str: a __dtstring. The Parsing Will Start from the

** Next Character After Str.Index.

** Exceptions: Formatexception if Error In Parsing Number.

============================================================================================================================================================================================================= ============================= * /

Private Static Bool ParsefractionExact (__ DTString Str, Int Digitlen, Bool IsthrowExp, Ref Double Result) {if (! Str.getNextDigit ()) {

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

Result = str.getdigit ();

For (int i = 1; i

IF (! Str.getNextDigit ()) {

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

Result = Result * 10 str.getdigit ();

}

Result = (Double) Result / Math.Pow (10, Digitlen);

Return (TRUE);

}

/ * ================================= PARSESIGN =============== ====================

** Action: Parse a Positive OR a NEGATIVE SIGN.

** Returns: True if Postive Sign. Flase if Negative Sign.

** Arguments: str: a __dtstring. The Parsing Will Start from the

** Next Character After Str.Index.

** Exceptions: Formatexception if End of string is encountered or a sign

** Symbol is not found.

============================================================================================================================================================================================================= ============================= * /

Private Static Bool Parsesign (__ DTString Str, Bool IsthrowExp, Ref Bool Result) {

IF (! Str.getNext ()) {

// a Sign Symbol (' ' or '-') is expected. Ho'ver, end of string is encountered.return (PartSeFormaterror (isthrowexp, "format_baddatetime));

}

CHAR CH = str.getchar ();

IF (CH == ' ') {

Result = TRUE;

Return (TRUE);

} else if (ch == '-') {

Result = false;

Return (TRUE);

}

// a Sign Symbol (' ' or '-') is expected.

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

/ * ================================= ParsetimezoneOffset ======================================= ====================

** Action: Parse the string formatted using "z", "zz", "zzz" in datetime.format ().

** RETURns: The TimeSpan for the Parsed Timezone Offset.

** Arguments: str: a __dtstring. The Parsing Will Start from the

** Next Character After Str.Index.

** LEN: The Repeated Number of The "Z"

** Exceptions: Formatexception if Errors in paings.

============================================================================================================================================================================================================= ============================= * /

Private Static Bool Parsetimezoneoffset (__ DTSTRING STR, INT LEN, BOOL IsthrowExp, Ref Timespan Result) {

Bool ispositive = true;

INT HOUROFFSET;

INT minuteOffset = 0;

Switch (len) {

Case 1:

Case 2:

IF (! Parsesign (Str, IsthrowExp, Ref Ispositive) {

Return (False);

}

IF (! Parsedigits (Str, Len, IsthrowExp, Out Houroffset) {

Return (False);

}

Break;

DEFAULT:

IF (! Parsesign (Str, IsthrowExp, Ref Ispositive) {

Return (False);

}

IF (! Parsedigits (STR, 2, IsthrowExp, Out Houroffset) {

Return (False);

}

// ':' is Optional.

IF (str.match (":")) {

// Found ':'

IF (! Parsedigits (STR, 2, IsthrowExp, Out minuteOffset) {

Return (False);

}

} else {

// Since We can not match ':', Put the char back.

Str.index -;

IF (! Parsedigits (STR, 2, IsthrowExp, Out minuteOffset) {

Return (False);

}

}

Break;

}

Result = (New Timespan (Houroffset, MinuteOffset, 0);

IF (! ispositive) {

Result = result.negate ();

}

Return (TRUE);

}

/ * ================================= matchabbreviatedMonthname ============== ====================

** Action: Parse The Abbreviated Month Name from string starting at str.index.

** RETURns: a value from 1 to 12 for the first month to the Twelveth Month.

** Arguments: str: a __dtstring. The Parsing Will Start from the

** Next Character After Str.Index.

** Exceptions: Formatexception if an abbreviated month name can not be found.

============================================================================================================================================================================================================= =======================================================================================================

INT maxMatchstrlen = 0;

Result = -1;

IF (str.getnext ()) {

//

// Scan the Month Names (Note That Some Calendars Has 13 Months) and find

// the matching month name Which has the max string length.

// we need to do this Because Some Cultures (E.G. "CS-CZ") Which Have

// Abbreviated Month Names with The Same Prefix.

//

INT MONTHSINYEAR = (DTFI.GETMONTHNAME (13) .length == 0? 12: 13);

For (INT i = 1; i <= monthsinyear; i ) {

String searchstr = DTFI.GetabbreviatedMonthname (i);

IF (STR.MATCHSPECifiedWord (SearchStr)) {

Int matchstrlen = searchstr.length;

IF (matchstrlen> maxmatchstrlen) {

Maxmatchstrlen = matchstrlen;

Result = i;

}

}

}

}

IF (Result> 0) {

Str.Index = (MaxMatchStrlen - 1);

Return (TRUE);

}

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

/ * ================================= MatchMonthname =============== ====================

** Action: Parse The Month Name from string starting at str.index.

** RETURns: a value from 1 to 12 indicating the first month to the twelveth month.

** Arguments: str: a __dtstring. The Parsing Will Start from the

** Next Character After Str.Index.

** Exceptions: Formatexception if a month name can not be found.

============================================================================================================================================================================================================= ============================= * /

Private Static Bool Matchmonthname (__ DTString Str, DateTimeformatinfo DTFI, Bool IsthrowExp, Ref Int Result) {

INT maxMatchstrlen = 0;

Result = -1;

IF (str.getnext ()) {

//

// Scan the Month Names (Note That Some Calendars Has 13 Months) and find

// the matching month name Which has the max string length.

// we need to do this Because Some Cultures (E.G. "VI-VN") Which Have

// Month Names with The Same Prefix.

//

INT MONTHSINYEAR = (DTFI.GETMONTHNAME (13) .length == 0? 12: 13);

For (INT i = 1; i <= monthsinyear; i ) {

String searchstr = DTFI.GETMONTHNAME (i);

IF (STR.MATCHSPECifiedWord (SearchStr)) {

Int matchstrlen = (SearchStr.Length - 1);

IF (matchstrlen> maxmatchstrlen) {

Maxmatchstrlen = matchstrlen;

Result = i;

}

}

}

}

IF (Result> 0) {

Str.Index = maxmatchstrlen;

Return (TRUE);

}

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

/ * ================================= matchabbreviateddayName =============== ==================== ** Action: Parse the Abbreviated Day of Week Name from string starting at str .index.

** Returns: a value from 0 to 6 indicating sunday to saturday.

** Arguments: str: a __dtstring. The Parsing Will Start from the

** Next Character After Str.Index.

** Exceptions: Formatexception if A Abbreviated Day of Week Name Can not be found.

============================================================================================================================================================================================================= ============================= * /

Private Static Bool MatchabbreviatedDayName (__ DTString Str, DateTimeformatinfo DTFI, Bool IsthrowExp, Ref Int Result) {

IF (str.getnext ()) {

For (Dayofweek I = dayofweek.sunday; i <= dayofweek.saturday; i ) {

String searchstr = dtfi.getabbreviateddayName (i);

IF (STR.MATCHSPECifiedWord (SearchStr)) {

Str.Index = (SearchStr.Length - 1);

Result = (int) i;

Return (TRUE);

}

}

}

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

/ * ================================= matchdayname ================ =====================================================================================================================================================================================================00 c

** Returns: a value from 0 to 6 indicating sunday to saturday.

** Arguments: str: a __dtstring. The Parsing Will Start from the

** Next Character After Str.Index.

** Exceptions: Formatexception if a day of week name can not be found.

============================================================================================================================================================================================================= ============================= * /

Private Static Bool MatchDayName (__ DTString Str, DateTimeformatinfo DTFI, Bool IsthrowExp, Ref Int Result) {

// Turkish (TR-TR) Got Day Names with The Same Prefix.

INT maxMatchstrlen = 0;

Result = -1;

IF (str.getnext ()) {

For (Dayofweek I = dayofweek.sunday; i <= dayofweek.saturday; i ) {

String searchstr = dtfi.getdayname (i);

IF (STR.MATCHSPECifiedWord (SearchStr)) {

Int matchstrlen = (SearchStr.Length - 1);

IF (matchstrlen> maxmatchstrlen) {

Maxmatchstrlen = matchstrlen;

Result = (int) i;

}

}

}

}

IF (Result> = 0) {

Str.Index = maxmatchstrlen;

Return (TRUE);

}

Return (ParseFormaterror (isthrowexp, "format_baddatetime");}

/ * ================================= MatCheraname =============== ====================

** Action: Parse Era Name from string starting at str .index.

** RETURns: an Era Value.

** Arguments: str: a __dtstring. The Parsing Will Start from the

** Next Character After Str.Index.

** Exceptions: Formatexception if An Era Name Can not be found.

============================================================================================================================================================================================================= ============================= * /

Private Static Bool Matcheraname (__ DTString Str, DateTimeformatinfo DTFI, Bool IsthrowExp, Ref Int Result) {

IF (str.getnext ()) {

Int [] eras = dtfi.calendar.ras;

IF (ERAS! = null) {

For (int i = 0; i <= Eras.length; i ) {

String searchstr = DTFI.Geteraname (ERAS [I]);

IF (STR.MATCHSPECifiedWord (SearchStr)) {

Str.Index = (SearchStr.Length - 1);

Result = ERAS [I];

Return (TRUE);

}

SearchStr = DTFI.Getabbreviatedraname (ERAS [I]);

IF (STR.MATCHSPECifiedWord (SearchStr)) {

Str.Index = (SearchStr.Length - 1);

Result = ERAS [I];

Return (TRUE);

}

}

}

}

Return (ParseFormaterror (isthrowexp, "format_baddatetime");}

/ * ================================= matchtimemark ============== ====================

** Action: Parse The Time Mark (AM / PM) from string starting at str.index.

** RETURns: TM_AM ORTM_PM.

** Arguments: str: a __dtstring. The Parsing Will Start from the

** Next Character After Str.Index.

** Exceptions: Formatexception if A Time Mark Can NOT BE FOUND.

============================================================================================================================================================================================================= ============================= * /

Private Static Bool Matchtimemark (__ DTString Str, DateTimeformatinfo DTFI, Bool IsthrowExp, Ref Int Result) {

Result = -1;

// in Some Cultures Have Empty strings in AM / PM Mark. E.G. AF-ZA (0x0436), THE AM MARK IS ", And PM Mark IS" NM ".

IF (dtfi.amdesignator.length == 0) {

Result = TM_AM;

}

IF (dtfi.pmdesignator.length == 0) {

Result = TM_PM;

}

IF (str.getnext ()) {

String searchstr = DTFI.AMDesignator;

IF (SearchStr.Length> 0) {

IF (STR.MATCHSPECifiedWord (SearchStr)) {

// Found AN am Timemark with longenet> 0.

Str.Index = (SearchStr.Length - 1);

Result = tm_am; return (true);

}

}

Searchstr = DTFI.PMDesignator;

IF (SearchStr.Length> 0) {

IF (STR.MATCHSPECifiedWord (SearchStr)) {

// Found a PM Timemark with longenet> 0.

Str.Index = (SearchStr.Length - 1);

Result = TM_PM;

Return (TRUE);

}

}

// if we can not match The Time Mark Strings with length> 0,

// Just returnire

Return (TRUE);

}

IF (Result! = -1) {

// if one of the am / pm Marks is Empty String, Return The Result.

Return (TRUE);

}

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

/ * ================================= matchabbreviatedtimemark =============== ====================

** Action: Parse The Abbreviated Time Mark (AM / PM) from string starting at str.index.

** RETURns: TM_AM ORTM_PM.

** Arguments: str: a __dtstring. The Parsing Will Start from the

** Next Character After Str.Index.

** Exceptions: Formatexception if A Abbreviated Time Mark Can NOT BE FOUND.

============================================================================================================================================================================================================= ============================= * /

private static bool MatchAbbreviatedTimeMark (__ DTString str, DateTimeFormatInfo dtfi, bool isThrowExp, ref int result) {// NOTENOTE: the assumption here is that abbreviated time mark is the first

// Character of the AM / PM Designator. if this Invariant Changes, WE Have To

// Change the code below.

IF (str.getnext ())

{

IF (str.getchar () == DTFI.AMDesignator [0]) {

Result = TM_AM;

Return (TRUE);

}

IF (str.getchar () == dtfi.pmdesignator [0]) {

Result = TM_PM;

Return (TRUE);

}

}

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

/ * ================================= ChecknewValue =============== ====================

** Action: Check if CurrentValue is initialized. If not, returnid.

** if Yes, Check if the capital value is equal to newvalue. Throw argumentexception

** if the is used to check the case like "d" and "dd" Are Both

** USED to format a string.

** Returns: The Correct Value for CurrentValue.

** arguments:

** Exceptions:

============================================================================================================================================================================================================= ============================= * /

Private Static Bool ChecknewValue (Ref Int CurrentValue, Int NewValue, CHAR PATTERNCHAR, BOOL Isthrowex) {

IF (currentValue == -1) {

CurrentValue = NewValue;

Return (TRUE);

} else {

IF (NewValue! = CurrentValue) {

BCLDebug.Trace ("NLS", "DateTimeParse.checknewValue ():", Patternchar, "Is Repeated);

IF (isthrowex) {

Throw new argumentexception

String.format (Environment.getResourceString ("format_repeatdatetimepattern"), Patternchar, "Format");

}

Return (False);

}

}

Return (TRUE);

}

Private Static Void CheckdefaultDatetime (DateTimeResult Result, Ref Calendar Cal, DateTimeStyles Styles) {

IF ((Result.Year == -1) || (Result.Mont == -1) || (Result.day == -1)) {

/ *

The Following Table Describes the Behaviors of getting the default value

When a certin year / month / day value..

An "x" Means That the value exissrs. And "-" Means That Value is Missing.

Year Month Day => Resultyear ResultMonth Resultday Note

X x x x, Year Parsed Month PaSed Day

................. ..

X - x pased year first month pased day if The Month Is Mingsing, Assume First Month of That Year.

X - PARSED Year First Month First Day If We Have Only the year, Assume The First Day of That Year.

- x currentyear pased Month Parsed day if the year is missing, assume the current year.

- X - CurrentYear Parsed month First day If we have only a month value, assume the current year and current day .-- - X CurrentYear First month Parsed day If we have only a day value, assume current year and first month .

- - Currentyear Current Month Current Day So this Means That, You Will Get Current Date.

* /

DateTime now = datetime.now;

IF (result.month == -1 && result.day == -1) {

IF (result.year == -1) {

IF (Styles & DateTimeStyles.nocurrentDatedefault)! = 0) {

// if there is no year / month / day value, and no, ocurrentdatedefault flag is buy,

// set the year / month / day value to the beginning beginning year / month / day of datetime ().

// Note We shop be used Gregorian for the year / month / day.

Cal = Gregoriancalendar.getDefaultInstance ();

Result.Year = result.month = result.day = 1;

} else {

// Year / Month / Day Are All Missing.

Result.Year = caver.getyear (now);

Result.month = Cal.getMonth (now);

Result.day = caver.getdayofmonth (now);

}

} else {

// Month / day are Both Missing.

Result.month = 1;

Result.day = 1;

}

} else {

IF (result.year == -1) {

Result.Year = caver.getyear (now);

}

IF (result.month == -1) {

Result.month = 1;

}

IF (result.day == -1) {

Result.day = 1;

}

}

}

// set hour / minute / second to zero if these value is not in str.

IF (result.Hour == -1) Result.Hour = 0;

IF (result.minute == -1) result.minute = 0;

IF (result.second == -1) result.second = 0;

IF (result.era == -1) Result.Ra = Calendar.currentera;

}

// Expand a pre-defined format string (Like "D" for long Date) to the real format That // We are going to use in the date time paarsing.

// this method also set the DTFI According / ParseInfo To Some Special Pre-Defined

// Formats.

//

Private static string expandpredefinedFormat (String Format, Ref DateTimeformatinfo DTFI, ParsingInfo Parseinfo) {

//

// check the format to see reason we need to override the dtfi to be invariantinfo,

// and see if we need to set up the useruniversaltime flag.

//

Switch (Format [0]) {

Case 'R':

Case 'r': // RFC 1123 Standard. (in Universal Time)

ParseInfo.calendar = Gregoriancalendar.getDefaultInstance ();

DTFI = DateTimeFormatinfo.invariantInfo;

Break;

Case 's': // Sortable Format (In Local Time)

DTFI = DateTimeFormatinfo.invariantInfo;

ParseInfo.calendar = Gregoriancalendar.getDefaultInstance ();

Break;

Case 'u': // Universal Time Format in Sortable Format.

ParseInfo.calendar = Gregoriancalendar.getDefaultInstance ();

DTFI = DateTimeFormatinfo.invariantInfo;

Break;

Case 'u': // Universal Time Format with Culture-Dependent Format.

ParseInfo.calendar = Gregoriancalendar.getDefaultInstance ();

ParseInfo.fuseUniversaltime = True;

IF (dtfi.calendar.gettype ()! = TypeOf (Gregoriancalendar) {

DTFI = (datetimeformatinfo) DTFI.Clone ();

DTFI.CALENDAR = Gregoriancalendar.getDefaultInstance ();

}

Break;

}

//

// Expand the pre-defined format character to the real format from datetimeformatinfo.

//

Return (DateTimeFormat.getRealFormat (Format, DTFI));

}

// Given a Specified Format Character, Parse and Update The Parsing Result.

//

Private static bool parsebyformat

__Dtstring STR,

__Dtstring format,

ParsingInfo PaSeinfo,

DateTimeFormatinfo DTFI,

Bool isthrowexp,

DateTimeResult result) {

Int tokenlen = 0;

INT TEMPYEAR = 0, TempMonth = 0, TempDay = 0, Tempdayofweek = 0, Temphour = 0, Tempminute = 0, Tempsecond = 0;

Double TempFraction = 0;

INT TEMPTIMEMARK = 0;

CHAR CH = format.getchar ();

Switch (ch) {

Case 'Y':

Tokenlen = Format.getRepeatcount ();

IF (tokenlen <= 2) {

Parseinfo.fusetwodigityear = true;

}

IF (! Parsedigits (Str, Tokenlen, IsthrowExp, Out Tempyear) {

Return (False);

}

IF (! ChecknewValue (Ref results.year, tempyear, ch, isthrowex) {

Return (False);

}

Break;

Case 'M':

Tokenlen = Format.getRepeatcount ();

IF (tokenlen <= 2) {

IF (! Parsedigits (Str, Tokenlen, IsthrowExp, Out Tempmonth) {

Return (False);

}

} else {

IF (tokenlen == 3) {

IF (! MatchabbreviatedMonthname (Str, DTFI, IsthrowExp, Ref Tempmonth) {

Return (False);

}

} else {

IF (! MatchMonthname (Str, DTFI, IsthrowExp, Ref Tempmonth) {

Return (False);

}

}

}

IF (! ChecknewValue (Ref Resrough.month, Tempmonth, Ch, isthrowex) {

Return (False);

}

Break;

Case 'd':

// day & day of week

Tokenlen = Format.getRepeatcount ();

IF (tokenlen <= 2) {

// "d" & "dd"

IF (! Parsedigits (Str, Tokenlen, IsthrowExp, Out Tempday) {

Return (False);

}

IF (! ChecknewValue (Ref Result.day, TempDay, Ch, isthrowex) {

Return (False);

}

} else {

IF (tokenlen == 3) {

// "DDD"

IF (! MatchabbreviatedDayName (Str, DTFI, IsthrowExp, Ref Tempdayofweek) {

Return (False);

}

} else {

// "DDDD *"

IF (! MatchdayName (Str, DTFI, IsthrowExp, Ref Tempdayofweek) {Return (false);

}

}

IF (! CHECKNEWVALUE (Ref Parseinfo.dayofweek, tempdayofwek, ch, isthrowexp) {

Return (False);

}

}

Break;

Case 'g':

Tokenlen = Format.getRepeatcount ();

// put The Era Value in Result.era.

IF (! Matcheraname (Str, DTFI, isthrowexp, ref results.era) {

Return (False);

}

Break;

Case 'h':

ParseInfo.fuseHOUR12 = true;

Tokenlen = Format.getRepeatcount ();

IF (! Parsedigits (STR, (Tokenlen <2? 1: 2), isthrowExp, Out Temphour) {

Return (False);

}

IF (! ChecknewValue (Ref Result. Hour, Temphour, Ch, isthrowex) {

Return (False);

}

Break;

Case 'h':

Tokenlen = Format.getRepeatcount ();

IF (! Parsedigits (STR, (Tokenlen <2? 1: 2), isthrowExp, Out Temphour) {

Return (False);

}

IF (! ChecknewValue (Ref Result. Hour, Temphour, Ch, isthrowex) {

Return (False);

}

Break;

Case 'M':

Tokenlen = Format.getRepeatcount ();

IF (! parsedigits (STR, (Tokenlen <2? 1: 2), isthrowExp, Out Tempminute)) {

Return (False);

}

IF (! ChecknewValue (Ref Result.minute, Tempminute, Ch, isthrowex) {

Return (False);

}

Break;

Case 's':

Tokenlen = Format.getRepeatcount ();

IF (! parsedigits (STR, (Tokenlen <2? 1: 2), isthrowExp, Out Tempsecond) {

Return (False);

}

IF (! ChecknewValue (ref result.second, tempsecond, ch, isthrowexp) {

Return (False);

}

Break;

Case 'f':

Tokenlen = Format.getRepeatcount ();

IF (tokenlease <= DATETIMEFORMAT.MAXSECONDSFRActionDIGITS) {

IF (! Parsefractionexact (Str, Tokenlen, IsthrowExp, Ref Tempfraction) {

Return (False);

}

IF (Result.fraction <0) {

Result.fraction = tempfraction;

} else {

IF (TempFraction! = Result.fraction) {if (isthrowex) {

Throw new argumentexception

String.Format (Environment.getResourceString ("Format_repeAtDateTimePattern"), CH, "STR");

} else {

Return (False);

}

}

}

} else {

Return PaSeformater (IsthrowExp, "Format_BaddateTime");

}

Break;

Case 'T':

// AM / PM Designator

Tokenlen = Format.getRepeatcount ();

IF (tokenlen == 1) {

IF (! MatchabbreviatedTimemark (Str, DTFI, IsthrowExp, Ref Temptimemark) {

Return (False);

}

} else {

IF (! MatchTimemark (STR, DTFI, IsthrowExp, Ref Temptimemark) {

Return (False);

}

}

IF (! ChecknewValue (ref parseinfo.timemark, temptimemark, ch, isthrowex) {

Return (False);

}

Break;

Case 'Z':

// Timezone Offset

IF (parseinfo.fusetimezone) {

Throw new argumentException (Environment.getResourceString ("argument_twotimezonespecifiers"), "Str");

}

PARSEINFO.FUSETIMEZONE = True;

Tokenlen = Format.getRepeatcount ();

IF (! ParsetimezoneOffset (Str, Tokenlen, Isthrowexp, Ref PaSeinfo.timezoneoffset) {

Return (False);

}

Break;

Case 'Z':

IF (parseinfo.fusetimezone) {

Throw new argumentException (Environment.getResourceString ("argument_twotimezonespecifiers"), "Str");

}

PARSEINFO.FUSETIMEZONE = True;

ParseInfo.timezoneOffset = new timeespan (0);

Str.Index ;

IF (! gettimezonename (str)) {

BCLDebug.Trace ("NLS", "DatetimeParse.DostrictParse (): 'Z' or 'GMT' Are Expected");

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

Break;

Case ':':

IF (! Str.match (DTFI.TimeSeparator) {

// a Time Separetor is expected.

BCLDebug.Trace ("NLS", "DateTimeParse.DostrictParse (): ':' is expected); return (isthrowexp," format_baddatetime));

}

Break;

Case '/':

IF (! str.match (dtfi.dateseparator) {

// a date separator is expected.

BCLDebug.Trace ("NLS", "DateTimeParse.DostrictParse (): Date Separetor is expected;

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

Break;

Case '/ "':

Case '/' ':

Stringbuilder enquotedstring = new stringbuilder ();

Try {

// Use Parsequotestring So That We can Handle Escape Characters within the quoted string.

Tokenlen = DateTimeFormat.Parsequotestring (Format.Value, Format.index, ENQUOTEDSTRING);

} catCH (Exception) {

IF (isthrowex) {

Throw new formatexception (String.Format (Environment.GetResourceString ("Format_Badquote", CH);

} else {

Return (False);

}

}

Format.index = tokenlen - 1;

// Some Cultures Uses Space in The Quote String. E.G. Spanish Has Long Date Format AS:

// "DDDD, DD 'DE' MMMM 'DE' YYYY". WHEN Inner Spaces Flag Is Set, We Should Skip Whitespaces IF The IS Space

// in the quoted string.

String quotedstr = enquotedstring.toString ();

For (int i = 0; i

IF (quotedstr [i] == '' && paseinfo.fallowinnerwhite) {

Str.skipwhitespaces ();

} else if (! Str.match (quotedstr [i])) {

// can not find the matching quoted string.

BCLDebug.Trace ("NLS", "DateTimeParse.DostrictParse (): Quote String Doesn't Match");

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

}

Break;

Case '%':

// Skip this so we can get to the next pattern character.// @ Case Like "% D", "% y"

// make Sure the next character is not a '%' again.

IF (Format.index> = Format.Value.Length - 1 || Format.Value [Format.index 1] == '%') {

BCLDebug.Trace ("NLS", "DateTimeParse.DostrictParse (): %% is not permitted");

Return (Parseformaterror (IsthrowExp, "Format_badFormatSpecifier));

}

Break;

Case '//':

// escape character, "/ d".

// Get the next character in format, and seeiff we can

// Find a match in str.

IF (Format.getNext ()) {

IF (! str.match (format.getchar ())) {

// can not find a match for the escaped character.

BCLDebug.Trace ("NLS", "DateTimeParse.DostrictParse (): can not find a match for the escaped character");

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

} else {

BCLDebug.Trace ("NLS", "DateTimeParse.DostrictParse (): // is at the end of the format string");

Return (Parseformaterror (IsthrowExp, "Format_badFormatSpecifier));

}

Break;

DEFAULT:

IF (CH == ') {

IF (Parseinfo.fallowinnerwhite) {

// Skip Whitespaces IF Allowinnerwhite.

// do nothing here.

} else {

IF (! Str.match (ch)) {

// if the space does not match, and trailing space is allowed, WE DO

// one more step to see reason the next format character can Lead to

// Successful Parsing.

// this is buy to deal with special case this a Empty string can match

// a specific pattern.

// The Example Here IS AF-ZA, WHICH HAS A TIME FORMAT LIKE "HH: MM: SS TT". HOWEVER,

// ITS am Symbol IS "" (EMPTY STRING). If FallowTrailingWhite IS Used, And Time Is in

// The am, we will trim the whitespaces at the end, Which Will Lead to a failure

//when we are trying to match the space "tt".

IF (ParseInfo.fallowTrailingWhite) {

IF (Format.getNext ()) {

IF (Parsebyformat (Str, Format, Parseinfo, DTFI, IsthrowExp, Result) {

Return (TRUE);

}

}

}

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

// Found a MACTH.

}

} else {

IF (Format.MatchSpecifiedword (gmtname) {

Format.index = (gmtname.length - 1);

// Found GMT String in format. This means the datetime string

// is in gmt timezone.

PARSEINFO.FUSETIMEZONE = True;

IF (! Str.match (gmtname)) {

BCLDebug.Trace ("NLS", "DateTimeParse.DostrictParse (): GMT in format, but not in str");

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

} else if (! Str.match (ch)) {

// CH is expected.

Bcldebug.Trace ("NLS", "DateTimeParse.Dostrictpival (): '", ch, "' is expected);

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

}

Break;

} // switch

Return (TRUE);

}

// a Very Small Utility Method to Either Return False Or Throw Format Exception According To The Flag.

Private Static Bool ParseFormater (Bool IsthrowException, String ResourceId)

{

IsthrowException

{

Throw new formatexception (Environment.getResourceString (ResourceId))); "ENVIRONMENT.GETRESOURSTRING (ResourceId);

}

Return (False);

}

/ * ================================= DostrictParse ====================== ==================== ** Action: Do DateTime Parsing Using The Format in formatParam.

** Returns: The PaSed DateTime.

** arguments:

** Exceptions:

**

** Notes:

** WHEN The Following General Formats Are Used, InvariantIntinfo is Used in DTFI:

** 'r', 'r', 's'.

** WHEN The Following General Formats Are Used, The Time Is Assumed to Be in Universal Time.

**

** Limitations:

** ONLY GREGARIANCALENDAR IS Supported for Now.

** Only Support Gmt Timezone.

============================================================================================================================================================================================================= ============================= * /

Private static bool dostrike (

String s,

String FormatParam,

DateTimeStyles Styles,

DateTimeFormatinfo DTFI,

Bool isthrowexp,

Out datetime returnvalue) {

Bool btimeonly = false;

ReturnValue = new datetime ();

ParsingInfo Parseinfo = New ParsingInfo ();

Parseinfo.calendar = DTFI.CALENDAR;

PARSEINFO.FALLOWINNNERWHITE = ((Styles & DateTimeStyles.allowinnerwhite)! = 0);

Parseinfo.fallowTrailingWhite = (Styles & DateTimeStyles.allowTrailingWhite)! = 0);

IF (FormatParam.length == 1) {FormatParam = ExpandPredEfinedFormat (FormatParam, Ref DTFI, PARSEINFO);

}

DatetimeResult results = new datetimereSult ();

// RESET SESE VALUES TO NEGATIVE ONE SO THAT We ​​Could Throw Exception

// if we have pased Every item twice.

Result.Hour = Result.minute = result.second = -1;

__Dtstring format = new __dtstring (formatparam);

__Dtstring str = new __dtstring (s);

IF (ParseInfo.fallowTrailingWhite) {

// Trim Trailing Spaces IF AllowTrailingWhite.

Format.trimtail ();

Format.Removetrailinginquotespaces ();

Str.trimtail ();

}

IF (Styles & DateTimeStyles.allowleadingWhite)! = 0) {

Format.skipwhitespaces ();

Format.RemoveLeadingInquotespaces ();

Str.skipwhitespaces ();

}

//

// Scan Every Character in format and match the pattern in str.

//

While (Format.getNext ()) {

// We Trim Inner Spaces Here, SO That We will not eat trailing space

// allowtrailingwhite is not used.

IF (Parseinfo.fallowinnerwhite) {

Str.skipwhitespaces ();

}

IF (! Parsebyformat (Str, Format, ParseInfo, DTFI, IsthrowEx, Result) &&

! isthroWexp) {

Return (False);

}

}

IF (str.index

// There is the remaining character in str.

BCLDebug.Trace ("NLS", "DateTimeParse.DostrictParse (): Still Characters in Str, Str.Index =", Str.Index);

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

IF (Parseinfo.fuseTwodigityear) {

// a Two Digit Year Value IS Expected. Check if the pased year value is valid.

IF (result.year> = 100) {

BCLDebug.Trace ("NLS", "DateTimeParse.DostrictParse (): Invalid Value for Two-Digit Year");

Return (ParseFormaterror (isthrowexp, "format_baddatetime");}

Result.year = parseinfo.calendar.tofourdigityear (Result.Year);

}

IF (ParseInfo.fuseHOUR12) {

IF (ParseInfo.timemark == -1) {

//HH is buy, but no am / pm designator isot specified.

// Assume The Time IS AM.

// Don n't throw exceptions in here becasue it is very confusing for mind.

// i Always Got Confused Myself When I Use "HH: mm: SS" to Parse a Time String,

// and parseexact () THROWS ON ME (Because I Didn't Use the 24-Hour Clock 'HH').

PARSEINFO.TIMEMARK = TM_AM;

Bcldebug.Trace ("NLS", "DateTimeParse.DostrictPars (): HH IS Used, But no AM / PM Designator is Specified.")

}

IF (Result.Hour> 12) {

// AM / PM IS Used, But The Value for HH IS TOO BIG.

Bcldebug.Trace ("NLS", "DateTimeParse.DostrictParse (): AM / PM IS Used, But The Value for HH is Too Big.")

Return (ParseFormaterror (isthrowexp, "format_baddatetime));

}

IF (ParseInfo.timemark == TM_AM) {

IF (result.hour == 12) {

Result.Hour = 0;

}

} else {

Result.Hour = (Result.Hour == 12)? 12: Result.Hour 12;

}

}

// Check if the pararated String Only Contains Hour / Minute / Second VALUES.

Btimeonly = (Result.Year == -1 && Result.mont == -1 && results == -1);

CheckdefaultDatetime (Result, Ref PaSeinfo.calendar, Styles);

Try {

ReturnValue = parseInfo.calendar.todatetime (result.year, result.month, result.day,

Result.Hour, Result.minute, Result.second, 0, Result.era);

IF (Result.fraction> 0) {

ReturnValue = RETURNVALUE.Addticks ((long) Math.Round (Result.fraction * Calendar.tickspersecond);

}

} catch (argumentoutofrangeexception) {return (partformaterror (isthrowexp, "format_dateoutofrange));

} catch (exception exp) {

IF (isthrowex) {

Throw Exp;

} else {

Return (False);

}

}

//

// Notenote:

// We Have to Check Day of Week Before We Adjust to The Time Zone.

// it is because the value of day of week may change after adjusting

// To the time zone.

//

IF (ParseInfo.dayofweek! = -1) {

//

// Check if day of week is the correct.

//

IF (Parseinfo.dayofweek! = (int) parseinfo.calendar.getdayofweek (returnvalue)) {

BCLDebug.Trace ("NLS", "DateTimeParse.DostrictParse (): DAY OF Week Is Not Correct");

Return (Parseformaterror (IsthrowExp, "Format_Baddayofweek);

}

}

IF (parseinfo.fusetimezone) {

IF (Styles & DateTimeStyles.adjustTouniversal)! = 0) {

ReturnValue = AdjustTimezonetouniversal (ReturnValue, ParseInfo.timezoneoffset);

} else {

ReturnValue = AdjustTimezonetolocal (ReturnValue, ParseInfo.timezoneoffset, btimeonly);

}

} else if (parseinfo.fuseUniversaltime) {

Try {

ReturnValue = returnvalue.tolocaltime ();

} catch (argumentoutofrangeexception) {

Return (Parseformaterror (IsthrowExp, "Format_DateOutOfRange);

}

}

Return (TRUE);

}

// this Method Should Never Be Called. ITS Sole Purpose Is To Shut Up The Compiler

// Because It Warns About Private Fields That Are Never Used. Most of these Fields

// is used in unmanaged code.

#if _debug

INTERNAL STRING [] nevercallthis ()

{

BCLDebug.Assert (false, "nevercallthis");

String [] i = invariantMonthnames;

I = INVARIANTABBREVMONTHNAMES;

I = INVARIANTDAYNAMES;

Return INVARIANTABBREVDAYNAMES;

}

#ENDIF

}

//

// this is a string Parsing Helper Which Wraps a string Object.// IT Has A Index Property Which TRACKS

// The current Parsing Pointer of The String.

//

[Serializable ()]

Internal

Class __dtstring

{

//

// Value ProPERY: Stores the real string to be pased.

//

INTERNAL STRING VALUE;

//

// Index Property: Points to the Character That We Are Currently Parsing.

//

INTERNAL INDEX = -1;

// the length of value string.

INTERNAL INT LEN = 0;

Private compareinfo m_info;

INTERNAL __DTSTSTRING ()

{

Value = "";

}

INTERNAL __DTSTRING (String STR)

{

Value = STR;

Len = Value.LENGTH;

M_INFO = thread.currentthread.currentculture.compareinfo;

}

INTERNAL COMPAREINFO COMPAREINFO {

Get {

Return M_INFO;

}

}

//

// Advance the index.

// Return True if index is not at the end of the string.

//

// Typical Usage:

// while (Str.getNext ())

// {

// char ch = str.getchar ()

//}

INTERNAL BOOL getNext () {

INDEX ;

Return (INDEX

}

//

// Return the Word Starting from the current index.

// Index Will NOT BE Updated.

//

INTERNAL INT FINDENDOFCURRENTWORD () {

INT i = index;

While (i

IF (value [i] == '|| value [i] ==', '|| value [i] ==' / '' || char.isdigit (value [i])) {

Break;

}

i ;

}

Return I;

}

INTERNAL STRING peekcurrentword () {

Int endindex = findendofcurrentword ();

Return Value.substring (INDEX, (EndIndex - Index));

}

INTERNAL BOOL MATCHSPECifiedWord (String Target) {

Return MatchSpecifiedWord (Target, Target.Length Index);

}

INTERNAL BOOL MATCHSPECifiedWord (String Target, int endindex) {

INT count = endindex - index;

IF (count! = target.length) {Return False;

}

IF (INDEX Count> Len) {

Return False;

}

Return (M_Info.compare (Value, Index, Count, Target, 0, Count, CompareOptions.ignorecase) == 0);

}

Internal Bool Startswith (String Target, Bool CHECKWORDBOUNDARY) {

IF (value.length - index) {

Return False;

}

IF (M_Info.compare (Value, Index, Target.length, Target, 0, Target.length)! = 0) {

Return (False);

}

Checkwordboundary {

INT nextcharindex = index target.length;

NextCharindex

IF (Char.isletter (Value [nextcharindex])) {

Return (False);

}

}

}

Return (TRUE);

}

//

// check to see if the string starting from index is a prefix of

// Str.

// if a match is found, true value is returned and index is updated to the next character to be pased.

// OtherWise, INDEX IS Unchanged.

//

INTERNAL BOOL MATCH (String Str) {

IF ( index> = len) {

Return (False);

}

IF (str.length> (value.length - index)) {

Return False;

}

IF (M_Info.compare (Value, Index, Str.length, Str, 0, Str.length, CompareOptions.ordinal) == 0) {

// Update the index to the end of the matching string.

// so the folcoming getnext () / match () Opertion Will Get

// The next character to be parse.

INDEX = (str.length - 1);

Return (TRUE);

}

Return (False);

}

INTERNAL BOOL MATCH (CHAR CH) {

IF ( index> = len) {

Return (False);

}

IF (value [index] == CH) {

Return (TRUE);

}

Return (False);

}

//

// Trying to match an array of words.

// Return Truehen One of the Word in the array matching with substring

// Starting from the current index.

// if the words array is null, also return true, assuming what there is a match.//

INTERNAL BOOL MATCHWORDS (String [] Words) {

IF (words == null) {

Return (TRUE);

}

IF (index> = len) {

Return (False);

}

For (INT i = 0; i

IF (Words [i] .length <= (value.length - index) {

IF (m_info.compare)

Value, Index, Words [I] .length, Words [i], 0, Words [i] .length, compareOptions.ignorecase) == 0) {

INDEX = Words [i] .length;

Return (TRUE);

}

}

}

Return (False);

}

//

// Get The Number of Repeat Character After The Current Character.

// for a string "hh: mm: s" at index of 3. getrepeatcount () = 2, and index

// Will Point to the second ':'.

//

INTERNAL INT GETREPEATCOUNT () {

CHAR REPEATCHAR = VALUE [INDEX];

INT POS = INDEX 1;

While ((POS

POS ;

}

INT repeatCount = (POS - INDEX);

// Update the index to the end of the repeated character.

// so the folload getnext () OPEATION Will Get

// The next character to be parse.

INDEX = POS - 1;

Return (repeatcount);

}

// RETURN FALSE WHEN End of string is encountered or a non-Digit Character is found.

INTERNAL BOOL getNextdigit () {

IF ( index> = len) {

Return (False);

}

Return (DateTimeParse.IsDigit (Value [Index]));

}

// Return Null when end of string is encountered or a matching quote character is not found.

// throws formatexception if the match quote Character Can NOT BE FOUND.

INTERNAL STRING GETQUOTEDSTRING (Char quotecha) {

// WHEN We Enter this Method, Index Points to The First Quote Character.

INT OLDPOS = Index;

While (Index

}

IF (index == len) {

// if We Move Past Len, IT Means A Matching Quote Character Is Not Found.

// 'ABC' 'ABC

// 01234 0123

Return (NULL);

}

// WHEN We Leave this Method, Index Points to the matching quote character.

Return (Value.Substring (Oldpos, INDEX - OLDPOS);

}

//

// Get The Current Character.

//

INTERNAL CHAR getchar () {

BCLDebug.Assert (INDEX> = 0 && Index = 0 && Index

Return (Value [index]);

}

//

// Convert The Current Character to a Digit, And Return IT.

//

INTERNAL INT getDigit () {

BCLDebug.Assert (INDEX> = 0 && Index = 0 && Index

Bcldebug.Assert (DateTimeParse.IsDigit (Value [Index]), "Isdigit (Value [Index])")

Return (Value [index] - '0');

}

//

// Enjoy Eating White Spaces.

//

// Return False if End of string is encountered.

//

Internal void Skipwhitespaces ()

{

// Look Ahead to See eti the next character

// is a whitespace.

While (INDEX 1

{

CHAR CH = Value [Index 1];

IF (! char.swhitespace (ch)) {

Return;

}

INDEX ;

}

Return;

}

//

// Enjoy Eating White Spaces and Commas.

//

// Return False if End of string is encountered.

//

Internal Bool SkipwhitespaceComma ()

{

CHAR CH;

IF (index> = len) {

Return (False);

}

IF (! char.iswhitespace (ch = value [index]) && ch! = ',')

{

Return (TRUE);

}

While ( Index

{

CH = value [index];

IF (! char.iswhitespace (ch) && ch! = ',')

{

Return (TRUE);

}

// Nothing here.

}

Return (False);

}

INTERNAL VOID TRIMTAIL () {

INT i = LEN - 1;

While (i> = 0 && char.iswhitespace (value [i])) {

I-;

}

Value = value.substring (0, i 1);

Len = Value.LENGTH;

}

// Trim The Trailing Spaces within a quoted string.

// Call this after trimtail () is done.

INTERNAL VOID REMOVETRAILINGINGINGINGINGINGINGINGINGINGINGINGINGINGINGINQUOTESPACES () {

INT i = LEN - 1;

IF (i <= 1) {

Return;

}

CHAR CH = Value [i];

// Check if The last character is a quote.

IF (CH == '/' '|| CH ==' / ") {

IF (Char.IsWhitespace (Value [i-1])) {

I-;

While (i> = 1 && char.iswhitespace (value [i-1])) {

I-;

}

Value = Value.Remove (I, Value.length - 1 - i);

Len = Value.LENGTH;

}

}

}

// Trim The Leading Spaces within a quoted string.

// Call this After the Leading Spaces Before Quoted String Are Trimmed.

INTERNAL VOID RemoveLeadingInquotespaces () {

IF (len <= 2) {

Return;

}

INT i = 0;

CHAR CH = Value [I];

// Check if The last character is a quote.

IF (CH == '/' '|| CH ==' / ") {

While ((i 1)

i ;

}

IF (i! = 0) {

Value = value.Remove (1, i);

Len = Value.LENGTH;

}

}

}

}

//

// The buffer to store the paingsing token.

//

[Serializable ()]

Internal

Class datetimetoken {

INTERNAL INT DTT; // Store the Token

INTERNAL INT SuFFIX; // Store the cjk year / month / day suffix (if any)

INTERNAL INT NUM; // Store The Number That We Are Parsing (if any)

}

//

// The buffer to store temporary paarsing information.

//

[Serializable ()]

Internal

Class datetimerawinfo {

INTERNAL INT [] NUM

INTERNAL INT NUMCOUNT = 0; Internal Int Month = -1;

INTERNAL INT YEAR = -1;

INTERNAL INT dayofweek = -1;

INTERNAL INT ERA = -1;

INTERNAL INT TIMEMARK = -1; // Value Could BE -1, TM_AM ORTM_PM.

INTERNAL DOUBLE FRACTION = -1;

//

//

INTERNAL BOOL TIMEZONE = FALSE

INTERNAL dateTimerawinfo ()

{

Num = new int = {-1, -1, -1};

}

}

//

// this Will Store The Result of The Parsing. And It Will Be Eventually

// use to construct a datetime instance.

//

[Serializable ()]

Internal

Class DateTimeResult

{

INTERNAL INT YEAR = -1;

INTERNAL INT MONTH = -1;

INTERNAL INT DAY = -1;

//

// set time defualt to 00:00:00.

//

INTERNAL INT Hour = 0;

INTERNAL INT minute = 0;

INTERNAL INT SECOND = 0;

INTERNAL DOUBLE FRACTION = -1;

INTERNAL INT ERA = -1;

INTERNAL BOOL TIMEZONEUSED = FALSE;

INTERNAL TIMESPAN TIMEZONEOFFSET;

INTERNAL CALENDAR CALENDAR;

INTERNAL dateTimeResult ()

{

}

INTERNAL Virtual Void SetDate (int year, int month, int day)

{

Year = year;

Month = month;

Day = day;

}

}

[Serializable]

INTERNAL CLASS PARSINGINFO {

INTERNAL CALENDAR CALENDAR;

INTERNAL INT dayofweek = -1;

INTERNAL INT TIMEMARK = -1;

INTERNAL TIMESPAN TIMEZONEOFFSET = New Timespan ();

INTERNAL BOOL FUSEUNIVERTIME = FALSE;

INTERNAL BOOL FUSEHOUR12 = false;

INTERNAL BOOL FUSETWodigityear = false

INTERNAL BOOL FUSETIMEZONE = FALSE;

INTERNAL BOOL FALLLOWINNNERWHITE = FALSE;

INTERNAL BOOL FALLLOWTRAILINGWHITE = FALSE;

INTERNAL PARSINFO () {

}

}

}

转载请注明原文地址:https://www.9cbs.com/read-128633.html

New Post(0)