"H:m",
"H tt", // Specifies AM to disallow '8'.
"H'\u6642'm'\u5206's'\u79D2'",
+ "zzz"
};
// DateTime.Parse date patterns extend ParseExact patterns as follows:
"yyyy/MMMM",
};
+ private static readonly string[] ExoticAndNonStandardFormats = new string[] {
+ "ddMMMyyyy"
+ };
+
private enum Which
{
Day,
}
// Try as a last resort all the patterns
- if (ParseExact (s, dfi.GetAllDateTimePatternsInternal (), dfi, styles, out result, false, ref longYear, setExceptionOnError, ref exception))
+ if (CoreParseExact (s, dfi.GetAllDateTimePatternsInternal (), dfi, styles, out result, out dto, false, ref longYear, setExceptionOnError, ref exception))
+ return true;
+
+ if (CoreParseExact (s, ExoticAndNonStandardFormats, dfi, styles, out result, out dto, false, ref longYear, setExceptionOnError, ref exception))
return true;
if (!setExceptionOnError)
DateTimeStyles style,
bool firstPartIsDate,
ref bool incompleteFormat,
- ref bool longYear)
+ ref bool longYear,
+ bool dateTimeOffset = false)
{
bool useutc = false;
bool use_invariant = false;
bool afterTFormat = false;
DateTimeFormatInfo invInfo = DateTimeFormatInfo.InvariantInfo;
if (format.Length == 1)
- format = DateTimeUtils.GetStandardPattern (format [0], dfi, out useutc, out use_invariant);
+ format = DateTimeUtils.GetStandardPattern (format [0], dfi, out useutc, out use_invariant, dateTimeOffset);
result = new DateTime (0);
if (format == null)
} else if (num < 3) {
year = _ParseNumber (s, valuePos, 1, 2, true, sloppy_parsing, out num_parsed);
} else {
- year = _ParseNumber (s, valuePos, exact ? 4 : 3, 4, false, sloppy_parsing, out num_parsed);
- if ((year >= 1000) && (num_parsed == 4) && (!longYear) && (s.Length > 4 + valuePos)) {
- int np = 0;
- int ly = _ParseNumber (s, valuePos, 5, 5, false, sloppy_parsing, out np);
- longYear = (ly > 9999);
- }
- num = 3;
+ year = _ParseNumber (s, valuePos, exact ? num + 1 : 3, num + 1, false, sloppy_parsing, out num_parsed);
+ longYear = (year > 9999);
}
//FIXME: We should do use dfi.Calendat.TwoDigitYearMax
if (num_parsed == -1)
return false;
fractionalSeconds = decimalNumber / Math.Pow(10.0, num_parsed);
+
+ //Parse ISO8601 with an unlimited number of fractional digits.
+ if (!exact && num == 6 && hour != -1 && minute != -1 && second != -1) {
+ var total_num_parsed = num_parsed;
+ while (true) {
+ valuePos += num_parsed;
+ decimalNumber = (double) _ParseNumber (s, valuePos, 0, 1, leading_zeros, sloppy_parsing, out num_parsed);
+ if (num_parsed < 1) {
+ num_parsed = 0;
+ break;
+ }
+
+ total_num_parsed += num_parsed;
+ if (total_num_parsed > 15)
+ continue; //not enough precision, ignore additional digits.
+
+ fractionalSeconds += decimalNumber / Math.Pow (10.0, total_num_parsed);
+ }
+ }
break;
case 't':
if (!_ParseAmPm (s, valuePos, num > 0 ? 0 : 1, dfi, exact, out num_parsed, ref ampm))
valuePos += num_parsed;
tzoffmin = _ParseNumber (s, valuePos, 0, 2, true, sloppy_parsing, out num_parsed);
- num = 2;
if (num_parsed < 0)
return false;
}
// '.FFF....' can be mapped to nothing
if (pos + 1 < len && chars[pos + 1] == 'F') {
++pos;
- while (pos < len && chars[pos + 1] == 'F') {
+ while (pos + 1 < len && chars[pos + 1] == 'F') {
++pos;
}
}
}
- // For anything out of range
- // return false
- if (year < 1 || year > 9999 ||
- month < 1 || month >12 ||
- day < 1 || day > DateTime.DaysInMonth(year, month) ||
- hour < 0 || hour > 23 ||
- minute < 0 || minute > 59 ||
- second < 0 || second > 59)
+ try {
+ result = dfi.Calendar.ToDateTime (year, month, day, hour, minute, second, 0);
+ } catch {
return false;
+ }
- result = new DateTime (year, month, day, hour, minute, second, 0);
result = result.AddSeconds(fractionalSeconds);
if (dayofweek != -1 && dayofweek != (int) result.DayOfWeek)
if (tzsign == -1) {
if (result != DateTime.MinValue) {
try {
- dto = new DateTimeOffset (result);
+ if ((style & DateTimeStyles.AssumeUniversal) != 0) {
+ dto = new DateTimeOffset (result, TimeSpan.Zero);
+ } else if ((style & DateTimeStyles.AssumeLocal) != 0) {
+ var offset = use_invariant ?
+ TimeSpan.Zero :
+ TimeZone.CurrentTimeZone.GetUtcOffset (DateTime.Now);
+ dto = new DateTimeOffset (result, offset);
+ } else {
+ dto = new DateTimeOffset (result);
+ }
} catch { } // We handle this error in DateTimeOffset.Parse
}
} else {
throw new FormatException ("Format specifier was invalid.");
DateTime result;
+ DateTimeOffset dto;
bool longYear = false;
Exception e = null;
- if (!ParseExact (s, formats, dfi, style, out result, true, ref longYear, true, ref e))
+ if (!CoreParseExact (s, formats, dfi, style, out result, out dto, true, ref longYear, true, ref e))
throw e;
return result;
}
{
if ((style & DateTimeStyles.AdjustToUniversal) != 0 || (style & DateTimeStyles.AssumeLocal) != 0 ||
(style & DateTimeStyles.AssumeUniversal) != 0)
- throw new ArgumentException ("The DateTimeStyles value RoundtripKind cannot be used with the values AssumeLocal, Asersal or AdjustToUniversal.", "style");
+ throw new ArgumentException ("The DateTimeStyles value RoundtripKind cannot be used with the values AssumeLocal, AssumeUniversal or AdjustToUniversal.", "style");
}
if ((style & DateTimeStyles.AssumeUniversal) != 0 && (style & DateTimeStyles.AssumeLocal) != 0)
throw new ArgumentException ("The DateTimeStyles values AssumeLocal and AssumeUniversal cannot be used together.", "style");
{
try {
DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (provider);
+ DateTimeOffset dto;
bool longYear = false;
Exception e = null;
- return ParseExact (s, formats, dfi, style, out result, true, ref longYear, false, ref e);
+ return CoreParseExact (s, formats, dfi, style, out result, out dto, true, ref longYear, false, ref e);
} catch {
result = MinValue;
return false;
}
}
- private static bool ParseExact (string s, string [] formats,
- DateTimeFormatInfo dfi, DateTimeStyles style, out DateTime ret,
+ internal static bool CoreParseExact (string s, string [] formats,
+ DateTimeFormatInfo dfi, DateTimeStyles style,
+ out DateTime ret, out DateTimeOffset dto,
bool exact, ref bool longYear,
- bool setExceptionOnError, ref Exception exception)
+ bool setExceptionOnError, ref Exception exception,
+ bool dateTimeOffset = false)
{
+ dto = new DateTimeOffset (0, TimeSpan.Zero);
int i;
bool incompleteFormat = false;
for (i = 0; i < formats.Length; i++)
if (format == null || format == String.Empty)
break;
- DateTimeOffset dto;
- if (_DoParse (s, formats[i], null, exact, out result, out dto, dfi, style, false, ref incompleteFormat, ref longYear)) {
+ if (_DoParse (s, formats[i], null, exact, out result, out dto, dfi, style, false, ref incompleteFormat, ref longYear, dateTimeOffset)) {
ret = result;
return true;
}