+
+ [Test]
+ public void ParseMissingSeconds ()
+ {
+ // as seen in ML for http://resources.esri.com/arcgisserver/apis/silverlight/
+ TimeSpan ts = TimeSpan.Parse ("0:0:.75");
+
+ Assert.AreEqual (0, ts.Days, "Days");
+ Assert.AreEqual (0, ts.Hours, "Hours");
+ Assert.AreEqual (750, ts.Milliseconds, "Milliseconds");
+ Assert.AreEqual (0, ts.Minutes, "Minutes");
+ Assert.AreEqual (0, ts.Seconds, "Seconds");
+ Assert.AreEqual (7500000, ts.Ticks, "Ticks");
+ Assert.AreEqual (0.0000086805555555555555, ts.TotalDays, 0.00000000000000001, "TotalDays");
+ Assert.AreEqual (0.00020833333333333332, ts.TotalHours, 0.00000000000000001, "TotalHours");
+ Assert.AreEqual (750.0, ts.TotalMilliseconds, "TotalMilliseconds");
+ Assert.AreEqual (0.0125, ts.TotalMinutes, "TotalMinutes");
+ Assert.AreEqual (0.75, ts.TotalSeconds, "TotalSeconds");
+ }
+
+ // 'Ported' the Parse test to use TryParse
+ [Test]
+ public void TryParse ()
+ {
+ TimeSpan result;
+
+ Assert.AreEqual (true, TimeSpan.TryParse (" 13:45:15 ", out result), "#A1");
+ Assert.AreEqual ("13:45:15", result.ToString (), "#A2");
+
+ Assert.AreEqual (true, TimeSpan.TryParse (" -1:2:3 ", out result), "#B1");
+ Assert.AreEqual ("-01:02:03", result.ToString (), "#B2");
+
+ Assert.AreEqual (false, TimeSpan.TryParse ("aaa", out result), "#C2");
+
+ Assert.AreEqual (true, TimeSpan.TryParse ("-21.23:59:59.9999999", out result), "#D1");
+ Assert.AreEqual ("-21.23:59:59.9999999", result.ToString (), "#D2");
+
+ Assert.AreEqual (false, TimeSpan.TryParse ("100000000000000.1:1:1", out result), "#E1");
+ Assert.AreEqual (false, TimeSpan.TryParse ("24:60:60", out result), "#E2");
+
+#if NET_4_0
+ Assert.AreEqual (true, TimeSpan.TryParse ("0001:0002:0003.12 ", out result), "#F1");
+#else
+ Assert.AreEqual (true, TimeSpan.TryParse ("0001:0002:0003.12 ", out result), "#F1");
+ Assert.AreEqual ("01:02:03.1200000", result.ToString (), "#F2");
+#endif
+
+ Assert.AreEqual (false, TimeSpan.TryParse (" 1:2:3:12345678 ", out result), "#G1");
+
+ // Min and Max values
+ Assert.AreEqual (true, TimeSpan.TryParse ("10675199.02:48:05.4775807", out result), "MaxValue#1");
+ Assert.AreEqual (TimeSpan.MaxValue, result, "MaxValue#2");
+ Assert.AreEqual (true, TimeSpan.TryParse ("-10675199.02:48:05.4775808", out result), "MinValue#1");
+ Assert.AreEqual (TimeSpan.MinValue, result, "MinValue#2");
+
+#if NET_4_0
+ // Force the use of french culture -which is using a non common NumberDecimalSeparator-
+ // as current culture, to show that the Parse method is *actually* being culture sensitive
+ CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR");
+ CultureInfo prev_culture = CultureInfo.CurrentCulture;
+ result = new TimeSpan (0, 10, 10, 10, 6);
+ try {
+ Thread.CurrentThread.CurrentCulture = french_culture;
+ Assert.AreEqual (true, TimeSpan.TryParse ("10:10:10,006", out result), "#CultureSensitive1");
+ Assert.AreEqual ("10:10:10.0060000", result.ToString (), "#CultureSensitive2");
+ } finally {
+ // restore culture
+ Thread.CurrentThread.CurrentCulture = prev_culture;
+ }
+#endif
+ }
+
+ [Test]
+ public void TryParseErrors ()
+ {
+ TimeSpan result;
+
+ Assert.AreEqual (false, TimeSpan.TryParse ("0.99.99.0", out result), "Format#1");
+ Assert.AreEqual (false, TimeSpan.TryParse ("10675199.02:48:05.4775808", out result), "OverMaxValue");
+ Assert.AreEqual (false, TimeSpan.TryParse ("-10675199.02:48:05.4775809", out result), "UnderMinValue");
+ }
+
+#if NET_4_0
+ [Test]
+ public void TryParseOverloads ()
+ {
+ TimeSpan result;
+
+ // We use fr-FR culture since its NumericDecimalSeparator is not the same used by
+ // most cultures - including the invariant one.
+ CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR");
+ Assert.AreEqual (true, TimeSpan.TryParse ("11:50:50,006", french_culture, out result), "#A1");
+
+ // LAMESPEC - msdn states that an instance of DateTimeFormatInfo is retrieved to
+ // obtain culture sensitive information, but at least in the betas that's false
+ DateTimeFormatInfo format_info = new DateTimeFormatInfo ();
+ format_info.TimeSeparator = ";";
+ Assert.AreEqual (false, TimeSpan.TryParse ("11;50;50", format_info, out result), "#B1");
+ Assert.AreEqual (true, TimeSpan.TryParse ("11:50:50", format_info, out result), "#B2");
+ }
+
+ [Test]
+ public void ParseExact ()
+ {
+ CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR");
+ CultureInfo us_culture = CultureInfo.GetCultureInfo ("en-US");
+
+ // At this point we are only missing the style bites and then we are
+ // pretty much done with the standard formats.
+
+ //
+ // 'g' format - this is the short and culture sensitive format
+ //
+ string [] g_format = new string [] { "g" };
+ ParseExactHelper ("12", g_format, false, false, "12.00:00:00");
+ ParseExactHelper ("11:12", g_format, false, false, "11:12:00");
+ ParseExactHelper ("-11:12", g_format, false, false, "-11:12:00");
+ ParseExactHelper ("25:13", g_format, true, false, "dontcare");
+ ParseExactHelper ("11:66", g_format, true, false, "dontcare"); // I'd have expected OverflowExc here
+ ParseExactHelper ("11:12:13", g_format, false, false, "11:12:13");
+ ParseExactHelper ("-11:12:13", g_format, false, false, "-11:12:13");
+ ParseExactHelper ("10.11:12:13", g_format, true, false, "dontcare"); // this should work as well
+ ParseExactHelper ("10.11:12:13", g_format, true, false, "dontcare", us_culture);
+ ParseExactHelper ("10.11:12:13", g_format, true, false, "dontcare", CultureInfo.InvariantCulture);
+ ParseExactHelper ("10:11:12:66", g_format, true, false, "dontcare");
+ ParseExactHelper ("10:11:12:13", g_format, false, false, "10.11:12:13");
+ ParseExactHelper ("11:12:13.6", g_format, false, false, "11:12:13.6000000", CultureInfo.InvariantCulture);
+ ParseExactHelper ("11:12:13,6", g_format, false, false, "11:12:13.6000000", french_culture);
+ ParseExactHelper ("10:11:12:13.6", g_format, false, false, "10.11:12:13.6000000", us_culture);
+ ParseExactHelper (" 10:11:12:13.6 ", g_format, false, false, "10.11:12:13.6000000", us_culture);
+ ParseExactHelper ("10:11", g_format, false, false, "10:11:00", null, TimeSpanStyles.None);
+ ParseExactHelper ("10:11", g_format, false, false, "10:11:00", null, TimeSpanStyles.AssumeNegative); // no effect
+
+ //
+ // G format
+ //
+ string [] G_format = new string [] { "G" };
+ ParseExactHelper ("9:10:12", G_format, true, false, "dontcare");
+ ParseExactHelper ("9:10:12.6", G_format, true, false, "dontcare");
+ ParseExactHelper ("3.9:10:12", G_format, true, false, "dontcare");
+ ParseExactHelper ("3.9:10:12.153", G_format, true, false, "dontcare"); // this should be valid...
+ ParseExactHelper ("3:9:10:12.153", G_format, false, false, "3.09:10:12.1530000", us_culture);
+ ParseExactHelper ("0:9:10:12.153", G_format, false, false, "09:10:12.1530000", us_culture);
+ ParseExactHelper ("03:09:10:12.153", G_format, false, false, "3.09:10:12.1530000", us_culture);
+ ParseExactHelper ("003:009:0010:0012.00153", G_format, false, false, "3.09:10:12.0015300", us_culture);
+ ParseExactHelper ("3:9:10:66.153", G_format, true, false, "dontcare"); // seconds out of range
+ ParseExactHelper ("3:9:10:12.153", G_format, true, false, "dontcare", french_culture); // fr-FR uses ',' as decimal separator
+ ParseExactHelper ("3:9:10:12,153", G_format, false, false, "3.09:10:12.1530000", french_culture);
+ ParseExactHelper (" 3:9:10:12.153 ", G_format, false, false, "3.09:10:12.1530000", us_culture);
+ ParseExactHelper ("3:9:10:13.153", G_format, false, false, "3.09:10:13.1530000", us_culture, TimeSpanStyles.AssumeNegative);
+
+ // c format
+ string [] c_format = new string [] { "c" };
+ ParseExactHelper ("12", c_format, false, false, "12.00:00:00");
+ ParseExactHelper ("12:11", c_format, false, false, "12:11:00");
+ ParseExactHelper ("12:66", c_format, true, false, "dontcare");
+ ParseExactHelper ("10.11:12", c_format, false, false, "10.11:12:00");
+ ParseExactHelper ("10.11:12:13", c_format, false, false, "10.11:12:13");
+ ParseExactHelper ("10:11:12:13", c_format, true, false, "dontcare"); // this is normally accepted in the Parse method
+ ParseExactHelper ("10.11:12:13.6", c_format, false, false, "10.11:12:13.6000000");
+ ParseExactHelper ("10:11:12,6", c_format, true, false, "dontcare");
+ ParseExactHelper ("10:11:12,6", c_format, true, false, "dontcare", french_culture);
+ ParseExactHelper (" 10:11:12.6 ", c_format, false, false, "10:11:12.6000000");
+ ParseExactHelper ("10:12", c_format, false, false, "10:12:00", null, TimeSpanStyles.AssumeNegative);
+ ParseExactHelper ("10:123456789999", c_format, true, false, "dontcare");
+
+ ParseExactHelper ("10:12", new string [0], true, false, "dontcare");
+ ParseExactHelper ("10:12", new string [] { String.Empty }, true, false, "dontcare");
+ ParseExactHelper ("10:12", new string [] { null }, true, false, "dontcare");
+ }
+
+ [Test]
+ public void ParseExactMultipleFormats ()
+ {
+ ParseExactHelper ("10:12", new string [] { "G", "g" }, false, false, "10:12:00");
+ ParseExactHelper ("10:12", new string [] { "g", "G" }, false, false, "10:12:00");
+ ParseExactHelper ("7.8:9:10", new string [] { "G", "g" }, true, false, "dontcare");
+ ParseExactHelper ("7.8:9:10", new string [] { "G", "g", "c" }, false, false, "7.08:09:10");
+ ParseExactHelper ("7:8:9:10", new string [] { "c", "g" }, false, false, "7.08:09:10");
+ ParseExactHelper ("7:8:9:10", new string [] { "c", "G" }, true, false, "dontcare");
+ ParseExactHelper ("7.123456789:1", new string [] { "c", "G", "g" }, true, false, "dontcare");
+ ParseExactHelper ("7.123456789:1", new string [] { "G", "g", "c" }, true, false, "dontcare");
+ ParseExactHelper ("1234567890123456", new string [] { "c", "g" }, true, false, "dontcare"); // I'd expect an OverflowException
+ ParseExactHelper ("10:12", new string [] { null, "c", "g" }, true, false, "10:12:00");
+ ParseExactHelper ("10:12", new string [] { String.Empty, "c", "g" }, true, false, "10:12:00");
+ }
+
+ [Test]
+ public void ParseExactCustomFormats ()
+ {
+ // Days
+ ParseExactHelper ("33", new string [] { "%d" }, false, false, "33.00:00:00");
+ ParseExactHelper ("00", new string [] { "%d" }, false, false, "00:00:00");
+ ParseExactHelper ("33", new string [] { "%dd" }, false, false, "33.00:00:00");
+ ParseExactHelper ("3333", new string [] { "%d" }, false, false, "3333.00:00:00");
+ ParseExactHelper ("3333", new string [] { "%ddd" }, true, false, "3333.00:00:00"); // 'dd' mismatch the digit count
+ ParseExactHelper ("3333", new string [] { "%dddd" }, false, false, "3333.00:00:00");
+ ParseExactHelper ("00033", new string [] { "%ddddd" }, false, false, "33.00:00:00");
+ ParseExactHelper ("00033", new string [] { "%d" }, false, false, "33.00:00:00");
+ ParseExactHelper ("00000003", new string [] { "%dddddddd" }, false, false, "3.00:00:00"); // up to 8 'd'
+ ParseExactHelper ("000000003", new string [] { "%ddddddddd" }, true, false, "dontcare");
+ ParseExactHelper ("33", new string [] { "d" }, true, false, "33.00:00:00"); // This is sort of weird.
+ ParseExactHelper ("33", new string [] { "dd" }, false, false, "33.00:00:00");
+ ParseExactHelper ("-33", new string [] { "%d" }, true, false, "dontcare");
+ ParseExactHelper ("33", new string [] { "%d" }, false, false, "-33.00:00:00", null, TimeSpanStyles.AssumeNegative);
+
+ // Hours
+ ParseExactHelper ("12", new string [] { "%h" }, false, false, "12:00:00");
+ ParseExactHelper ("00", new string [] { "%h" }, false, false, "00:00:00");
+ ParseExactHelper ("012", new string [] { "%h" }, true, false, "dontcare"); // more than 2 digits
+ ParseExactHelper ("00012", new string [] { "%hhhhh" }, true, false, "dontcare");
+ ParseExactHelper ("15", new string [] { "%h" }, false, false, "15:00:00");
+ ParseExactHelper ("24", new string [] { "%h" }, true, false, "dontcare");
+ ParseExactHelper ("15", new string [] { "%hh" }, false, false, "15:00:00");
+ ParseExactHelper ("1", new string [] { "%hh" }, true, false, "dontcare"); // 'hh' but a single digit
+ ParseExactHelper ("01", new string [] { "%hh" }, false, false, "01:00:00");
+ ParseExactHelper ("015", new string [] { "%hhh" }, true, false, "dontcare"); // Too many 'h'
+ ParseExactHelper ("12", new string [] { "h" }, true, false, "dontcare");
+ ParseExactHelper ("12", new string [] { "hh" }, false, false, "12:00:00");
+ ParseExactHelper ("-15", new string [] {"%h"}, true, false, "dontcare"); // Explicit - not accepted
+ ParseExactHelper ("15", new string [] { "%h" }, false, false, "-15:00:00", null, TimeSpanStyles.AssumeNegative);
+ ParseExactHelper ("15", new string [] { "%H" }, true, false, "dontcare"); // Uppercase is not accepted
+
+ // Minutes
+ ParseExactHelper ("12", new string [] { "%m" }, false, false, "00:12:00");
+ ParseExactHelper ("00", new string [] { "%m" }, false, false, "00:00:00");
+ ParseExactHelper ("60", new string [] { "%m" }, true, false, "dontcare");
+ ParseExactHelper ("12", new string [] { "%mm" }, false, false, "00:12:00");
+ ParseExactHelper ("1", new string [] { "%mm" }, true, false, "dontcare");
+ ParseExactHelper ("12", new string [] { "%mmm" }, true, false, "dontcare");
+ ParseExactHelper ("12", new string [] { "m" }, true, false, "dontcare");
+ ParseExactHelper ("12", new string [] { "mm" }, false, false, "00:12:00");
+ ParseExactHelper ("-12", new string [] { "%m" }, true, false, "dontcare");
+ ParseExactHelper ("12", new string [] { "%m" }, false, false, "-00:12:00", null, TimeSpanStyles.AssumeNegative);
+ ParseExactHelper ("12", new string [] { "%M" }, true, false, "dontcare");
+
+ // Seconds
+ ParseExactHelper ("12", new string [] { "%s" }, false, false, "00:00:12");
+ ParseExactHelper ("00", new string [] { "%s" }, false, false, "00:00:00");
+ ParseExactHelper ("000", new string [] { "%s" }, true, false, "dontcare");
+ ParseExactHelper ("12", new string [] { "%ss" }, false, false, "00:00:12");
+ ParseExactHelper ("12", new string [] { "%sss" }, true, false, "dontcare");
+ ParseExactHelper ("60", new string [] { "%s" }, true, false, "dontcare");
+ ParseExactHelper ("-12", new string [] { "%s" }, true, false, "dontcare");
+ ParseExactHelper ("12", new string [] { "%s" }, false, false, "-00:00:12", null, TimeSpanStyles.AssumeNegative);
+
+ // Fractions of seconds - f
+ ParseExactHelper ("3", new string [] { "%f" }, false, false, "00:00:00.3000000");
+ ParseExactHelper ("0", new string [] { "%f" }, false, false, "00:00:00");
+ ParseExactHelper ("03", new string [] { "%f" }, true, false, "dontcare"); // This would work for other elements
+ ParseExactHelper ("10", new string [] { "%f" }, true, false, "dontcare"); // Only a digit is accepted with '%f'
+ ParseExactHelper ("3", new string [] { "%ff" }, true, false, "dontcare");
+ ParseExactHelper ("12", new string [] { "%ff" }, false, false, "00:00:00.1200000");
+ ParseExactHelper ("123", new string [] { "%ff" }, true, false, "dontcare");
+ ParseExactHelper ("123", new string [] { "%fff" }, false, false, "00:00:00.1230000");
+ ParseExactHelper ("1234", new string [] { "%ffff" }, false, false, "00:00:00.1234000");
+ ParseExactHelper ("1234567", new string [] { "%fffffff" }, false, false, "00:00:00.1234567");
+ ParseExactHelper ("1234567", new string [] { "%FfFFFFF" }, true, false, "dontcare"); // Mixed f and M
+ ParseExactHelper ("12345678", new string [] { "%ffffffff" }, true, false, "dontcare");
+ ParseExactHelper ("0000000", new string [] { "%fffffff" }, false, false, "00:00:00");
+
+ // Fractions of second - F
+ ParseExactHelper ("3", new string [] { "%F" }, false, false, "00:00:00.3000000");
+ ParseExactHelper ("333", new string [] { "%FFFFF" }, false, false, "00:00:00.3330000");
+ ParseExactHelper ("1234567", new string [] { "%FFFFFFF" }, false, false, "00:00:00.1234567");
+
+ // Multiple symbols
+ ParseExactHelper ("9:10", new string [] { @"h\:m" }, false, false, "09:10:00");
+ ParseExactHelper ("9;10", new string [] { @"h\;m" }, false, false, "09:10:00");
+ ParseExactHelper ("10:9", new string [] { @"m\:h" }, false, false, "09:10:00");
+ ParseExactHelper ("10:9", new string [] { @"%m\:%h" }, false, false, "09:10:00");
+ ParseExactHelper ("9 10", new string [] { @"h\ m" }, false, false, "09:10:00");
+ ParseExactHelper ("9 10", new string [] { @"h\ \ \ m" }, false, false, "09:10:00");
+ ParseExactHelper (" 9:10 ", new string [] { @"h\:m" }, true, false, "dontcare");
+ ParseExactHelper ("9:10:11", new string [] { @"h\:m\:s" }, false, false, "09:10:11");
+ ParseExactHelper ("9:10:11:6", new string [] { @"h\:m\:s\:f" }, false, false, "09:10:11.6000000");
+ ParseExactHelper ("9:10:11:666", new string [] { @"h\:m\:s\:f" }, true, false, "dontcare"); // fff with 1 digit
+ ParseExactHelper ("9:10:11:", new string [] { @"h\:m\:s\:F" }, false, false, "09:10:11"); // optional frac of seconds
+ ParseExactHelper ("9:10:11:", new string [] { @"h\:m\:s\:FF" }, false, false, "09:10:11");
+ ParseExactHelper ("9:10:11::", new string [] { @"h\:m\:s\:F\:" }, false, false, "09:10:11");
+ ParseExactHelper ("8:9:10:11:6666666", new string [] { @"d\:h\:m\:s\:fffffff" }, false, false, "8.09:10:11.6666666");
+ ParseExactHelper ("8:9:10:11:6666666", new string [] { @"d\:h\:m\:s\:fffffff" }, false, false, "-8.09:10:11.6666666",
+ null, TimeSpanStyles.AssumeNegative);
+ ParseExactHelper ("9:10", new string [] { @"h\:h" }, true, false, "dontcare"); // Repeated element
+
+ // Misc
+ ParseExactHelper (" 0 ", new string [] { "%d" }, true, false, "dontcare");
+ ParseExactHelper (" 0 ", new string [] { " %d " }, true, false, "dontcare");
+ ParseExactHelper ("0", new string [] { " %d " }, true, false, "dontcare");
+ ParseExactHelper ("::", new string [] { @"\:\:" }, false, false, "00:00:00"); // funny
+ ParseExactHelper ("::", new string [] { @"\:\:" }, false, false, "00:00:00", null, TimeSpanStyles.AssumeNegative);
+ ParseExactHelper (" 0", new string [] { @"\ d" }, false, false, "00:00:00");
+ ParseExactHelper ("Interval = 12:13:14", new string [] { @"'Interval = 'h\:m\:s" }, false, false, "12:13:14");
+ }
+
+ void ParseExactHelper (string input, string [] formats, bool format_error, bool overflow_error, string expected,
+ IFormatProvider formatProvider = null, TimeSpanStyles timeSpanStyles = TimeSpanStyles.None)
+ {
+ bool overflow_exc = false;
+ bool format_exc = false;
+ TimeSpan result = TimeSpan.Zero;
+
+ try {
+ result = TimeSpan.ParseExact (input, formats, formatProvider, timeSpanStyles);
+ } catch (OverflowException) {
+ overflow_exc = true;
+ } catch (FormatException) {
+ format_exc = true;
+ }
+
+ Assert.AreEqual (format_error, format_exc, "A1");
+ Assert.AreEqual (overflow_error, overflow_exc, "A2");
+ if (!overflow_exc && !format_exc)
+ Assert.AreEqual (expected, result.ToString ());
+ }
+
+ // 'Ported' the ParseExact test to use TryParseExact instead.
+ [Test]
+ public void TryParseExact ()
+ {
+ CultureInfo french_culture = CultureInfo.GetCultureInfo ("fr-FR");
+ CultureInfo us_culture = CultureInfo.GetCultureInfo ("en-US");
+
+ //
+ // 'g' format - this is the short and culture sensitive format
+ //
+ string [] g_format = new string [] { "g" };
+ TryParseExactHelper ("12", g_format, false, "12.00:00:00");
+ TryParseExactHelper ("11:12", g_format, false, "11:12:00");
+ TryParseExactHelper ("-11:12", g_format, false, "-11:12:00");
+ TryParseExactHelper ("25:13", g_format, true, "dontcare");
+ TryParseExactHelper ("11:66", g_format, true, "dontcare"); // I'd have expected OverflowExc here
+ TryParseExactHelper ("11:12:13", g_format, false, "11:12:13");
+ TryParseExactHelper ("-11:12:13", g_format, false, "-11:12:13");
+ TryParseExactHelper ("10.11:12:13", g_format, true, "dontcare"); // this should work as well
+ TryParseExactHelper ("10.11:12:13", g_format, true, "dontcare", us_culture);
+ TryParseExactHelper ("10.11:12:13", g_format, true, "dontcare", CultureInfo.InvariantCulture);
+ TryParseExactHelper ("10:11:12:66", g_format, true, "dontcare");
+ TryParseExactHelper ("10:11:12:13", g_format, false, "10.11:12:13");
+ TryParseExactHelper ("11:12:13.6", g_format, false, "11:12:13.6000000", CultureInfo.InvariantCulture);
+ TryParseExactHelper ("11:12:13,6", g_format, false, "11:12:13.6000000", french_culture);
+ TryParseExactHelper ("10:11:12:13.6", g_format, false, "10.11:12:13.6000000", us_culture);
+ TryParseExactHelper (" 10:11:12:13.6 ", g_format, false, "10.11:12:13.6000000", us_culture);
+ TryParseExactHelper ("10:11", g_format, false, "10:11:00", null, TimeSpanStyles.None);
+ TryParseExactHelper ("10:11", g_format, false, "10:11:00", null, TimeSpanStyles.AssumeNegative); // no effect
+
+ //
+ // G format
+ //
+ string [] G_format = new string [] { "G" };
+ TryParseExactHelper ("9:10:12", G_format, true, "dontcare");
+ TryParseExactHelper ("9:10:12.6", G_format, true, "dontcare");
+ TryParseExactHelper ("3.9:10:12", G_format, true, "dontcare");
+ TryParseExactHelper ("3.9:10:12.153", G_format, true, "dontcare"); // this should be valid...
+ TryParseExactHelper ("3:9:10:12.153", G_format, false, "3.09:10:12.1530000", us_culture);
+ TryParseExactHelper ("0:9:10:12.153", G_format, false, "09:10:12.1530000", us_culture);
+ TryParseExactHelper ("03:09:10:12.153", G_format, false, "3.09:10:12.1530000", us_culture);
+ TryParseExactHelper ("003:009:0010:0012.00153", G_format, false, "3.09:10:12.0015300", us_culture);
+ TryParseExactHelper ("3:9:10:66.153", G_format, true, "dontcare"); // seconds out of range
+ TryParseExactHelper ("3:9:10:12.153", G_format, true, "dontcare", french_culture); // fr-FR uses ',' as decimal separator
+ TryParseExactHelper ("3:9:10:12,153", G_format, false, "3.09:10:12.1530000", french_culture);
+ TryParseExactHelper (" 3:9:10:12.153 ", G_format, false, "3.09:10:12.1530000", us_culture);
+ TryParseExactHelper ("3:9:10:13.153", G_format, false, "3.09:10:13.1530000", us_culture, TimeSpanStyles.AssumeNegative);
+
+ // c format
+ string [] c_format = new string [] { "c" };
+ TryParseExactHelper ("12", c_format, false, "12.00:00:00");
+ TryParseExactHelper ("12:11", c_format, false, "12:11:00");
+ TryParseExactHelper ("12:66", c_format, true, "dontcare");
+ TryParseExactHelper ("10.11:12", c_format, false, "10.11:12:00");
+ TryParseExactHelper ("10.11:12:13", c_format, false, "10.11:12:13");
+ TryParseExactHelper ("10:11:12:13", c_format, true, "dontcare"); // this is normally accepted in the Parse method
+ TryParseExactHelper ("10.11:12:13.6", c_format, false, "10.11:12:13.6000000");
+ TryParseExactHelper ("10:11:12,6", c_format, true, "dontcare");
+ TryParseExactHelper ("10:11:12,6", c_format, true, "dontcare", french_culture);
+ TryParseExactHelper (" 10:11:12.6 ", c_format, false, "10:11:12.6000000");
+ TryParseExactHelper ("10:12", c_format, false, "10:12:00", null, TimeSpanStyles.AssumeNegative);
+ TryParseExactHelper ("10:123456789999", c_format, true, "dontcare");
+
+ TryParseExactHelper ("10:12", new string [0], true, "dontcare");
+ TryParseExactHelper ("10:12", new string [] { String.Empty }, true, "dontcare");
+ TryParseExactHelper ("10:12", new string [] { null }, true, "dontcare");
+
+ TryParseExactHelper (null, new string [] { null }, true, "dontcare");
+ }
+
+ void TryParseExactHelper (string input, string [] formats, bool error, string expected, IFormatProvider formatProvider = null,
+ TimeSpanStyles styles = TimeSpanStyles.None)
+ {
+ TimeSpan result;
+ bool success;
+
+ success = TimeSpan.TryParseExact (input, formats, formatProvider, styles, out result);
+ Assert.AreEqual (!error, success);
+ if (!error)
+ Assert.AreEqual (expected, result.ToString ());
+ }
+
+ [Test]
+ public void ParseExactExceptions ()
+ {
+ try {
+ TimeSpan.ParseExact (null, "g", null);
+ Assert.Fail ("#A1");
+ } catch (ArgumentNullException) {
+ }
+
+ try {
+ TimeSpan.ParseExact ("10:12", (string)null, null);
+ Assert.Fail ("#A2");
+ } catch (ArgumentNullException) {
+ }
+
+ try {
+ TimeSpan.ParseExact ("10:12", (string [])null, null);
+ Assert.Fail ("#A3");
+ } catch (ArgumentNullException) {
+ }
+ }
+
+ [Test]
+ public void ToStringOverloads ()
+ {
+ TimeSpan ts = new TimeSpan (1, 2, 3, 4, 6);
+
+ // Simple version - culture invariant
+ Assert.AreEqual ("1.02:03:04.0060000", ts.ToString (), "#A1");
+ Assert.AreEqual ("1.02:03:04.0060000", ts.ToString ("c"), "#A2");
+ Assert.AreEqual ("1.02:03:04.0060000", ts.ToString (null), "#A3");
+ Assert.AreEqual ("1.02:03:04.0060000", ts.ToString (String.Empty), "#A4");
+
+ //
+ // IFormatProvider ones - use a culture changing numeric format.
+ // Also, we use fr-FR as culture, since it uses some elements different to invariant culture
+ //
+ CultureInfo culture = CultureInfo.GetCultureInfo ("fr-FR");
+
+ Assert.AreEqual ("1:2:03:04,006", ts.ToString ("g", culture), "#B1");
+ Assert.AreEqual ("1:02:03:04,0060000", ts.ToString ("G", culture), "#B2");
+ Assert.AreEqual ("1.02:03:04.0060000", ts.ToString ("c", culture), "#B3"); // 'c' format ignores CultureInfo
+ Assert.AreEqual ("1.02:03:04.0060000", ts.ToString ("t", culture), "#B4"); // 't' and 'T' are the same as 'c'
+ Assert.AreEqual("1.02:03:04.0060000", ts.ToString("T", culture), "#B5");
+
+ ts = new TimeSpan (4, 5, 6);
+ Assert.AreEqual ("4:05:06", ts.ToString ("g", culture), "#C1");
+ Assert.AreEqual ("0:04:05:06,0000000", ts.ToString ("G", culture), "#C2");
+ }
+
+ [Test]
+ public void ToStringCustomFormats ()
+ {
+ TimeSpan ts = new TimeSpan (1, 3, 5, 7);
+
+ Assert.AreEqual ("1", ts.ToString ("%d"), "#A0");
+ Assert.AreEqual ("3", ts.ToString ("%h"), "#A1");
+ Assert.AreEqual ("5", ts.ToString ("%m"), "#A2");
+ Assert.AreEqual ("7", ts.ToString ("%s"), "#A3");
+ Assert.AreEqual ("0", ts.ToString ("%f"), "#A4");
+ Assert.AreEqual (String.Empty, ts.ToString ("%F"), "#A5"); // Nothing to display
+
+ Assert.AreEqual ("01", ts.ToString ("dd"), "#B0");
+ Assert.AreEqual ("00000001", ts.ToString ("dddddddd"), "#B1");
+ Assert.AreEqual ("03", ts.ToString ("hh"), "#B2");
+ Assert.AreEqual ("05", ts.ToString ("mm"), "#B3");
+ Assert.AreEqual ("07", ts.ToString ("ss"), "#B4");
+ Assert.AreEqual ("00", ts.ToString ("ff"), "#B5");
+ Assert.AreEqual ("0000000", ts.ToString ("fffffff"), "#B6");
+ Assert.AreEqual (String.Empty, ts.ToString ("FF"), "#B7");
+
+ Assert.AreEqual ("01;03;05", ts.ToString (@"dd\;hh\;mm"), "#C0");
+ Assert.AreEqual ("05 07", ts.ToString (@"mm\ ss"), "#C1");
+ Assert.AreEqual ("05 07 ", ts.ToString (@"mm\ ss\ FF"), "#C2");
+ Assert.AreEqual ("Result = 3 hours with 5 minutes and 7 seconds",
+ ts.ToString (@"'Result = 'h' hours with 'm' minutes and 's' seconds'"), "#C3");
+ Assert.AreEqual (" ", ts.ToString (@"\ \ "), "#C4");
+
+ ts = new TimeSpan (1, 3, 5, 7, 153);
+ Assert.AreEqual ("1", ts.ToString ("%F"), "#D0");
+ Assert.AreEqual ("15", ts.ToString ("FF"), "#D1"); // Don't use %, as the parser gets confused here
+ Assert.AreEqual ("153", ts.ToString ("FFFFFFF"), "#D2");
+
+ // Negative values are shown without sign
+ ts = new TimeSpan (-1, -3, -5);
+ Assert.AreEqual ("1", ts.ToString ("%h"), "#E0");
+ Assert.AreEqual ("3", ts.ToString ("%m"), "#E1");
+ Assert.AreEqual ("5", ts.ToString ("%s"), "#E2");
+
+ ts = new TimeSpan (123456789);
+ Assert.AreEqual ("12.3", ts.ToString ("s\\.f"), "#F0");
+ Assert.AreEqual ("12.3", ts.ToString ("s\\.F"), "#F1");
+ }
+
+ [Test]
+ public void ToStringOverloadsErrors ()
+ {
+ TimeSpan ts = new TimeSpan (10, 10, 10);
+ string result;
+
+ try {
+ result = ts.ToString ("non-valid");
+ Assert.Fail ("#1");
+ } catch (FormatException) {
+ }
+
+ try {
+ result = ts.ToString ("C");
+ Assert.Fail ("#2");
+ } catch (FormatException) {
+ }
+
+ try
+ {
+ ts.ToString ("m");
+ Assert.Fail ("#3");
+ } catch (FormatException) {
+ }
+
+ try
+ {
+ ts.ToString ("d"); // Missing % for single char
+ Assert.Fail ("#4");
+ } catch (FormatException)
+ {
+ }
+
+ try
+ {
+ ts.ToString ("ddddddddd");
+ Assert.Fail ("#5");
+ } catch (FormatException)
+ {
+ }
+
+ try
+ {
+ ts.ToString ("hhh");
+ Assert.Fail ("#5");
+ } catch (FormatException)
+ {
+ }
+
+ try
+ {
+ ts.ToString ("ffffffff");
+ Assert.Fail ("6");
+ } catch (FormatException)
+ {
+ }
+ }
+#endif