F # генератор даты - PullRequest
       24

F # генератор даты

5 голосов
/ 15 сентября 2010

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

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
        }

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

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

Ответы [ 2 ]

11 голосов
/ 15 сентября 2010

Если 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
        }
5 голосов
/ 15 сентября 2010

Арифметическая разница между двумя объектами 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))
...