DateTime.ParseExact with varible fraction of seconds - c#

I have to parse time given in hours, minutes, seconds and fraction of seconds. Such as
"15:42:58.1"
"15:42:58.21"
"15:42:58.417"
using the following code:
DateTime.ParseExact("15:42:58.1", "HH:mm:ss.0.f", CultureInfo.InvariantCulture);
This works with excactly one decimal. Any other nomber of decimal will cause an exception.
Question:
Is there a generic possibility for the number of decimals of seconds?

You can use TimeSpan if this is a time of day or similar. See Custom TimeSpan format strings. The trick from Jeroen Mostert's comment to your question still applies: Use capital Fs.
You must escape the delimiters with TimeSpan format strings. Therefore, use one of:
var ts1 = TimeSpan.ParseExact("15:42:58.1", #"hh\:mm\:ss\.FFFFFFF", CultureInfo.InvariantCulture);
var ts2 = TimeSpan.ParseExact("15:42:58.1", "hh':'mm':'ss'.'FFFFFFF", CultureInfo.InvariantCulture);
This appears to work even with trailing zeros, e.g. "15:42:58.10" parses OK.

You can use array of DateTimeFormat.
like
string[] validFormats = { "HH:mm:ss.f", "HH:mm:ss.ff", "HH:mm:ss.fff" };
DateTime.ParseExact("15:42:58.1", validFormats, CultureInfo.InvariantCulture, DateTimeStyles.None);
Now this will parse your DateTime, even if you fraction of 3 digits
.net Fiddle

Related

ParseExact/TryParseExact failing with single digit hour [duplicate]

This question already has answers here:
DateTime conversion from string C#
(3 answers)
Closed 5 years ago.
I have a time and a date value with no field delimiters which I'm attempting to parse into a DateTime using TryParseExact. The time component has a single digit hour, and two digit minutes and seconds.
The following expression:
DateTime.ParseExact("20170101 84457", "yyyyMMdd Hmmss",
System.Globalization.CultureInfo.InvariantCulture)
results in FormatException with the message "String was not recognized as a valid DateTime.". I am assuming that this is because the time can't be unambiguously resolved, however since mm and ss are always going to be two digits each, I don't understand why this would be an issue.
The following results in successful parsing:
Hacking the input time to include delimiters (e.g., '8:44:57' and 'H:mm:ss')
Kludging the input time to have a leading zero if < 6 digits
Both of these seem a bit of a hack.
From what I can understand from other people's research, parsing attempts to retrieve two digits if it can, and parses from left to right.
Using my failing example of the raw time value 84857 and format Hmmss, because the hour is followed by a digit, it will be parsed as 84 - hence throwing a format exception.
According to the documentation:
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".
So it appears that if you don't have any delimiters, you are required to use HH and not H.
Personally I would pad the time component to 6 digits and use HH. The following works fine for me:
DateTime.ParseExact("20170101 084457", "yyyyMMdd hhmmss", System.Globalization.CultureInfo.InvariantCulture);
If you want to wrap this in a custom function, you can use something like this:
static DateTime ParseDateTime(string input)
{
int dateInteger, timeInteger;
var s = input.Split(' ');
bool dateOK = int.TryParse(s[0], out dateInteger);
bool timeOK = int.TryParse(s[1], out timeInteger);
if (!dateOK || !timeOK) throw new FormatException("Invalid date/time string.");
var newInput = String.Format("{0:00000000} {1:000000}", dateInteger, timeInteger);
return DateTime.ParseExact(newInput, "yyyyMMdd hhmmss", System.Globalization.CultureInfo.InvariantCulture);
}

Short Time with DateTime.ParseExact

I’m trying to parse a time. I’ve seen this question asked/answered here many times but not for this specific scenario. Here’s my code:
var time1 = DateTime.ParseExact("919", "Hmm", CultureInfo.InvariantCulture);
also
var time2 = DateTime.ParseExact("919", "Hmm", null);
both of these throw the same
"String was not recognized as a valid DateTime"
What I want is 9:19 AM.
For further info I also need to parse “1305” as 1:05 PM, this is working fine.
It seems to me I’m using the correct format. What am I overlooking?
I'm not sure there is any format that can handle this. The problem is that "H" can be either one digit or two, so if there are two digits available, it will grab both - in this case parsing it as hour 91, which is clearly invalid.
Ideally, you'd change the format to HHmm - zero-padding the value where appropriate - so "0919" would parse fine. Alternatively, use a colon in the format, to distinguish between the hours and the minutes. I don't believe there's any way of making DateTime parse a value of "919" as you want it to... so you'll need to adjust the string somehow before parsing it. (We don't have enough context to recommend a particular way of doing that.)
Yes, your format is right but since H specifier might be 2 character, ParseExact method try to parse 91 as an hour, which is an invalid hour, that's why you get FormatException in both case.
I connected to microsoft team about this situation 4 months ago. Take a look;
DateTime conversion from string C#
They suggest to use 2 digit form in your string or insert a date separator between them.
var time1 = DateTime.ParseExact("0919", "Hmm", CultureInfo.InvariantCulture);
or
var time1 = DateTime.ParseExact("9:19", "H:mm", CultureInfo.InvariantCulture);
You cant exclude the 0 prefix to the hour. This works
var time1 = DateTime.ParseExact("0919", "Hmm", CultureInfo.InvariantCulture);
Perhaps you want to just prefix 3-character times with a leading zero before parsing.
Much appreciated for all the answers. I don’t have control of the text being created so the simplest solution for me seemed to be prefixing a zero as opposed to adding a colon in the middle.
var text = "919";
var time = DateTime.ParseExact(text.PadLeft(4, '0'), "Hmm", null);

DateTime losing Milliseconds

I am parsing a date from a file as a string and converting it to DateTime so that I can compare it with a previous date. I am losing the milliseconds when I do this which are extremely important as I am missing lines from the file I am parsing.
Example of Date From File I am extracting: 2014/11/12 10:47:23.571
m_LatestProcessDate after I do ParseExact 12/11/2014 10:47:23
See below line of code I am using. Any ideas how I get around this?
DateTime m_LatestProcessDate = DateTime.ParseExact(m_CurrentDateString,
"yyyy/MM/dd HH:mm:ss.fff",
CultureInfo.InvariantCulture);
CodeCaster already explained your problem, I wanna add this as an answer if he let's me..
Don't worry! Your milliseconds didn't lost. They are still there. Sounds like you just didn't see them when you try to represent your m_LatestProcessDate and that's probably because your string representation of your DateTime doesn't have milliseconds part.
For example, if you use DateTime.ToString() method without any parameter, this method uses "G" standard format of your CurrentCulture.
This specifier formats your DateTime as ShortDatePattern + LongTimePattern. And no culture have Millisecond part on it's LongTimePattern.
For example; InvariantCulture has HH:mm:ss format which doesn't represent millisecond part.
You can see your milliseconds of your m_LatestProcessDate like;
Console.WriteLine(m_LatestProcessDate.ToString("fff")); // prints 571

TimeSpan.Parse Parsing Issue

I am trying to parse time using TimeSpan.Parse method; However i get an unexpected result as i am trying to parse this 00:00:45.748 which supposed to be
0 Hours
0 Minutes
45 Seconds
748 Milliseconds
TimeSpan.Parse("00:00:45.748")
Result :
00:00:45.7480000
I want to know why it reads the milliseconds as 7480000 instead of 748 ?
The result you are showing is that of displaying a TimeSpan in a textual format.
By default it will show the full range.
The string you have shown actually shows that the parse was successful and you got the right result.
If you want to format the TimeSpan, use ToString with an appropriate TimeSpan format string (.NET 4.0 and above).
There are custom and standard format strings for TimeSpan.
In your case, it looks like you are looking for:
myTimeSpan.ToString("hh:mm:ss.FFF")
As additional to Oded's answer;
From TimeSpan.Parse Method (String)
ff - Optional fractional seconds, consisting of one to seven decimal
digits.
You can use The "FFF" Custom Format Specifier
Like;
TimeSpan ts = TimeSpan.Parse("00:00:45.748");
Console.WriteLine(ts.ToString(#"hh\:mm\:ss\.FFF"), CultureInfo.InvariantCulture);
Output will be;
00:00:45.748
For more informations, take a look at Standard TimeSpan Format Strings and Custom TimeSpan Format Strings
00:00:45.7480000 == 00:00:45.748
The difference is simply the number of decimal places on the milliseconds
This will format your output as desired:
var ts = TimeSpan.Parse("00:00:45.748");
Console.WriteLine(string.Format("{0:dd\\:hh\\:mm\\:ss\\.fff}", ts));
The fff is the number of decimal places you want to display (this can be from 1 to 7). See http://msdn.microsoft.com/en-us/library/ee372287.aspx
Note that this will require .NET 4.0 or above

How to parse this string as a DateTime

How can I parse the following string to DateTime with timezone?
Should I use CultureInfo? TimeZoneInfo? Or some other kind?
15.08.11 17:15:18.084867000 +02:00
I have try to use the following format:
var z = DateTime.Now.ToString("dd.MM.yy H:mm:ss.fffffff", CultureInfo.InvariantCulture);
But it threw an exception.
DateTime.ParseExact is what you want.
The actual format string you need is dd.MM.yy HH:mm:ss.FFFFFFF00 zzz
var dateTest = "15.08.11 17:15:18.084867000 +02:00";
var format = "dd.MM.yy HH:mm:ss.FFFFFFF00 zzz";
var returnDate = DateTime.ParseExact(dateTest, format, System.Globalization.CultureInfo.InvariantCulture);
The problem is that the fractional portion of seconds can only be 7 digits, and you need to pad the format string with zeros to cater for it.
There is a problem in that the last two digits of the seconds must be 00, otherwise the format won't work, so if the last two digits are ever anything other than 00 this format string won't work for you.
You'd need to parse out the entire string excluding the last to digits of the seconds but keeping the rest of the string intact. If one was to go to that much bother one might be as well off just manually parsing the string.
Sorry I can't be of more help.

Categories