I'm trying to validate a date is valid and has the iso format.
const Joi = require('joi');
const result = Joi.validate('2015-02-29', Joi.date().iso());
console.log(result);
{ error: null, value: '2015-03-01T00:00:00.000Z' }
I expected to get an error. Because February 29th, 2015 doesn't exist.
It is not testing calendar accuracy, it is testing that the string you passed in is formatted properly as an iso date string.
So the reason why you don't receive an error is because this is "gracefully" handled by the Javascript Date object. In the case of Joi we are just concerned about the ability for the string provided to be turned into a valid Javascript date.
So let's explore a little about what's going on here. Here's a couple things that you might not expect:
new Date(2015, 1, 29)
// Sun Mar 01 2015 00:00:00 GMT-0500 (Eastern Standard Time)
new Date(2015, 1, 35)
// Sat Mar 07 2015 00:00:00 GMT-0500 (Eastern Standard Time)
Interestingly enough, the Javascript Date object is handling this value for us and rolling us over to March, you'll see a similar thing for year end and any other boundary dates:
new Date(2015, 12, 35)
// Thu Feb 04 2016 00:00:00 GMT-0500 (Eastern Standard Time)
So if we go into the underlying pieces of the Date object we can see the setDate() method which states:
If the dayValue is outside of the range of date values for the month, setDate() will update the Date object accordingly. For example, if 0 is provided for dayValue, the date will be set to the last day of the previous month.
You might ask how all this works? Well, underneath the hood everything with the Date object is done based on the number of milliseconds. So if you call new Date(2015, 1, 29).setDate(0) then setDate() would just add -86400000 to the date object so that we go back a single day.
Nice info. Thanks for that @DavidTPate :D
That's very informative thanks @DavidTPate !
Should we add a validator that tests a date is valid?
In my opinion this is something that is outside the purview of Joi. What do you guys think @Marsup @WesTyler?
You would need something like moment to even do that, Date.parse just gives you march 1 :P
Yup, it looks like moment would handle this.
If the moment that results from the parsed input does not exist,
moment#isValidwill return false.
moment("2010 13", "YYYY MM").isValid(); // false (not a real month)
moment("2010 11 31", "YYYY MM DD").isValid(); // false (not a real day)
moment("2010 2 29", "YYYY MM DD").isValid(); // false (not a leap year)
moment("2010 notamonth 29", "YYYY MMM DD").isValid(); // false (not a real month name)
In the meantime @gaastonsr if you're looking to validate the value of a date (and not allow JavaScript to gracefully handle it) I'd suggest using moment or another date library that has this functionality.
it would belong in https://github.com/hapijs/joi-date-extensions though
Yeah I don't think this falls under Joi's umbrella. :) +1 for
Joi-date-extensions
On Mon, Jul 17, 2017 at 2:20 PM Adri Van Houdt notifications@github.com
wrote:
it would belong in https://github.com/hapijs/joi-date-extensions though
—
You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub
https://github.com/hapijs/joi/issues/1245#issuecomment-315838288, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ALl4O8jIuB264CCBVLQhx9WTi2ztWBwqks5sO6XhgaJpZM4OX58P
.
I'll welcome a PR on the other repo if it's still needed, closing this one.
This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions.
Most helpful comment
So the reason why you don't receive an error is because this is "gracefully" handled by the Javascript Date object. In the case of Joi we are just concerned about the ability for the string provided to be turned into a valid Javascript date.
So let's explore a little about what's going on here. Here's a couple things that you might not expect:
Interestingly enough, the Javascript Date object is handling this value for us and rolling us over to March, you'll see a similar thing for year end and any other boundary dates:
So if we go into the underlying pieces of the Date object we can see the setDate() method which states:
You might ask how all this works? Well, underneath the hood everything with the Date object is done based on the number of milliseconds. So if you call
new Date(2015, 1, 29).setDate(0)thensetDate()would just add-86400000to the date object so that we go back a single day.