Checking if a date is valid


#1

Hello!

I’m making a module that uses dates, and I need to check if dates are valid, e.g. 29. february 1999 is not a valid date, since 1999 was not a leap year, but 29. february 1996 is a valid date since 1996 was a leap year.

The Js.Date library got the function getDate that will return NaN if the date is invalid. I have tried to use this together with Js.Float.isNaN, but it does not seem to work as a validator for dates, since it returns 29. february 1999 as valid date:

Js.Date.makeWithYMD(~year=1999., ~month=2., ~date=29., ())
          |> Js.Date.getDate
          |> Js.Float.isNaN
/* => false */

Does anyone know how to check if a date is valid in ReasonML? I know this is possible with moment, e.g. would moment('29021999', 'DDMMYYYY').isValid() return false, but I would like to avoid third party libraries if possible.

Regards Mikael


#2

Okay, so I think I can tell you why you are not getting NaN as you expect. What the best Reason alternative is I’m not sure, hopefully someone else can help you there.

So, first a simple error: Months in JS Dates are 0-indexed! So your call should look like:

Js.Date.makeWithYMD(~year=1999., ~month=1., ~date=29., ())

Second, at least in my browser this actually returns the 28. of february at time 23.00. I’m not sure why, maybe something timezone-y? Anyway, we can pass an hour argument to force this:

Js.Date.makeWithYMDH(~year=1999., ~month=1., ~date=29., ~hours=1., ())

This fixes it on my browser. Maybe you didn’t have this problem in the first place? Anyway, JS claims this is still not NaN, and inspecting the actual date created we can see why: It has simply overflown to March 1st instead.

Moral of the story: There is a reason we wanted to get away from JS in the first place - whenever you use JS.* functions, be ready for the usual Javascript nonsensical quirks.
I’m unfortunately not too familiar with the ecosystem, so I can’t tell you the best alternative. There are Moment bindings, but without using third party libraries, you would need something from the Reason/OCaml standard library, and I’m just not familiar enough with that. Hopefully someone else will come through and recommend something, I would be interested to hear it as well.


#3

Thanks for such a thorough answer, that was clarifying! To bad Js.Date apparently couldn’t help even if the zero indexed month and hour was fixed.

I am very interested in Reason/Ocaml way of dealing with dates, and if there is any way to validate dates without JS code.


#4

Someone recently posted this on discord: https://github.com/mobily/re-date/blob/master/src/ReDate.rei
They say “it has similar API to date-fns but it has been written in pure reasonml.”


#5

@jdeisenberg thank you for mentioning re-date! :blush:

@mikael I have just added the isValid function, let me know if this is something that you need :slight_smile:

Usage:

ReDate.isValid(~year=1999., ~month=1., ~date=29., ())

#6

That seem to do the trick! Simple and clever implementation of the isValid function :slight_smile:

Great job, thanks!