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.
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.
Related
In the First overload of ParseExact method
public static DateTime ParseExact (string s, string format, IFormatProvider provider);
according to Microsoft:
If format is a custom format pattern that does not include date or time separators (such as "yyyyMMddHHmm"), use the invariant culture for the provider parameter and the widest form of each custom format specifier. For example, if you want to specify hours in the format pattern, specify the wider form, "HH", instead of the narrower form, "H".
In particular if we use stander format pattern we could use any other cultures
what is the really purpose of using invariant culture and widest custom specifier if we use custom format pattern that does not include date or time separators if we use?
The purpose of InvariantCulture is to have a well-known way to format dates and numbers, that does not depend on the system or user locale.
You should use it every time you format something that is not meant to be parsed by humans. For example in a JSON or XML file you want to store the date in ISO format so there is no ambiguity. On the other hand if you display the date on the screen, you generally respect the user's choice of culture and display it in the preferred way.
If you use a custom format, then it would surely be good if the resulting string can be parsed back into the exact same date and time. In order to do that without separators you have to use fixed length strings for each component.
// omitting CultureInfo.InvariantCulture for brevity
var dt = new DateTime(2018,1,2,3,45,6);
dt.ToString("yyyyMMddHHmmss") // returns "20180102034506"
dt.ToString("yyyyMdHms") // returns "2018123456"
You can easily see that the second one is not unique, i.e. there are other dates which will return the same string. In order to avoid that you use the wider form of each component.
the real purpose of invariant culture is taken taken from a an answer in this question, as it describes it's purpose best:
Not all cultures use the same format for dates and decimal / currency
values.
This will matter for you when you are converting input values (read)
that are stored as strings to DateTime, float, double or decimal. It
will also matter if you try to format the aforementioned data types to
strings (write) for display or storage.
If you know what specific culture that your dates and decimal /
currency values will be in ahead of time, you can use that specific
CultureInfo property (i.e. CultureInfo("en-GB")). For example if you
expect a user input.
The CultureInfo.InvariantCulture property is used if you are
formatting or parsing a string that should be parseable by a piece of
software independent of the user's local settings.
To sum this up, the invariant culture will help with conversions be a string stored to float, decimal or asDateTime, it is here also to help when you are trying to format or parse a string that should be parseable by a piece of software independent of the user's local settings, as the quote said and that is what
widest custom specifier
means by that.
I am getting issue on single line code ;(
TBCurrent.Text = DateTime.Now.Subtract(Current).ToString("HH:mm:ss");
This triggers on timer tick. I've tried already following formats:
"HH\:mm\:ss"
"HH':'mm':'ss"
"HH\":\"mm\":\"ss"
It works if I put just "mm" or "ss", but not even "HH mm ss".
Did you face such error before? Or this is .NET version (4.0) related?
Thank you,
Michael
That is TimeSpan formatting (see link), not DateTime. Try "hh':'mm':'ss".
It is a usual mistake to think TimeSpan formatting is the same as DateTime formatting. Before .NET 4.0, you could not format TimeSpan.
For DateTime there are two ways to write times of day, 20:50 or 8:50 PM. There "H" gives 20, and "h" gives 8. With TimeSpan, that difference is absent and you must always use lowercase h.
This format seems to get the output that you want
TBCurrent.Text = DateTime.Now.Subtract(Current).ToString(#"hh\:mm\:ss");
You need to put the backslashes before the colons because the Subtract method returns a TimeSpan not a DateTime and a TimeSpan has different rules for Custom Format String. And do not forget the # verbatim to escape the backslashes
I have a Timespan variable which should store the resulting subtraction operation from two datetime value and then display them in a dd:hh:mm format.
This is what I have tried so far and it doesn't work
Duration=(DateTime.Now- instance.StagesInformations.Last().Value.TransactionDate).ToString("\\hh:mm")
Please help
TimeSpan formatting strings are somewhat different than DateTime formatting strings. You need to escape literal characters like ::
.ToString("dd\\:hh\\:mm")
or use # so you don't have to escape the formatting escape characters:
.ToString(#"dd\:hh\:mm")
That said, why not just store as a TimeSpan and let the display layer format it? (I'm assuming you're storing in a class property based on your syntax)
To achieve your desired format dd:hh:mm it should be .ToString(#"dd\:hh\:mm")
See MSDN for reference.
How can I get today's date in M/d/yyyy format irrespective of system format of date using C#?
DateTime.Now.Tostring('M/d/yyyy')
is working only if the system date is in format dd/MM/yyyy or M/dd/yyyy but is not working in case yyyy-MM-dd format.
Eg:
if system date is 2013-06-26 then DateTime.Now.Tostring('M/d/yyyy') is converting the date into 06-26-2013 but not in 06/26/2013
Use CultureInfo.InvariantCulture to enforce / as date separator:
DateTime.Now.ToString("M/d/yyyy", CultureInfo.InvariantCulture)
Ideone
Looks like you just need to use CultureInfo.InvariantCulture as a second parameter in your .ToString method.
Console.WriteLine(DateTime.Now.ToString("M/d/yyyy", CultureInfo.InvariantCulture));
Using the invariant culture is the correct solution if you always want the same DateTime to produce the exact same string on multiple systems (or even on the same system due to culture changes). However, be aware that if this is user-visible, you're giving up the possibility of internationalization (for instance, if you display day or month names, they will be in English regardless of what language the user speaks). To only ensure that slashes are not replaced with another date separator, use single quotation marks:
DateTime.Now.Tostring("M'/'d'/'yyyy");
Edit:
Also, if your users are using different date formats, there's a good chance they're also using different time zones. If this DateTime needs to make sense across multiple systems, consider using DateTime.UtcNow. This will also protect you against potential bugs due to a user changing their time zone (when travelling, say) or daylight saving/summer time beginning/ending. If you're just displaying the string to the user at the current instance and not persisting it, DateTime.Now is probably what you want. In that case, however, I'd question why you're trying to mess with the format they've chosen.
Like this:
DateTime.Now.Tostring("M'/'d'/'yyyy");
The apostrofe forces the ToString() method to use the delimiter that you specified.
However, I would let the user choose a culture and use that cultures default formatting instead.
i am trying to format the date to this format. 01/20/2013 02:30PM EDT, using this
LastModified.ToString("MM/dd/yyyy HH:mmtt");
but the result is coming like this
01-20-2013 02:30PM dont know why it is showing '-' instead '/'.
Also, for timezome, it seems there is only format available like +02:00. But I want timezone as string, i could not find any format for this, how can I get is as string like EDT/PST/IST etc?
From the MSDN page on custom date and time format strings:
The "/" custom format specifier represents the date separator, which is used to differentiate years, months, and days. The appropriate localized date separator is retrieved from the DateTimeFormatInfoDateSeparator property of the current or specified culture.
If you want it to definitely use /, you should either use the invariant culture, or quote the slash ("MM'/'dd'/'yyyy hh':'mmtt"). Note that I've quoted the time separator as well, as that can vary by culture too. I've also changed it to use the 12 hour clock, as per Arshad's answer.
When using a custom date/time format, you should probably use the invariant culture anyway. (For example, it seems odd to use a UK culture to format the string in a US-centric way - today would normally be represented as 02/05/2013 in the UK, not 05/02/2013.)
In terms of a time zone specifier - I don't know any way to use the time zone abbrevation within date/time formatting. I would personally advise against using abbreviations anyway, as they can be ambiguous and confusing. I can't see anything within TimeZoneInfo which even exposes that information for you to manually add it.
(It's possible that in Noda Time we'll support formatting with the abbreviation, but probably not parsing, precisely because of the ambiguity.)
i have found one mistake is that ,HH means time in 24 HRS format. You can try
string date = "01/20/2013 02:30PM";
DateTime dtTime;
if (DateTime.TryParseExact(date, "MM/dd/yyyy hh:mmtt",
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.None, out dtTime))
{
Console.WriteLine(dtTime);
}
Formatting of DateTime is influenced by your Culture and your format string. Your current culture (Thread.CurrentThread.CurrentCulture) uses the - as the default seperator of your date components.
The Culture of India uses - and since you are from Inda, it would make sence (see: http://en.wikipedia.org/wiki/Date_and_time_notation_in_India)
Two options:
Choose a correct Culture which uses the / by default as seperator. For example: LastModified.ToString("MM/dd/yyyy HH:mmtt", new CultureInfo("en-US"));
Or reformat your format string with the escape character \. For example: For example: LastModified.ToString("MM\/dd\/yyyy HH:mmtt");
See also: http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx