2010-09-15 2 views
5

Я пытаюсь написать функцию, которая формирует список DateTimes с использованием синтаксиса генератора:F # генератор daterange?

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 
     } 

, но генератор («след») блок не разобрать правильно. Он хочет время. Хотя синтаксис генератора кажется идеальным для того, что я хочу сделать, он скорее не интуитивно понятен ни для чего, кроме двух чисел.

  1. Можно ли использовать синтаксис генератора для создания диапазона DateTime?
  2. есть лучший способ думать о том, как создать диапазон, чем я написал (то есть «в» п)
+0

Формат ваших дат не позволяет мне прочитать остальную часть этого вопроса. Серьезно, мои глаза поливают. – Kendrick

+0

Я не совсем понимаю. В чем проблема с форматом даты? –

ответ

5

arithemetic разница между двумя объектами DateTime в .NET всегда TimeSpan , это ваша первая проблема. И если у вас есть TimeSpan, он не будет реализовывать IEnumerable <>, поэтому не может использоваться как последовательность. Вы можете написать собственное выражение последовательности, хотя:

let rec dates (fromDate:System.DateTime) (toDate:System.DateTime) = seq { 
      if fromDate <= toDate then 
       yield fromDate 
       yield! dates (fromDate.AddDays(1.0)) toDate 
      } 

Вы можете использовать его для создания последовательности со всеми датами в диапазоне, а затем отфильтровать результат:

let result = dates startDate endDate |> Seq.filter (fun dt -> IsBusinessDate(dt)) 
11

Если TimeSpan имела статический Zero собственность, то вы можете сделать что-то вроде startDate .. TimeSpan(1,0,0,0) .. endDate. Даже если это не так, вы можете создать обертку, которая будет делать то же самое:

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 
     }