How to parse string with long milliseconds (nanoseconds) part to DateTime?
Asked Answered
C

3

6

I'm trying to figure-out the right string format of the following given date-time literal:

18-JUN-13 12.17.36.000000000

Using MSDN, I managed to composed the following format:

"d'-'MMM'-'y'T'h'.'m'.'s'.'fff"

But when using the DateTime.ParseExact, the parsing fails with a FormatException: String was not recognized as a valid DateTime.

My code:

DateTime.ParseExact("18-JUN-13 12.17.36.000000000", "d'-'MMM'-'y'T'h'.'m'.'s'.'fff", null);
Credulous answered 9/2, 2015 at 12:17 Comment(0)
L
6

You can use

dd-MMM-yy hh.mm.ss.fffffff

with english based culture like InvariantCulture for example. I'm on mobile right now, so I can't try it :(

AFAIK, milliseconds part parsing limit is 7, that's why you can't parse your string without manipulate it. You can use it like;

var dt = DateTime.ParseExact("18-JUN-13 12.17.36.0000000",
                             "dd-MMM-yy HH.mm.ss.fffffff",
                             CultureInfo.InvariantCulture);

Looks like that's why probably we have The "fffffff" custom format as top character of milliseconds. From docs;

Although it is possible to display the ten millionths of a second component of a time value, that value may not be meaningful. The precision of date and time values depends on the resolution of the system clock. On the Windows NT 3.5 (and later) and Windows Vista operating systems, the clock's resolution is approximately 10-15 milliseconds.

You asked;

How would you have manipulate the string?

Well, one way to get last index of comma and substring it to 8 index after that like;

string s = "18-JUN-13 12.17.36.000000000";
var dateString = s.Substring(0, s.LastIndexOf(".") + 8);
Loria answered 9/2, 2015 at 12:18 Comment(7)
The important thing with the 'f' formatter is that it represents one digit of sub-second precision. It has to match the number of input decimal places for it to match ParseExact.Megganmeggi
Have you tried it? It seems that you cannot use 9f. The input string's length must also match.Amygdalin
Actually the limit is 7. After 7 f's it will give you an exception.Fathom
@TimSchmelter You are right. I'm on mobile now, so I can't try it correctly. Looks like the limit of milliseconds parsing is 7. I think my second example will work.Decelerate
@BerinLoritsch Yes, you are right. Since I'm on mobile, I couldn't write it on first time. Thank you.Decelerate
@YairNevet Edited my answer. Take a look.Decelerate
The quoted text is saying that when formatting with ffff/FFFF and beyond you might end up with more digits than the system clock can represent; if you're parsing or the value to be formatted didn't originate from the Windows clock (e.g. DateTime.Now) then I don't think it applies. Instead, the reason you can't go beyond fffffff is because 0.0000001 seconds is 100 nanoseconds, which happens to be one tick, the smallest interval a DateTime can represent. It's unfortunate that neither the exception message nor the documentation calls out this limitation, which seems easy to overlook.Slavic
S
0

You can't directly parse (i.e. ParseExact()) a time string with more than seven digits after the decimal point unless, as suggested by juharr's comment on DateTime format throws exception, you parse the excess digits as literal characters:

string before = "18-JUN-13 12.17.36.000000000";
string format = "d'-'MMM'-'y' 'h'.'m'.'s'.'fffffff'00'";
DateTime value = DateTime.ParseExact(before, format, null);
string after = value.ToString(format);

Console.WriteLine(before);// 18-JUN-13 12.17.36.000000000
Console.WriteLine(after); // 18-Jun-13 12.17.36.000000000

Otherwise, you'll need to truncate the excess digits, as in Soner Gönül's answer.

It's unfortunate that neither the exception message nor the documentation calls out why fffffff/FFFFFFF is the limit, because the reason is simple but easy to overlook.

0.0000001 seconds is:

  • One ten-millionth of a second, or...
  • 100 nanoseconds, or...
  • One tick

A tick is the smallest interval a DateTime can represent. Format strings such as ffffffff (eight significant digits) and beyond can't be valid because that would require a DateTime to be able to store fractions of a tick. While "String was not recognized as a valid DateTime" does describe the problem, in this case it's not just that the input doesn't match the specified format, it's also that the input can't be precisely represented by a DateTime, anyways.

Slavic answered 18/5, 2023 at 6:55 Comment(0)
I
-1

You have a bunch of single quotes in there which isn't a correct format. Try this

DateTime.ParseExact("18-JUN-13 12.17.36.000000000", "d-MMM-yTh.m.s.fff", null);
Isoelectronic answered 9/2, 2015 at 12:20 Comment(2)
NOTE: unless you use the single quotes, the date-time formatter may change the dash to a different locale specific separator like a slash. I've been bitten by this one when parsers started to fail after someone changed their default locale.Megganmeggi
Single quotes are valid and an alternative to escaping characters individually with \; see Standard date and time format strings where several of the patterns are expressed using quotes.Slavic

© 2022 - 2024 — McMap. All rights reserved.