Alex Gordon
Alex Gordon

Reputation: 60741

How to parse a timespan in order to add it to a datetime?

I've got a string in the following format: 05/06/2019|1330|60

The output I'm looking for is: 05/06/2019T14:30:00

I'm attempting to parse out the TimeSpan portion right now:

  public static string getProcedureEndingDateTime (string input) {
    //05/06/2019|1330|60

    string myDate = input.Split ( '|' ) [0];
    DateTime myDateTime = DateTime.Parse (myDate);

    string myTime = input.Split('|')[1];
    string hours = myTime.Substring(0,2);
    string minutes = myTime.Substring(2,2);
    TimeSpan myTimeSpan = TimeSpan.Parse($"{hours}:{minutes}");

    myDateTime.Add(myTimeSpan);

    return myDateTime.ToString();
}

But right now, getting the following output:

enter image description here

To get the above output I'm calling my function like so:

Console.WriteLine (getProcedureEndingDateTime("05/06/2019|1330|60"));

How do I parse the string "1330" into a TimeSpan?

Upvotes: 0

Views: 755

Answers (4)

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241525

Assuming the date shown is May 6th (and not June 5th), and also assuming the 60 represents a time zone offset expressed in minutes west of GMT, and also assuming you want the corresponding UTC value, then:

public static string getProcedureEndingDateTime (string input) {

    // example input: "05/06/2019|1330|60"

    // separate the offset from the rest of the string
    string dateTimeString = input.Substring(0, 15);
    string offsetString = input.Substring(16);

    // parse the DateTime as given, and parse the offset separately, inverting the sign
    DateTime dt = DateTime.ParseExact(dateTimeString, "MM/dd/yyyy|HHmm", CultureInfo.InvariantCulture);
    TimeSpan offset = TimeSpan.FromMinutes(-int.Parse(offsetString));

    // create a DateTimeOffset from these two components
    DateTimeOffset dto = new DateTimeOffset(dt, offset);

    // Convert to UTC and return a string in the desired format
    DateTime utcDateTime = dto.UtcDateTime;
    return utcDateTime.ToString("MM/dd/yyyy'T'HH:mm:ss", CultureInfo.InvariantCulture);
}

A few additional points:

  • Not only is the input format strange, but so is your desired output format. It is strange to see a T separating the date and time and also see the date in the 05/06/2019 format. T almost always means to use ISO 8601, which requires year-month-day ordering and hyphen separators. I'd suggest either dropping the T if you want a locale-specific format, or keep the T and use the standard format. Don't do both.

  • In ISO 8601, it's also a good idea to append a Z to UTC-based values. For DateTime values, the K specifier should be used for that. In other words, you probably want the last line above to be:

    return utcDateTime.ToString("yyyy-MM-dd'T'HH:mm:ssK", CultureInfo.InvariantCulture);
    
    // outputs: "2019-05-06T14:30:00Z"
    
  • You might want to not format a string here, but instead return the DateTime or DateTimeOffset value. It's usually better to create a string only at the time of display.

  • Don't forget that the DateTime struct is immutable. In your question you were ignoring the return value of the Add method.

Upvotes: 1

0xFF
0xFF

Reputation: 838

No need to us a Timespan here, just call ParseExact instead with a proper format to do it in one line.

var myDateTime = DateTime.ParseExact("05/06/2019|1330|60", "dd/MM/yyyy|HHmm|60", CultureInfo.InvariantCulture);
Console.WriteLine(myDateTime.ToString()); 
//this gives 2019-06-05 1:30:00 PM, format depends on your PC's locale

I don't know what the 60 part is, you can adjust the format or substring it out beforehand.

Upvotes: 3

John H
John H

Reputation: 14655

The problem is because Add() returns a new DateTime instance, which means you're currently discarding it. Store it, and return that from your function instead, like so:

var adjusted = myDateTime.Add(myTimeSpan);
return adjusted.ToString();

Upvotes: 2

Rhaokiel
Rhaokiel

Reputation: 843

Try using the numeric values as exactly that, numbers.

Also, the other issue with your code is the DateTime.Add() method doesn't add to that DateTime variable. Instead it returns a new variable, which you are ignoring.

Try this:

 public static string getProcedureEndingDateTime (string input) {
    string[] parts = input.Split('|');
    string myDate = parts[0];
    DateTime myDateTime = DateTime.Parse (myDate);

    string myTime = parts[1];
    if (!int.TryParse(myTime.Substring(0,2), out int hours))
        hours = 0;
    if (!int.TryParse(myTime.Substring(2,2), out int minutes))
        minutes = 0;
    TimeSpan myTimeSpan = new TimeSpan(hours, minutes, 0);

    myDateTime += myTimeSpan;

    return myDateTime.ToString();
}

Upvotes: 1

Related Questions