С# TimeSpan.Parse недопустимый формат возвращает неверное значение вместо исключения
TimeSpan.Parse( "23:00:00" ) возвращает 23 часа.
TimeSpan.Parse( "24:00:00" ) возвращает 24 дня!
Я понимаю, что допустил ошибку в том, что допустимый диапазон часов равен 0-23. Но в течение минут и секунд, если вы попытаетесь проанализировать значение вне диапазона, вы получите исключение. В случае часов с пределами диапазона значение парсер неправильно предполагает, что вы означали дни вместо часов.
Может кто-нибудь объяснить это?
Этот пример здесь охватывает эту тему и указывает, что
http://msdn.microsoft.com/en-us/magazine/ee309881.aspx
То же самое можно сказать и о TryParse. Я получаю 24 дня, несмотря на документы, в которых говорится, что синтаксический анализ не завершился.
http://msdn.microsoft.com/en-us/library/3z48198e
// String to Parse TimeSpan
// --------------- ---------------------
// 0 00:00:00
// 14 14.00:00:00
// 1:2:3 01:02:03
// 0:0:0.250 00:00:00.2500000
// 10.20:30:40.50 10.20:30:40.5000000
// 99.23:59:59.9999999 99.23:59:59.9999999
// 0023:0059:0059.0099 23:59:59.0099000
// 23:0:0 23:00:00
// 24:0:0 Parse operation failed.
// 0:59:0 00:59:00
// 0:60:0 Parse operation failed.
// 0:0:59 00:00:59
// 0:0:60 Parse operation failed.
// 10: Parse operation failed.
// 10:0 10:00:00
// :10 Parse operation failed.
// 0:10 00:10:00
// 10:20: Parse operation failed.
// 10:20:0 10:20:00
// .123 Parse operation failed.
// 0.12:00 12:00:00
// 10. Parse operation failed.
// 10.12 Parse operation failed.
// 10.12:00 10.12:00:00
Я нашел ошибку или я делаю что-то неправильно?
EDIT:
Я тестировал это в LinqPad и использовал консольное приложение в .NET4 на 64-разрядной версии Windows 7.
var result = TimeSpan.Parse("24:00:00");
Console.WriteLine(result);
result = TimeSpan.Parse("24:00:00", CultureInfo.InvariantCulture);
Console.WriteLine(result);
Это приводит к:
24.00:00:00
24.00:00:00
Ответы
Ответ 1
Что происходит, так это то, что TimeSpan.Parse
пытается разобрать ##:##:##
, используя каждый из следующих форматов, чтобы остановить, как только получится:
-
hh:mm:ss
(инвариантная культура)
-
d.hh:mm
(инвариантная культура)
-
hh:mm:ss
(локализованный)
-
d.hh:mm
(локализованный, более подробная информация о "." ниже)
Итак:
-
23:08:09
успешно анализируется как 0d 23h 8m 9s на шаге 1.
-
24:08:09
успешно проанализирован как 24d 8h 9m 0s на шаге 4.
Если это не подходит вам, вы можете вместо этого использовать TimeSpan.ParseExact:
TimeSpan.ParseExact("23:00:00", "hh':'mm':'ss", null) // OK
TimeSpan.ParseExact("24:00:00", "hh':'mm':'ss", null) // OverflowException
ОБНОВЛЕНИЕ: В соответствии с документацией для TimeSpan.Parse,. между "d" и "hh" есть
Символ, чувствительный к культуре, который отделяет дни от часов. В инвариантном формате используется символ периода (..).
Тем не менее, я врывался в исходный код с Reflector, и получается, что в локализованном формате этот предполагаемый "чувствительный к культуре" символ всегда является двоеточием! Здесь выдержка из внутреннего свойства DateTimeFormatInfo.FullTimeSpanPositivePattern
:
string separator = new NumberFormatInfo(cultureData).NumberDecimalSeparator;
this.m_fullTimeSpanPositivePattern = "d':'h':'mm':'ss'" + separator + "'FFFFFFF";