2010-09-15 25 views
5

Je tente d'écrire une fonction qui génère une liste de DateTimes en utilisant la syntaxe du générateur:F # générateur 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 
     } 

mais le générateur (« seq ») bloc n'analyse pas correctement. Il veut un délai. Bien que la syntaxe du générateur semble parfaite pour ce que je veux faire, elle n'est pas intuitive pour quoi que ce soit d'autre que deux nombres.

  1. Est-il possible d'utiliser la syntaxe du générateur pour créer une plage DateTime?
  2. est-il une meilleure façon de penser sur la façon de créer la gamme que je l'ai écrit (le « dans » l'article)
+0

Le format de vos dates me rend impossible de lire le reste de cette question. Sérieusement, mes yeux arrosent. – Kendrick

+0

Je ne comprends pas très bien. Quel est le problème avec le format de date? –

Répondre

5

La différence arithemetic entre deux objets DateTime dans .NET est toujours un TimeSpan , c'est ton premier problème. Et si vous aviez un TimeSpan, il n'implémenterait pas IEnumerable <>, donc ne peut pas être utilisé comme une séquence. Vous pouvez écrire votre propre expression de séquence, cependant:

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

Vous l'utilisez pour créer une séquence avec toutes les dates de gamme, puis filtrer le résultat:

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

Si TimeSpan avait une Zero statique propriété, alors vous pourriez faire quelque chose comme startDate .. TimeSpan(1,0,0,0) .. endDate. Même si ce n'est pas le cas, vous pouvez créer un wrapper qui fera la même chose:

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 
     }