.Net C# Getting a rich DateTime Duration object to represent 2 dates

2019-07-26 14_34_23-0638616_PE699035_S5.JPG (600×600).pngOften 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 { getset; } = EnumDurationKind.NotSet;
    public int Amount { getset; }
 
    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 startDateDateTime 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);
}

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s