0

I have a datetime, I want to show the difference from DateTime.Now to received datetime and bind it. The result should be something like this:

1d 15h 13m 7s

What is the best way to do it? StringFormat? IValueConverter?

nvoigt
  • 61,531
  • 23
  • 73
  • 116
UFO
  • 370
  • 2
  • 6
  • 14

5 Answers5

4

I'd suggest using the Timespans ToString method and custom TimeSpan format strings

Timespans if you aren't already aware are designed for measuring time intervals like this and can be convenienty obtained by subtracting one date from another.

var startDate = new DateTime(2013,1,21);
var currentDate = DateTime.Now;
TimeSpan interval = currentDate - startDate;
string intervalInWords = String.Format("{0:%d} days {0:%h} hours {0:%m} minutes {0:%s} seconds", interval);
Console.WriteLine(intervalInWords);

This will print out something like

267 days 10 hours 45 minutes 21 seconds

As has been noted in comments because these datetimes may be in different timezones/daylight saving times you should be very careful using this technique. Using UTCtime for both which is consistent throughout the whole year should be sufficient if that is feasible. In general it is often best policy to save all datetimes as UTC along with the timezone/offset (if required) and then if they are needed in a specific timezone offset convert on display.

Chris
  • 26,164
  • 4
  • 67
  • 85
  • 1
    Note that in many places of the world, as of today, your output has an extra hour in it due to daylight saving time. [`DateTime.Now` is not safe for math](http://codeofmatt.com/2013/04/25/the-case-against-datetime-now/). Other than that - good answer. – Matt Johnson-Pint Oct 15 '13 at 14:24
  • @MattJohnson: That is an excellent point. I'll add a note in to that effect. – Chris Oct 15 '13 at 18:31
1

Use TimeSpan

Example:

DateTime oldDate = new DateTime(2002,7,15);
DateTime newDate = DateTime.Now;

// Difference in days, hours, and minutes.
TimeSpan ts = newDate - oldDate;
// Difference in days.
int differenceInDays = ts.Days;

Now you can change it according to your requirement.

vikky
  • 4,746
  • 4
  • 40
  • 63
0

You can use TimeSpan, also look out [here][1]

[1]: Showing Difference between two datetime values in hours i would suggest you to go through TimeSpan.

DateTime startDate = Convert.ToDateTime(2008,8,2);
    DateTime endDate = Convert.ToDateTime(2008,8,3);
    TimeSpan duration = startDate - endDate;
Community
  • 1
  • 1
0

Create a property like DateProp of type DateTime to which you'll bind on your XAML , and assuming your property is Other_date_here, initialize it like this:

DateProp = DateTime.Now.Subtract(Other_date_here);

Last, on your XAML, bind it and set the formatting like this:

Text="{Binding Date, StringFormat=d day H hours m minutes s seconds}"

(or whatever other format you like:).

m.s.
  • 15,040
  • 6
  • 49
  • 79
Noctis
  • 10,865
  • 3
  • 38
  • 74
0

The other answers are correct from the formatting point of view, but just to address the WPF angle, I'm guessing you want to update a label/textbox so it constantly contains an accurate duration?

If so, you can do this with the timer and the dispatcher.

Timer code:

//duration in milliseconds, 1000 is 1 second
var timer = new Timer(1000);
timer.Elapsed += timer_Elapsed;
timer.Start();

Timer elapsed code:

//this is set elsewhere
private readonly DateTime _received;

void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    Application.Current.Dispatcher.Invoke(
        DispatcherPriority.Normal,
        new Action(() 
            => //replace label1 with the name of the control you wish to update
            label1.Content = 
            string.Format("{0:%d} days {0:%h} hours {0:%m} minutes {0:%s} seconds"
            , (DateTime.Now - _received))));
}
JMK
  • 24,985
  • 50
  • 147
  • 268
  • Great. Can i use it in mvvm ? is there any way to hide 0 days 0 hours ? i cant voteup for this answer. i have just 6 reputation. – UFO Oct 15 '13 at 11:04
  • Yes you can use this in MVVM, just have the Timespan as a property in a model class implementing INotifyPropertyChanged, have an instance of this class in your viewmodel, have this viewmodel as the DataContext of your view and then bind your label to the property, I can update my answer if you like? – JMK Oct 15 '13 at 11:07