I'm attempting to write a function that generates a list of DateTimes using the generator syntax:
let dateRange =
let endDate = System.DateTime.Parse("6/1/2010")
let startDate = System.DateTime.Parse("3/1/2010")
seq {
for date in startD开发者_如何学Pythonate..endDate do
if MyDateClass.IsBusinessDay(date) then yield date
}
but the generator ('seq') block does not parse correctly. It wants a timespan. While the generator syntax seems perfect for what I want to do, it's rather non-intuitive for anything but two numbers.
- Is it possible to use the generator syntax to create a DateTime range?
- is there a better way to think about how to create the range than I wrote (i.e. the 'in' clause)
If TimeSpan
had a static Zero
property, then you could do something like startDate .. TimeSpan(1,0,0,0) .. endDate
. Even though it doesn't, you can create a wrapper that will do the same thing:
open System
type TimeSpanWrapper = { timeSpan : TimeSpan } with
static member (+)(d:DateTime, tw) = d + tw.timeSpan
static member Zero = { timeSpan = TimeSpan(0L) }
let dateRange =
let endDate = System.DateTime.Parse("6/1/2010")
let startDate = System.DateTime.Parse("5/1/2010")
let oneDay = { timeSpan = System.TimeSpan(1,0,0,0) }
seq {
for date in startDate .. oneDay .. endDate do
if MyDateClass.IsBusinessDay(date) then yield date
}
The arithemetic difference between two DateTime objects in .NET is always a TimeSpan, that's your first problem. And if you had a TimeSpan, it wouldn't implement IEnumerable<>, so can't be used as a sequence. You can write your own sequence expression, though:
let rec dates (fromDate:System.DateTime) (toDate:System.DateTime) = seq {
if fromDate <= toDate then
yield fromDate
yield! dates (fromDate.AddDays(1.0)) toDate
}
You use it to create a sequence with all the dates in range, and then filter the result:
let result = dates startDate endDate |> Seq.filter (fun dt -> IsBusinessDate(dt))
精彩评论