2010-09-15 71 views
5

我試圖寫一個使用所生成語法DateTime是否列表的功能:日期範圍的F#生成器?

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 2010-09-15 19:26:39

+0

我不太明白。日期格式有什麼問題? – 2010-09-15 21:08:32

回答

5

在.NET兩個日期時間對象之間的arithemetic差異始終是一個時間跨度這是你的第一個問題。如果你有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 
     }