2010-09-15 7 views
5

Estoy intentando escribir una función que genera una lista de DateTime utilizando la sintaxis del generador:F # generador de 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 
     } 

pero el generador ('SEC') de bloque no analiza correctamente. Quiere un intervalo de tiempo. Si bien la sintaxis del generador parece perfecta para lo que quiero hacer, no es intuitiva para nada que no sean dos números.

  1. ¿Es posible usar la sintaxis del generador para crear un rango de DateTime?
  2. ¿Hay una mejor manera de pensar acerca de cómo crear el rango de lo que escribí (es decir, el 'en' cláusula)
+0

El formato de sus fechas me impide leer el resto de esta pregunta. En serio, mis ojos están llorando. – Kendrick

+0

No lo entiendo del todo. ¿Cuál es el problema con el formato de fecha? –

Respuesta

5

La diferencia arithemetic entre dos objetos DateTime en .NET es siempre un intervalo de tiempo ese es tu primer problema Y si tiene un TimeSpan, no implementará IEnumerable <>, por lo que no se puede usar como una secuencia. Usted puede escribir su propia expresión de secuencia, sin embargo:

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

Se utiliza para crear una secuencia con todas las fechas en rango, y luego filtrar el resultado:

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

Si TimeSpan tenían una estática Zero propiedad, entonces podría hacer algo como startDate .. TimeSpan(1,0,0,0) .. endDate. Aunque no es así, puede crear un contenedor que haga lo mismo:

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 
     }