2010-09-15 14 views
5

Sto tentando di scrivere una funzione che genera un elenco di DateTimes utilizzando la sintassi del generatore:F # generatore di 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 
     } 

ma il generatore ('ss') per categoria non si analizza correttamente. Vuole un periodo di tempo. Mentre la sintassi del generatore sembra perfetta per quello che voglio fare, è piuttosto non intuitiva per qualcosa tranne due numeri.

  1. È possibile utilizzare la sintassi del generatore per creare un intervallo DateTime?
  2. c'è un modo migliore per pensare a come creare la gamma di quanto scritto (cioè il 'in' clausola)
+0

Il formato delle date mi rende impossibile leggere il resto di questa domanda. Seriamente, i miei occhi stanno annaffiando. – Kendrick

+0

Non capisco. Qual è il problema con il formato della data? –

risposta

5

La differenza arithemetic tra due oggetti DateTime in .NET è sempre un periodo , questo è il tuo primo problema. E se avessi un TimeSpan, non implementerebbe IEnumerable <>, quindi non può essere usato come una sequenza. È possibile scrivere il proprio espressione di sequenza, però:

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

Lo si utilizza per creare una sequenza con tutte le date nella gamma, e poi filtrare il risultato:

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

Se TimeSpan aveva una statica Zero proprietà, quindi si potrebbe fare qualcosa come startDate .. TimeSpan(1,0,0,0) .. endDate. Anche se non lo è, puoi creare un wrapper che faccia la stessa cosa:

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 
     }