我正在尝试构建一个DateTimes序列,其中X个元素的长度可以追溯到时间,但只会落在某些TimeSpans上。这些TimeSpans是计算2个范围和提供的步长间隔之间的有效TimeSpans的结果。我首先使用以下方法计算此TimeSpans列表:
let timeSpans (rangeBottom: TimeSpan) (rangeTop: TimeSpan) (step: TimeSpan) =
let isInsideRange (timeStamp: TimeSpan) =
timeStamp >= rangeBottom && timeStamp < rangeTop
let validTimes = list<TimeSpan>.Empty
let rec checkTime (timeStamp:TimeSpan) (times: list<TimeSpan>) =
if (isInsideRange(timeStamp)) then
checkTime (timeStamp + step) (list.Cons(timeStamp, times))
else
list.Cons(rangeTop, times)
checkTime rangeBottom validTimes
因此,给定rangeBottom为10AM,rangeTop为11AM,步长为12分钟,我将生成一个包含值[11:00:00; 10:48:00; 10:36:00; 10:24:00; 10:12:00; 10:00:00]
的有效TimeSpans列表
现在,给定一个DateTime作为我的起点,我想从列表中最接近的TimeSpan开始,在周期性的时间内将其映射到我的TimeSpans列表中。
因此,如果我的注意点是今天的10:50,而我正在寻找8个值,那么我想要构建的结果序列是today 10:48, today 10:36, today 10:24, today 10:12, today 10:00, yesterday 11:00, yesterday 10:48, yesterday 10:36
我正在疯狂地试图周期性地重复使用TimeSpans以防止倒退,有人能指出我正确的方向吗?我的代码在F#中,但是如果有人能够理解这个问题并帮助我在C#中使用LINQ解决它,我很乐意将其转换过来。
答案 0 :(得分:2)
我认为这就是你想要的。
repeat
功能会将您的时间和开始日期转换为Seq
DateTime
的永不停止的Seq.skipWhile
,然后您可以Seq.take
和let times = timeSpans (TimeSpan.FromHours(10.)) (TimeSpan.FromHours(11.)) (TimeSpan.FromMinutes(12.))
let startDate = DateTime.Today.AddHours(10.).AddMinutes(50.)
let rec repeat (date:DateTime) times =
seq {
yield! times |> Seq.map (fun t -> date.Date.Add(t));
yield! repeat (date.AddDays(-1.0)) times }
times
|> repeat startDate
|> Seq.skipWhile (fun dt -> dt > startDate)
|> Seq.take 8
|> Seq.toArray
获取正确的起点和项目数。
{{1}}
答案 1 :(得分:1)
这样的事情可能有用。
let times : seq<TimeSpan> = ... //computed using your function
let timesRepeating = seq { while true do yield! times }
let dates = seq<DateTime> = ... //your list of dates
let datesRepeating =
seq { for date in dates do
for _ in times do
yield date }
Seq.zip datesRepeating timesRepeating
|> Seq.map (fun (date, time) -> date.Add(time))