tags:

views:

81

answers:

2

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 startDate..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.

  1. Is it possible to use the generator syntax to create a DateTime range?
  2. is there a better way to think about how to create the range than I wrote (i.e. the 'in' clause)
+2  A: 

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))
Alexander Rautenberg
+7  A: 

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
        }
kvb