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

标签 datetime time f# clock intervals

我需要一个解决方案来将时间添加到忽略给定时间间隔的日期。 例如,如果给定日期是 2015 年 1 月 1 日 19:00,关闭间隔是 20:00 - 8:00 添加 3 小时将得到 2015 年 1 月 2 日 10:00。另一个例子是 日期:2015 年 1 月 1 日 03:00 AM,间隔 20:00 - 08:00 将给出 2015 年 1 月 1 日 11:00 AM 的结果

我的解决方案是这样的:

    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

我的问题是:有人对此有更短的解决方案吗?

最佳答案

我会使用某种形式的模运算,而不是循环。换句话说,考虑日期的更简单方法是:

  • 我在哪个时期? (即,当前未忽略时间段从哪一天开始?)
  • 当前时间段内已经过去了多少时间?

如果要加时间,将其加到当前周期内的时间上,然后用除法余数拆分出整个周期。

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

测试 以20:00 - 8:00为忽略区间,一天从8:00开始,耗时12h:

let test = addTime (TimeSpan(8, 0, 0)) (TimeSpan(12, 0, 0))

使用第一个例子作为输入:

test (DateTime(2015, 01, 01, 19, 0, 0)) (TimeSpan(3, 0, 0))
// result: 2015-01-02 10:00:00

关于datetime - f# 中自定义时钟的更好解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29538342/

相关文章:

SQL 服务器 : datetime comparison ignoring few milliseconds

python - python "time.time"中的以下代码不执行任何操作

java - F#,系统.IO.IOException : All pipe instances are busy

powershell - 在 Windows 中根据修改日期删除数百万个文件的最有效方法

java - 比较忽略 Joda 中 DateTime 的秒和毫秒瞬间的日期

C# DateTime解析问题

ruby - 在一定时间间隔或满足条件时执行循环

php - 从数据库检索的 unix 时间戳获取周

f# - 从 F# 中的一组元组中获取元素

f# - FSlex/FSyacc 崩溃 - 无法找到 FSharp.Core 程序集