Why does TimeSpan.ToString() require escaping separators?
Asked Answered
C

1

19

You can specify a custom format for a DateTime object like this:

DateTime.Now.ToString("HH:mm:ss");   // 19:55:23

But when I try to use the same format for a TimeSpan object like this:

DateTime.Now.TimeOfDay.ToString("HH:mm:ss");

I get the "Input string was not in a correct format." exception.

It turns out, the solution is that you need to escape the ':' characters like in "HH\\:mm\\:ss". Note that there is a double backslash because if you specify only one, it will break the string so you need to escape that one too.

The question is, why .NET Framework developers made it this way? There must be a reason for sure. Why can't we use custom format specifiers without escaping them like we can with a DateTime object?

Looking for .NET gurus to shed light on this subject.

Comte answered 4/1, 2014 at 17:33 Comment(1)
This MSDN link: msdn.microsoft.com/en-us/library/ee372287%28v=vs.110%29.aspx states The .NET Framework does not define a grammar for separators in time intervals., I'm not entirely sure what the reasoning is though (worth a read anyway).Alva
C
13

As stated in documentation, one of the differences between DateTime.ToString and TimeSpan.ToString format specifiers is the following: the custom TimeSpan format specifiers do not include placeholder separator symbols, such as the symbols that separate days from hours, hours from minutes, or seconds from fractional seconds. Instead, these symbols must be included in the custom format string as string literals.

In contrast with TimeSpan (see table of format specifiers in docs), DateTime format specifiers include predefined symbols for Date separator /, and for Time separator :. It means that for example for Italian culture semicolon will be recognized as time separator (not the literal) and will be replaced with . symbol:

    // outputs 09.57.18 instead of 09:57:18 because of Italian culture.
    Console.WriteLine(DateTime.Now.ToString("hh:mm:ss", CultureInfo.GetCultureInfo("it-IT")));

I think .NET designers made such difference between DateTime and TimeSpan string formatters intentionally, and it is quite reasonable. This is because historically Date/Time were formatted differently for different cultures. And .NET tried to provide globalization means for that matter along with DateTime type. But TimeSpan did not get such 'globalization' duties, it is just a type representing period of time, and formatting of it is not tied to any culture specifics (if they are ever existed), but instead formatting of it is constant in different culture settings.

Caricature answered 4/1, 2014 at 18:6 Comment(5)
Sergey, DateTime.Now.ToString("hh:mm:ss", CultureInfo.GetCultureInfo("it-IT")) does not output '.' instead of ':'. Has there been a misunderstanding?Comte
@Anar - for me it works great, in your case it probably means that some Windows settings were overriden. Does other cultures formatters work for you? Try "Ru-ru" for example, it should return dates formatted like 04.01.2014Caricature
I read your answer over and over again until I understood almost all of it :). Please explain this part: "... but instead formatting of it (TimeSpan) is constant in different culture settings." If formatting is constant then why does italian timestamp include . instead of a "constant" :? What am I not understanding?Comte
@Anar - This sentence is related to formatting of TimeSpan, and this formatting is indeed "constant" (culture-independent). My example for Italian culture was related to DateTime, which in opposite is culture-dependent. So there is no contradiction here.Caricature
I think I understand now. The main minconception here is that DateTime's natural form is a formatted date/time string whereas TimeSpan's natural form is a number (a long variable). Custom formatting for TimeSpan is not natural, but rather a kind of bonus. Hence no pre-defined formatting options. Yeah, I think I got it now :)Comte

© 2022 - 2024 — McMap. All rights reserved.