Merge pull request #1304 from slluis/mac-proxy-autoconfig
[mono.git] / mcs / class / corlib / System / DateTimeOffset.cs
index 8c6b03596b6bd45bb802aec8f7dcc3c5593629b6..1267f9270decadd2c3d02078de4a3f94cf9feb87 100644 (file)
@@ -6,6 +6,7 @@
  *     Marek Safar (marek.safar@gmail.com)
  *
  *  Copyright (C) 2007 Novell, Inc (http://www.novell.com) 
+ *  Copyright 2012 Xamarin, Inc (http://www.xamarin.com) 
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -122,9 +123,9 @@ namespace System
                        return new DateTimeOffset (dt.AddHours (hours).Ticks, utc_offset);
                }
 
-               public static DateTimeOffset operator + (DateTimeOffset dateTimeTz, TimeSpan timeSpan)
+               public static DateTimeOffset operator + (DateTimeOffset dateTimeOffset, TimeSpan timeSpan)
                {
-                       return dateTimeTz.Add (timeSpan);
+                       return dateTimeOffset.Add (timeSpan);
                }
 
                public DateTimeOffset AddMilliseconds (double milliseconds)
@@ -296,11 +297,15 @@ namespace System
                        DateTime d;
                        DateTimeOffset dto;
                        Exception exception = null;
-                       if (!DateTime.CoreParse (input, formatProvider, styles, out d, out dto, true, ref exception))
-                               throw exception;
+                       try {
+                               if (!DateTime.CoreParse (input, formatProvider, styles, out d, out dto, true, ref exception))
+                                       throw exception;
+                       } catch (ArgumentOutOfRangeException ex) {
+                               throw new FormatException ("The UTC representation falls outside the 1-9999 year range", ex);
+                       }
 
                        if (d.Ticks != 0 && dto.Ticks == 0)
-                               throw new ArgumentOutOfRangeException ("The UTC representation falls outside the 1-9999 year range");
+                               throw new FormatException ("The UTC representation falls outside the 1-9999 year range");
 
                        return dto;
                }
@@ -338,326 +343,19 @@ namespace System
                        if ((styles & DateTimeStyles.AssumeLocal) != 0 && (styles & DateTimeStyles.AssumeUniversal) != 0)
                                throw new ArgumentException ("styles parameter contains incompatible flags");
 
+                       DateTimeFormatInfo dfi = DateTimeFormatInfo.GetInstance (formatProvider);
+                       DateTime d;
                        DateTimeOffset result;
