Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DateTime.ParseExact - how to parse single- and double-digit hours with same format string?

I want to be able to parse strings of time (hours, minutes, seconds) where the hours run from 0 to 23, and where the preceding zero for one-digit hours is optional.

Examples of time strings that I want to be able to parse into valid DateTime objects:

  • 212540
  • 061525
  • 94505

I am trying to use the C# method DateTime.ParseExact to manage the parsing, but I cannot for the life of it come up with a format string that can handle the "single-digit hour without preceding zero" scenario.

How should I specify the DateTime.ParseExact format string to sufficiently parse all examples above with the same line of code?

Inspired by the MSDN page on custom date and time formats, I have tried the following approaches:

DateTime.ParseExact(time_string, "Hmmss", CultureInfo.InvariantCulture);
DateTime.ParseExact(time_string, "%Hmmss", CultureInfo.InvariantCulture);
DateTime.ParseExact(time_string, "HHmmss", CultureInfo.InvariantCulture);

All these format strings work for the first two example cases above, but faced with a single-digit hour and no preceding zero, all formulations throw a FormatException.

like image 799
Anders Gustafsson Avatar asked Sep 24 '13 10:09

Anders Gustafsson


2 Answers

You can insert delimiters between hours, minutes and seconds like this:

string timeString = "94505";
string formatedTimeString = Regex.Replace(str, @"\d{1,2}(?=(\d{2})+$)", "$&:");
var datetime = DateTime.ParseExact(formatedTimeString, "H:mm:ss", CultureInfo.InvariantCulture);

UPDATE: I've found the cause of failure when parsing "94505" with format string "Hmmss":

What's happening is that H, m and s actually grabs two digits when they can, even if there won't be enough digits for the rest of the format. So the for example with the format Hmm and the digits 123, H would grab 12 and there would only be a 3 left. And mm requires two digits, so it fails.

So basically you have two options for handling the "single-digit hour without preceding zero" scenario:

  1. Change time format: place hours to the end (for example, "ssmmH" or "mmssH") or use delimiters (for example, "H:mm:ss")

  2. Modify the string like I've suggested earlier or like keyboardP has.

like image 82
Alexander Simonov Avatar answered Oct 29 '22 03:10

Alexander Simonov


You could pad your input string if you know that you'll always have six characters.

string input = "94505";
if(input.Length < 6)
   input = input.PadLeft(6, '0');

(Or use input.Length == 5 if you have other valid formats that are shorter).

like image 25
keyboardP Avatar answered Oct 29 '22 03:10

keyboardP