Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# generate a sequence/array of dates

Tags:

f#

In F# I can easily do

let a = [1 .. 10];;

Then why can't I do

let a = DateTime.Parse("01/01/2012")
let b = DateTime.Parse("01/01/2020")


let dateList = [a .. b]

It gives an error Type constraint mismatch. The type DateTime is not compatible with type TimeSpan

like image 733
Knows Not Much Avatar asked Jun 24 '12 09:06

Knows Not Much


2 Answers

There are two problems - firstly you need to specify the interval you want to use between elements of the list. This would be a TimeSpan, however it does not have a static Zero member.

This constraint is required by the skip range operator which requires the 'step' type to have static (+) and Zero members

You can define your own structure which supports the required operations however:

type TimeSpanW = { span : TimeSpan } with
  static member (+) (d:DateTime, wrapper) = d + wrapper.span
  static member Zero = { span = new TimeSpan(0L) }

You can then do:

let ts = new TimeSpan(...)
let dateList = [a .. {span = ts} .. b]

Edit: Here's an alternative syntax using discriminated unions that you may prefer:

type Span = Span of TimeSpan with
  static member (+) (d:DateTime, Span wrapper) = d + wrapper
  static member Zero = Span(new TimeSpan(0L))

let ts = TimeSpan.FromDays(1.0)
let dateList = [a .. Span(ts) .. b]
like image 99
Lee Avatar answered Oct 14 '22 03:10

Lee


Here's a funky way of generating a list of dates. Note I'm taking no credit for this whatsoever as I got it from someone else.

open System
let a = new DateTime(2013,12,1)
let b = new DateTime(2013,12,5)
Seq.unfold (fun d -> if d < b then Some(d, d.AddDays(1.0)) else None) a
 |> Seq.toList;;

It returns:

val it : DateTime list = [01/12/2013 00:00:00; 02/12/2013 00:00:00; 03/12/2013 00:00:00; 04/12/2013 00:00:00]

like image 31
jamiet Avatar answered Oct 14 '22 01:10

jamiet