-                       if (!ParseExact (input, formats, DateTimeFormatInfo.GetInstance (formatProvider), styles, out result))
-                               throw new FormatException ("Invalid format string");
-
-                       return result;
-               }
-
-               private static bool ParseExact (string input, string [] formats,
-                               DateTimeFormatInfo dfi, DateTimeStyles styles, out DateTimeOffset ret)
-               {
-                       foreach (string format in formats)
-                       {
-                               if (format == null || format == String.Empty)
-                                       throw new FormatException ("Invalid format string");
-
-                               DateTimeOffset result;
-                               if (DoParse (input, format, false, out result, dfi, styles)) {
-                                       ret = result;
-                                       return true;
-                               }
-                       }
-                       ret = DateTimeOffset.MinValue;
-                       return false;
-               }
-
-               private static bool DoParse (string input, 
-                               string format,
-                               bool exact,
-                               out DateTimeOffset result,
-                               DateTimeFormatInfo dfi,
-                               DateTimeStyles styles)
-               {
-                       if ((styles & DateTimeStyles.AllowLeadingWhite) != 0) {
-                               format = format.TrimStart (null);
-                               input = input.TrimStart (null);
-                       }
-
-                       if ((styles & DateTimeStyles.AllowTrailingWhite) != 0) {
-                               format = format.TrimEnd (null);
-                               input = input.TrimEnd (null);
-                       }
-
-                       bool allow_white_spaces = false;
-                       if ((styles & DateTimeStyles.AllowInnerWhite) != 0)
-                               allow_white_spaces = true;
-
-                       bool useutc = false, use_invariants = false;
-                       if (format.Length == 1)
-                               format = DateTimeUtils.GetStandardPattern (format[0], dfi, out useutc, out use_invariants, true);
-
-                       int year = -1;
-                       int month = -1;
-                       int day = -1;
-                       int partial_hour = -1; // for 'hh tt' formats
-                       int hour = -1;
-                       int minute = -1;
-                       int second = -1;
-                       double fraction = -1;
-                       int temp_int = -1;
-                       TimeSpan offset = TimeSpan.MinValue;
-
-                       result = DateTimeOffset.MinValue;
-
-                       int fi = 0; //format iterator
-                       int ii = 0; //input iterator
-                       while (fi < format.Length) {
-                               int tokLen;
-                               char ch = format [fi];
-
-                               switch (ch) {
-                               case 'd':
-                                       tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
-                                       if (day != -1 || tokLen > 4)
-                                               return false;
-
-                                       if (tokLen <= 2)
-                                               ii += ParseNumber (input, ii, 2, tokLen == 2, allow_white_spaces, out day);
-                                       else
-                                               ii += ParseEnum (input, ii, tokLen == 3 ? dfi.AbbreviatedDayNames : dfi.DayNames, allow_white_spaces, out temp_int); 
-                                       break;
-                               case 'f':
-                                       tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
-                                       ii += ParseNumber (input, ii, tokLen, true, allow_white_spaces, out temp_int);
-                                       if (fraction >= 0 || tokLen > 7 || temp_int == -1)
-                                               return false;
-                                       fraction = (double)temp_int / Math.Pow (10, tokLen);
-                                       break;
-                               case 'F':
-                                       tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
-                                       int digits;
-                                       int read = ParseNumber (input, ii, tokLen, true, allow_white_spaces, out temp_int, out digits);
-                                       if (temp_int == -1)
-                                               ii += ParseNumber (input, ii, digits, true, allow_white_spaces, out temp_int);
-                                       else
-                                               ii += read;
-                                       if (fraction >= 0 || tokLen > 7 || temp_int == -1)
-                                               return false;   
-                                       fraction = (double)temp_int / Math.Pow (10, digits);    
-                                       break;
-                               case 'h':
-                                       tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
-                                       if (hour != -1 || tokLen > 2)
-                                               return false;
-
-                                       ii += ParseNumber (input, ii, 2, tokLen == 2, allow_white_spaces, out temp_int);
-                                       if (temp_int == -1)
-                                               return false;
-
-                                       if (partial_hour == -1)
-                                               partial_hour = temp_int;
-                                       else 
-                                               hour = partial_hour + temp_int;
-                                       break;
-                               case 'H':
-                                       tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
-                                       if (hour != -1 || tokLen > 2)
-                                               return false;
-
-                                       ii += ParseNumber (input, ii, 2, tokLen == 2, allow_white_spaces, out hour);
-                                       break;
-                               case 'm':
-                                       tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
-                                       if (minute != -1 || tokLen > 2)
-                                               return false;
-
-                                       ii += ParseNumber (input, ii, 2, tokLen == 2, allow_white_spaces, out minute);
-                                       break;
-                               case 'M':
-                                       tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
-                                       if (month != -1 || tokLen > 4)
-                                               return false;
-
-                                       if (tokLen <= 2)
-                                               ii += ParseNumber (input, ii, 2, tokLen == 2, allow_white_spaces, out month);
-                                       else {
-                                               ii += ParseEnum (input, ii, tokLen == 3 ? dfi.AbbreviatedMonthNames : dfi.MonthNames, allow_white_spaces, out month);
-                                               month += 1;
-                                       }
-
-                                       break;
-                               case 's':
-                                       tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
-                                       if (second != -1 || tokLen > 2)
-                                               return false;
-                                       ii += ParseNumber (input, ii, 2, tokLen == 2, allow_white_spaces, out second);
-                                       break;
-                               case 't':
-                                       tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
-                                       if (hour != -1 || tokLen > 2)
-                                               return false;
-
-                                       ii += ParseEnum (input, ii,
-                                                        tokLen == 1 ? new string[] {new string (dfi.AMDesignator[0], 1), new string (dfi.PMDesignator[0], 0)} 
-                                                                    : new string[] {dfi.AMDesignator, dfi.PMDesignator},
-                                                        allow_white_spaces, out temp_int);
-                                       if (temp_int == -1)
-                                               return false;
-
-                                       if (partial_hour == -1)
-                                               partial_hour = temp_int * 12;
-                                       else
-                                               hour = partial_hour + temp_int * 12;
-                                       break;
-                               case 'y':
-                                       if (year != -1)
-                                               return false;
-
-                                       tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
-                                       if (tokLen <= 2) {
-                                               ii += ParseNumber (input, ii, 2, tokLen == 2, allow_white_spaces, out year);
-                                               if (year != -1)
-                                                       year += DateTime.Now.Year - DateTime.Now.Year % 100;
-                                       } else if (tokLen <= 4) { // yyy and yyyy accept up to 5 digits with leading 0
-                                               int digit_parsed;
-                                               ii += ParseNumber (input, ii, 5, false, allow_white_spaces, out year, out digit_parsed);
-                                               if (digit_parsed < tokLen || (digit_parsed > tokLen && (year / Math.Pow (10, digit_parsed - 1) < 1)))
-                                                       return false;
-                                       } else
-                                               ii += ParseNumber (input, ii, tokLen, true, allow_white_spaces, out year);
-                                       break;
-                               case 'z':
-                                       tokLen = DateTimeUtils.CountRepeat (format, fi, ch);
-                                       if (offset != TimeSpan.MinValue || tokLen > 3)
-                                               return false;
-
-                                       int off_h, off_m = 0, sign;
-                                       temp_int = 0;
-                                       ii += ParseEnum (input, ii, new string [] {"-", "+"}, allow_white_spaces, out sign);
-                                       ii += ParseNumber (input, ii, 2, tokLen != 1, false, out off_h);
-                                       if (tokLen == 3) {
-                                               ii += ParseEnum (input, ii, new string [] {dfi.TimeSeparator}, false, out temp_int);
-                                               ii += ParseNumber (input, ii, 2, true, false, out off_m);
-                                       }
-                                       if (off_h == -1 || off_m == -1 || sign == -1)
-                                               return false;
-
-                                       if (sign == 0)
-                                               sign = -1;
-                                       offset = new TimeSpan (sign * off_h, sign * off_m, 0);
-                                       break;
-                               case ':':
-                                       tokLen = 1;
-                                       ii += ParseEnum (input, ii, new string [] {dfi.TimeSeparator}, false, out temp_int);
-                                       if (temp_int == -1)
-                                               return false;
-                                       break;
-                               case '/':
-                                       tokLen = 1;
-                                       ii += ParseEnum (input, ii, new string [] {dfi.DateSeparator}, false, out temp_int);
-                                       if (temp_int == -1)
-                                               return false;
-                                       break;
-                               case '%':
-                                       tokLen = 1;
-                                       if (fi != 0) 
-                                               return false;
-                                       break;
-                               case ' ':
-                                       tokLen = 1;
-                                       ii += ParseChar (input, ii, ' ', false, out temp_int);
-                                       if (temp_int == -1)
-                                               return false;
-                                       break;
-                               case '\\':
-                                       tokLen = 2;
-                                       ii += ParseChar (input, ii, format [fi + 1], allow_white_spaces, out temp_int);
-                                       if (temp_int == -1)
-                                               return false;
-                                       break;
-                               default:
-                                       //Console.WriteLine ("un-parsed character: {0}", ch);
-                                       tokLen = 1;
-                                       ii += ParseChar (input, ii, format [fi], allow_white_spaces, out temp_int);
-                                       if (temp_int == -1)
-                                               return false;
-                                       break;
-                               }
-                               fi += tokLen;
-                       }
-
-                       //Console.WriteLine ("{0}-{1}-{2} {3}:{4} {5}", year, month, day, hour, minute, offset);
-                       if (offset == TimeSpan.MinValue && (styles & DateTimeStyles.AssumeLocal) != 0)
-                               offset = TimeZone.CurrentTimeZone.GetUtcOffset (DateTime.Now);
-
-                       if (offset == TimeSpan.MinValue && (styles & DateTimeStyles.AssumeUniversal) != 0)
-                               offset = TimeSpan.Zero;
-
-                       if (hour < 0)           hour = 0;
-                       if (minute < 0)         minute = 0;
-                       if (second < 0)         second = 0;
-                       if (fraction < 0)       fraction = 0;
-                       if (year > 0 && month > 0 && day > 0) {
-                               result = new DateTimeOffset (year, month, day, hour, minute, second, 0, offset);
-                               result = result.AddSeconds (fraction);
-                               if ((styles & DateTimeStyles.AdjustToUniversal) != 0)
-                                       result = result.ToUniversalTime ();
-                               return true;
-                       }
-
-                       return false;
-               }
-
-               private static int ParseNumber (string input, int pos, int digits, bool leading_zero, bool allow_leading_white, out int result)
-               {
-                       int digit_parsed;
-                       return ParseNumber (input, pos, digits, leading_zero, allow_leading_white, out result, out digit_parsed);
-               }
-
-               private static int ParseNumber (string input, int pos, int digits, bool leading_zero, bool allow_leading_white, out int result, out int digit_parsed)
-               {
-                       int char_parsed = 0;
-                       digit_parsed = 0;
-                       result = 0;
-                       for (; allow_leading_white && pos < input.Length && input[pos] == ' '; pos++)
-                               char_parsed++;
-
-                       for (; pos < input.Length && Char.IsDigit (input[pos]) && digits > 0; pos ++, char_parsed++, digit_parsed++, digits --)
-                               result = 10 * result + (byte) (input[pos] - '0');
-
-                       if (leading_zero && digits > 0)
-                               result = -1;
-
-                       if (digit_parsed == 0)
-                               result = -1;
-
-                       return char_parsed;
-               }
-
-               private static int ParseEnum (string input, int pos, string [] enums, bool allow_leading_white, out int result)
-               {
-                       int char_parsed = 0;
-                       result = -1;
-                       for (; allow_leading_white && pos < input.Length && input[pos] == ' '; pos++)
-                               char_parsed ++;
-                       
-                       for (int i = 0; i < enums.Length; i++)
-                               if (input.Substring(pos).StartsWith (enums [i])) {
-                                       result = i;
-                                       break;
-                               }
-
-                       if (result >= 0)
-                               char_parsed += enums[result].Length;
-
-                       return char_parsed;     
-               }
-       
-               private static int ParseChar (string input, int pos, char c, bool allow_leading_white, out int result)
-               {
-                       int char_parsed = 0;
-                       result = -1;
-                       for (; allow_leading_white && pos < input.Length && input[pos] == ' '; pos++, char_parsed++)
-                               ;
-
-                       if (pos < input.Length && input[pos] == c){
-                               result = (int) c;
-                               char_parsed ++;
+                       Exception exception = null;
+                       bool longYear = false;
+                       try {
+                               if (!DateTime.CoreParseExact (input, formats, dfi, styles, out d, out result, true, ref longYear, true, ref exception, true))
+                                       throw exception;
+                       } catch (ArgumentOutOfRangeException ex) {
+                               throw new FormatException ("The UTC representation falls outside the 1-9999 year range", ex);
                        }
 
-                       return char_parsed;
+                       return result;
                }
 
                public TimeSpan Subtract (DateTimeOffset value)
@@ -675,9 +373,9 @@ namespace System
                        return left.Subtract (right);
                }
 
-               public static DateTimeOffset operator - (DateTimeOffset dateTimeTz, TimeSpan timeSpan)
+               public static DateTimeOffset operator - (DateTimeOffset dateTimeOffset, TimeSpan timeSpan)
                {
-                       return dateTimeTz.Subtract (timeSpan);  
+                       return dateTimeOffset.Subtract (timeSpan);      
                }
 
                public long ToFileTime ()