4

I'm trying to convert a timestamp string to a TimeSpan object. However, TimeSpan.Parse() doesn't work as I expect. I'll explain why.

There are two types of timestamps I'd like to convert.

  1. minutes:seconds
    e.g. 30:53, 1:23, 0:05
  2. hours:minutes:seconds
    e.g. 1:30:53, 2:1:23, 0:0:3

The issue is, type 1 is interpreted as an hours:minutes format in TimeSpan.Parse() method.

Console.WriteLine(TimeSpan.Parse("12:43"));
// the result I expect -> 0:12:43
// the actual result -> 12:43:00

I googled the issue and found this SO post.
Parse string in HH.mm format to TimeSpan

This uses DateTime.ParseExact() to parse a string in a certain format. However, the issue is I need to use different formats for type 1 and 2.

// ok
var ts1 = DateTime.ParseExact("7:33", "m:s", CultureInfo.InvariantCulture).TimeOfDay;
// throws an exception
var ts2 = DateTime.ParseExact("1:7:33", "m:s", CultureInfo.InvariantCulture).TimeOfDay;
// throws an exception
var ts3 = DateTime.ParseExact("7:33", "h:m:s", CultureInfo.InvariantCulture).TimeOfDay;
// ok
var ts4 = DateTime.ParseExact("1:7:33", "h:m:s", CultureInfo.InvariantCulture).TimeOfDay;

I also checked MSDN but it wasn't helpful.
https://msdn.microsoft.com/ja-jp/library/se73z7b9(v=vs.110).aspx

So the solutions I came up with were as follows.

A. DateTime.ParseExact with if

string s = "12:43";
TimeSpan ts;
if (s.Count(c => c == ':') == 1)
    ts = DateTime.ParseExact(s, "m:s", CultureInfo.InvariantCulture).TimeOfDay;
else
    ts = DateTime.ParseExact(s, "h:m:s", CultureInfo.InvariantCulture).TimeOfDay;

B. TimeSpan.Parse with if

string s = "12:43";
if (s.Count(c => c == ':') == 1)
    s = "0:" + s;
var ts = TimeSpan.Parse(s);

But both of them are lengthy and not "cool." it feels like I'm reinventing the wheel. I don't want them, any takers?

So what is a simple way to convert h:m:s and m:s strings to TimeSpan object?

Thanks in advance!

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
dixhom
  • 2,419
  • 4
  • 20
  • 36

1 Answers1

6

You can specify several formats in the TimeSpan.ParseExact:

  string source = "17:29";

  TimeSpan result = TimeSpan.ParseExact(source, 
    new string[] { @"h\:m\:s", @"m\:s" }, 
    CultureInfo.InvariantCulture);

In the code above we try h:m:s format first, and then m:s if the first format fails.

Test:

  string[] tests = new string[] { 
     // minutes:seconds
    "30:53", "1:23", "0:05", 
     // hours:minutes:seconds 
    "1:30:53", "2:1:23", "0:0:3" };

  var report = string.Join(Environment.NewLine, tests
    .Select(test => TimeSpan.ParseExact(
       test, 
       new string[] { @"h\:m\:s", @"m\:s" },
       CultureInfo.InvariantCulture)));

  Console.Write(report);

Outcome:

00:30:53
00:01:23
00:00:05
01:30:53
02:01:23
00:00:03
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215