Reputation: 374
I need a solution to add time to a date ignoring a given time interval. For example if the given date is 01 jan 2015 19:00 , the off interval is 20:00 - 8:00 adding 3 hours will give as a result 02 jan 2015 10:00. Another example is Date: 01 jan 2015 03:00 AM , Interval 20:00 - 08:00 will give as result 01 jan 2015 11:00 AM
My solution is this:
let nextInterval (d:DateTime) (s:TimeSpan) (f:TimeSpan) =
let next (d:DateTime) (ts:TimeSpan)
= if d.TimeOfDay < ts
then d.Date.Add(ts)
else d.Date.AddDays(1.0).Add(ts)
let ns = next d s
let nf = next d f
(ns,nf)
let addTime (d:DateTime) (n:TimeSpan) (s:TimeSpan) (f:TimeSpan) =
let rec loop (d:DateTime) (n:TimeSpan) =
let dt = d.TimeOfDay
let (ns,nf) = nextInterval d s f //next start interval and next finish interval
let outOfInterval = ((dt < s || dt >= f) && f >= s) ||
((dt < s && dt >=f) && f < s)
if n = TimeSpan.Zero
then if outOfInterval then d
else nf
else
if outOfInterval
then if (d+n < ns)
// before next start
then loop (d+n) TimeSpan.Zero
// intersecting with interval
else if (d+n < nf)
then loop (d+n) (n - (ns - d))
else loop nf (n - (ns - d))
else //in interval
loop nf n
loop d n
My question is : has anybody a shorter solution for this?
Upvotes: 3
Views: 214
Reputation: 6223
I'd use some form of modulo operation, not a loop. In other words, an easier way to think about the date would be:
If you want to add time, add it to the time inside the current period and then split off full periods using division and remainder.
let day = TimeSpan(1, 0, 0, 0).Ticks
let addTime (dayBegin : TimeSpan) (daySpan : TimeSpan) (d : DateTime) (dt : TimeSpan) =
if dt.Ticks < 0L then invalidArg "dt" "Negative time-spans are not supported."
let t0 = (d - dayBegin).Ticks
let rawSlot, rawSpan = t0 / day * day, t0 % day
let slot, span = if rawSpan > daySpan.Ticks then rawSlot + day, dt.Ticks
else rawSlot, rawSpan + dt.Ticks
DateTime(slot + span / daySpan.Ticks * day + span % daySpan.Ticks) + dayBegin
Test For 20:00 - 8:00 as the ignored interval, the day begins at 8:00 and takes 12h:
let test = addTime (TimeSpan(8, 0, 0)) (TimeSpan(12, 0, 0))
Using the first example as input:
test (DateTime(2015, 01, 01, 19, 0, 0)) (TimeSpan(3, 0, 0))
// result: 2015-01-02 10:00:00
Upvotes: 2