Often I need to find the duration between two dates, but with more metadata to better explain the duration, but also to be Linq compliant.
First, let’s create a class which will be the container for our metadata and will help us render more human-readable durations:
public enum EnumDurationKind { NotSet, Minute, Hour, Day, } public class Duration { public EnumDurationKind Kind { get; set; } = EnumDurationKind.NotSet; public int Amount { get; set; } public override string ToString() { var x = ""; switch (Kind) { case EnumDurationKind.Minute: x = "m"; break; case EnumDurationKind.Hour: x = "h"; break; case EnumDurationKind.Day: x = "d"; break; } if (x.IsNullOrEmpty() && Amount == 0) return ""; return $"{Amount}{x}"; } }
Now, an extension method to pull out the metadata:
public static Duration GetDurationBetweenTwoDates(this DateTime startDate, DateTime endDate) { Duration result = new Duration(); DateTime from = startDate; DateTime to = endDate; TimeSpan total = to - from; var mins = Convert.ToInt32(Math.Round(total.TotalMinutes,0)); var hours = Convert.ToInt32(Math.Round(total.TotalHours, 0)); var days = Convert.ToInt32(Math.Round(total.TotalDays, 0)); //Special case for hours, like 100 if (mins > 0 && mins % 60 != 0) { result.Amount = mins; result.Kind = EnumDurationKind.Minute; } //Special case for hours, like 26 if (result.Kind == EnumDurationKind.NotSet && hours > 0 && hours % 24 != 0) { result.Amount = hours; result.Kind = EnumDurationKind.Hour; } if (result.Kind==EnumDurationKind.NotSet && days > 0) { result.Amount = days; result.Kind = EnumDurationKind.Day; } if (result.Kind == EnumDurationKind.NotSet && hours > 0) { result.Amount = hours; result.Kind = EnumDurationKind.Hour; } if (result.Kind == EnumDurationKind.NotSet && mins > 0) { result.Amount = mins; result.Kind = EnumDurationKind.Minute; } return result; }
And finally, a test (one of many) to show it:
[Test] public void Min_60() { DateTime d = DateTime.Now; var duration = d.GetDurationBetweenTwoDates(d.AddMinutes(60)); Assert.IsTrue(duration.Kind == EnumDurationKind.Hour); Assert.IsTrue(duration.Amount == 1); }