# Getting the last date where a given week day occurred

I'm trying to learn a little bit about functional programming and as my tool I chose F# since I'm a .NET developer and the environment is more natural to me.

In one of my pet projects I'm dealing with dates, so I created a function to get the last date where a given week day occurred. For example, last Tuesday was yesterday (DateTime.Now.AddDays(-1.0)).

#light

module DateTimeExtensions
open System

let rec whenWasLastBasedOnDate (weekDay:DayOfWeek, currentDate:DateTime) =
match currentDate with
| _ when currentDate.DayOfWeek = weekDay -> currentDate
| _ -> whenWasLastBasedOnDate(weekDay, currentDate.AddDays(-1.0))

let whenWasLast (weekDay:DayOfWeek) =
let currentDate = DateTime.Now
match currentDate with
| _ when currentDate.DayOfWeek = weekDay -> currentDate
| _ -> whenWasLastBasedOnDate(weekDay, currentDate.AddDays(-1.0))

let now = DateTime.Now
let lastSunday = whenWasLast DayOfWeek.Sunday
let lastMonday = whenWasLast DayOfWeek.Monday
let lastTuesday = whenWasLast DayOfWeek.Tuesday
let lastWednesday = whenWasLast DayOfWeek.Wednesday
let lastThursday = whenWasLast DayOfWeek.Thursday
let lastFriday = whenWasLast DayOfWeek.Friday
let lastSaturday = whenWasLast DayOfWeek.Saturday


## 1 Answer

The most obvious point to make is that whenWasLast repeats the entire code of whenWasLastBasedOnDate. You can (and should) simply write the whole method by just calling whenWasLastBasedOnDate:

let whenWasLast (weekDay:DayOfWeek) =
whenWasLastBasedOnDate(weekDay, DateTime.Now)


Another point is that you should write AddDays(-1.0) as AddDays -1.0. In languages with ML-like syntax it is generally discouraged to add redundant parentheses around function arguments because it encourages the misconception that the parentheses are part of the method call syntax.

On a somewhat more subjective note, I think that using if would read nicer than a match without any patterns.

On a more general design note it is generally considered good style in functional programming to use higher order functions to express the code more abstractly. For example instead of saying "Check if the given day was a weekDay. If so, return it, if not repeat with the day before" you could say "Look at the last seven days and return the one who is a weekDay". This is not only more idiomatic functional programming, but also makes it impossible to get into infinite recursion by getting the exit condition wrong. In code it would look like this:

[-6.0..0.0] |> Seq.map currentDate.AddDays |>
Seq.find (fun d -> d.DayOfWeek = weekDay)

• Thank you so much! This is what I was looking for. The thought I had when created the function was exactly the same as your last one but I could not express it into code. I guess I'm too imperative yet. Refactored as you proposed. Thanks again! – tucaz Feb 3 '11 at 2:20
• Could you please edit the first part of your answer to include the corrected code with 'just whenWasLastBasedOnDate DateTime.Now'? This would help people not familiar with F# to get your idea. Thanks. – Xavier Nodet Feb 3 '11 at 10:03