public bool Parse(string text, XsdDateTimeFlags kinds) {
this.text = text;
this.length = text.Length;
// Skip leading withitespace
int start = 0;
while(start < length && char.IsWhiteSpace(text[start])) {
start ++;
}
// Choose format starting from the most common and trying not to reparse the same thing too many times
if (Test(kinds, XsdDateTimeFlags.DateTime | XsdDateTimeFlags.Date | XsdDateTimeFlags.XdrDateTime | XsdDateTimeFlags.XdrDateTimeNoTz)) {
if (ParseDate(start)) {
if (Test(kinds, XsdDateTimeFlags.DateTime)) {
if (ParseChar(start + Lzyyyy_MM_dd, 'T') && ParseTimeAndZoneAndWhitespace(start + Lzyyyy_MM_ddT)) {
typeCode = DateTimeTypeCode.DateTime;
return true;
}
}
if (Test(kinds, XsdDateTimeFlags.Date)) {
if (ParseZoneAndWhitespace(start + Lzyyyy_MM_dd)) {
typeCode = DateTimeTypeCode.Date;
return true;
}
}
if (Test(kinds, XsdDateTimeFlags.XdrDateTime)) {
if (ParseZoneAndWhitespace(start + Lzyyyy_MM_dd) || (ParseChar(start + Lzyyyy_MM_dd, 'T') && ParseTimeAndZoneAndWhitespace(start + Lzyyyy_MM_ddT)) ) {
typeCode = DateTimeTypeCode.XdrDateTime;
return true;
}
}
if (Test(kinds, XsdDateTimeFlags.XdrDateTimeNoTz)) {
if (ParseChar(start + Lzyyyy_MM_dd, 'T')) {
if (ParseTimeAndWhitespace(start + Lzyyyy_MM_ddT)) {
typeCode = DateTimeTypeCode.XdrDateTime;
return true;
}
}
else {
typeCode = DateTimeTypeCode.XdrDateTime;
return true;
}
}
}
}
if (Test(kinds, XsdDateTimeFlags.Time)) {
if (ParseTimeAndZoneAndWhitespace(start)) { //Equivalent to NoCurrentDateDefault on DateTimeStyles while parsing xs:time
year = leapYear;
month = firstMonth;
day = firstDay;
typeCode = DateTimeTypeCode.Time;
return true;
}
}
if (Test(kinds, XsdDateTimeFlags.XdrTimeNoTz)) {
if (ParseTimeAndWhitespace(start)) { //Equivalent to NoCurrentDateDefault on DateTimeStyles while parsing xs:time
year = leapYear;
month = firstMonth;
day = firstDay;
typeCode = DateTimeTypeCode.Time;
return true;
}
}
if (Test(kinds, XsdDateTimeFlags.GYearMonth | XsdDateTimeFlags.GYear)) {
if (Parse4Dig(start , ref year) && 1 <= year) {
if (Test(kinds, XsdDateTimeFlags.GYearMonth)) {
if (
ParseChar(start + Lzyyyy, '-') &&
Parse2Dig(start + Lzyyyy_, ref month) && 1 <= month && month <= 12 &&
ParseZoneAndWhitespace(start + Lzyyyy_MM)
) {
day = firstDay;
typeCode = DateTimeTypeCode.GYearMonth;
return true;
}
}
if (Test(kinds, XsdDateTimeFlags.GYear)) {
if (ParseZoneAndWhitespace(start + Lzyyyy)) {
month = firstMonth;
day = firstDay;
typeCode = DateTimeTypeCode.GYear;
return true;
}
}
}
}
if (Test(kinds, XsdDateTimeFlags.GMonthDay | XsdDateTimeFlags.GMonth)) {
if (
ParseChar(start , '-') &&
ParseChar(start + Lz_, '-') &&
Parse2Dig(start + Lz__, ref month) && 1 <= month && month <= 12
) {
if (Test(kinds, XsdDateTimeFlags.GMonthDay) && ParseChar(start + Lz__mm, '-')) {
if (
Parse2Dig(start + Lz__mm_, ref day) && 1 <= day && day <= DateTime.DaysInMonth(leapYear, month) &&
ParseZoneAndWhitespace(start + Lz__mm_dd)
) {
year = leapYear;
typeCode = DateTimeTypeCode.GMonthDay;
return true;
}
}
if (Test(kinds, XsdDateTimeFlags.GMonth)) {
if (ParseZoneAndWhitespace(start + Lz__mm) || (ParseChar(start + Lz__mm, '-') && ParseChar(start + Lz__mm_, '-') && ParseZoneAndWhitespace(start + Lz__mm__)) ) {
year = leapYear;
day = firstDay;
typeCode = DateTimeTypeCode.GMonth;
return true;
}
}
}
}
if (Test(kinds, XsdDateTimeFlags.GDay)) {
if (
ParseChar(start , '-') &&
ParseChar(start + Lz_, '-') &&
ParseChar(start + Lz__, '-') &&
Parse2Dig(start + Lz___, ref day) && 1 <= day && day <= DateTime.DaysInMonth(leapYear, firstMonth) &&
ParseZoneAndWhitespace(start + Lz___dd)
) {
year = leapYear;
month = firstMonth;
typeCode = DateTimeTypeCode.GDay;
return true;
}
}
return false;
}