简体   繁体   中英

Return actual hours of day between two times

I have a rather interesting problem at the minute where i want to return the actual hour values between two times. I dont mind if this is either in c# or mysql but i'm not sure what way to go about it.

Eg Time 1= 13:00 & Time 2= 18:10

i would like to return 13:00,14:00,15:00,16:00,17:00,18:00

There is plenty around for calculating the hour count between two times and i know i can use that integer value and increment my base hour as below but i was wondering if there was a cleaner way?

Mysql

timediff('2014-04-01 18:10:00', '2014-04-01 13:00:00' ) 

returns 05:10:00

hour('2014-04-01 13:00:00')

returns 13

increment the 13 by the hour value

seems long winded :(

I recommend working with DateTime and TimeSpan classes. You can use this:

double HoursBetween(DateTime t1, DateTime t2)
{
    return (t2 - t1).TotalHours;
}

You may want to apply some rounding if you need int return type.

What is happening is that the - operator for two DateTime objects is defined so a TimeSpan object is created which holds the time difference. TotalHours simply returns the TimeSpan value expressed in whole and fractional hours.

In C# to enumerate all (full) hours from start to end :

public static IEnumerable<DateTime> Hours(DateTime start, DateTime end)
{
    start -= TimeSpan.FromMinutes(start.TimeOfDay.TotalMinutes);
    end -= TimeSpan.FromMinutes(end.TimeOfDay.TotalMinutes);

    return Enumerable.Range(0, (int)Math.Ceiling((end - start).TotalHours))
        .Select(x => begin + TimeSpan.FromHours(x));
}

First we remove minutes from interval boundaries, we need whole hours only (so 10:30 and 11:10 will result in two hours, not just the difference between them). Then we create an enumeration from zero to number of whole hours, we'll use it to create offsets from beginning. I keep start DateTime using calculated TimeSpan as offset to keep track of date changes (for example if interval boundary is across two or more days).

If, for example, start is 2014/04/01 10:25 and end is 2014/04/01 13:20 then you'll get:

2014/04/01 10:00
2014/04/01 11:00
2014/04/01 12:00
2014/04/01 13:00

To get just time part change return type to IEnumerable<TimeSpan> and last Select() to:

.Select(x => (begin + TimeSpan.FromHours(x)).TimeOfDay);

In SQL it can be done but it's little bit more tricky because you need a working table with a sequence of integers. Please note following code is untested.

First you need to calculate that difference:

CEIL(TIMESTAMPDIFF(MINUTE, startDate, endDate) / 60)

Now you can use a working table filled with numbers for offsets:

Value
-----
0
1
2
3
...

With this:

SELECT
    DATE_ADD(startDate, INTERVAL Value HOUR)
FROM 
    NumericTable
WHERE
    Value <= CEIL(TIMESTAMPDIFF(MINUTE, startDate, endDate) / 60)

In both cases (C# and SQL) you may replace output DateTime / Date with a TimeSpan / TIME object).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM