简体   繁体   English

f#中自定义时钟的更好解决方案

[英]Better solution for a Custom Clock in f#

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. 例如,如果给定日期是2015年1月1日19:00,则关闭间隔是20:00 - 8:00,因此将在2015年1月10日10:00添加3小时。 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 另一个例子是Date:01 jan 2015 03:00 AM,Interval 20:00 - 08:00将给出结果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? 我的问题是:有没有人为此提供更短的解决方案?

I'd use some form of modulo operation, not a loop. 我会使用某种形式的模运算,而不是循环。 In other words, an easier way to think about the date would be: 换句话说,考虑日期的更简单方法是:

  • Which period am I in? 我在哪个时期? (Ie, which day did the current period of not-ignored time start on?) (即,哪一天的当前时间没有被忽略的时间开始?)
  • How much time inside the current period has passed? 本期内部已经过了多少时间?

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: 测试 20:00 - 8:00作为忽略的间隔,日期从8:00开始,需要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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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