0

My form has a Kendo DatePicker and a button that runs a JavaScript function prior to doing a form.submit(). I need to be able to compare my date that is entered against a lower limit, and prevent the code from going on (submitting the form) if it is earlier than my set date. I want to return false if the limit hasn't been breached, true if it has. I'll use this example to show what I'm trying to do in the validation code:

var lowerBound = new Date('1776', '6','4');  // July 4, 1776
var dateField = $('#myDateField').val();  // <-- comes from Kendo DatePicker
var dateToConsider = new Date(dateField);  // if this is 1/1/0001, this changes to 1/1/1901... not good, so I do this, instead....

var arrDate = dateField.split('/'); // I also check for '-', ' ', and '.'
dateToConsider = arrDate[2] + '-' + arrDate[0] + '-' arrDate[1]; // could add 'T00:00:00Z'; but don't think it matters

var momentDTC = moment(dateToConsider);
var lowerLimitBreached = moment(lowerBound).isAfter(momentDTC); // <-- this is always false

if (!lowerLimitBreached)
    $('form').submit();

I've been inputting 1/1/0001 into the control, and it keeps giving lowerLimitBreached as false, when it should be true, since 1-1-0001 is clearly earlier than 7-4-1776... I tried using .isBefore(), but met with the same issue, and the documentation actually says NOTE: moment().isBefore() has undefined behavior and should not be used!, so I dare not use that.

Moment documentation: http://momentjs.com/docs/#/query/

vapcguy
  • 7,097
  • 1
  • 56
  • 52

2 Answers2

0

Since you're using moment.js, don't use the JavaScript Date object at all. Stick to moment objects only.

//evaluates correctly
moment('0001-01-01');

//evaluates to Feb 2, 0001 - makes no sense...
new Date(Date.parse('0001-02-03'))
                            //^ but that's a 3, not a 2

//true - Jan 1, 0001 is before June 4, 1776
moment('0001-01-01').diff(moment('1776-06-04')) < 0

So, looking at your code, try this out:

var lowerBound = moment('1776-06-04');
var dateField = $('#myDateField').val();

// String replace and put in proper format for moment
dateField = dateField.replace(/(\/)/g,'-');
var year = dateField.split('-')[2];
var month = dateField.split('-')[0];
var day = dateField.split('-')[1];

if (month < 10) { month = "0" + month; }
if (day < 10) { day = "0" + day; }
dateField = year + '-' + month + '-' + day;

// Enter into moment and compare
var dateToConsider = moment(dateField);
var lowerLimitBreached = dateToConsider.diff(lowerBound) < 0;

if (lowerLimitBreached)
    $('form').submit();
John Washam
  • 4,073
  • 4
  • 32
  • 43
ThisClark
  • 14,352
  • 10
  • 69
  • 100
  • "Since you're using moment, don't use the javascript Date object at all" --- you don't need momentjs to compare 2 dates. – zerkms Mar 25 '15 at 01:36
  • 1
    Isn't that the OPs question, though? – ThisClark Mar 25 '15 at 01:37
  • 1
    It is. OP did not state anywhere a solution must be momentjs based specifically. – zerkms Mar 25 '15 at 01:37
  • Needs to support IE 8. I used my test year, 1/1/0001 and got `Tue Jan 1 00:00:00 EST 1901`. If I used your test year of `0001-02-03`, `Date.parse` gives me `Fri Jan 02 00:00:00 EST 1903`, so it's treating the 3rd column like a year, instead of the day, for me. – vapcguy Mar 25 '15 at 01:39
  • @vapcguy "Needs to support IE 8" --- what is the reason that prevented you from putting it into the question? We cannot read your mind that you still support ancient browsers. – zerkms Mar 25 '15 at 01:40
  • Relevance. Moment supports IE 8, and using things like `Date.parse()` is vanilla JavaScript. – vapcguy Mar 25 '15 at 01:41
  • Okay, it supports it - use it. It does not - file a bug. – zerkms Mar 25 '15 at 01:41
  • This is close. If I hard-code `dateField` as `0001-01-01` it works, so the rest is getting it to work with the input format. It will come in as `1/1/0001`, so the rest is replacing the slashes (code needs 2 of those `.replace('/','-')` to make that work), and the rest is re-arranging the date so it's in the YYYY-MM-DD ISO format. So this works -- thanks. – vapcguy Mar 25 '15 at 01:57
  • Edited the code above to show how I formatted it to use the moment lines - final solution. Oh, and I noticed that moment actually doesn't need the month subtracted-by-one, but forgot to edit that from 6 to 7 for the July, up there. – vapcguy Mar 25 '15 at 06:33
  • 1
    I noticed your edit as I had to approve it. I had a question about the `.replace('/','-').replace('/','-');` - why is it necessary to do this twice? I see you also said something about it in your previous comment above. – ThisClark Mar 25 '15 at 14:08
  • One time for each `/` character. It doesn't do it throughout the string (I tried it). To do that, I believe you need `\g` or something, but I was lazy and didn't look up the syntax. – vapcguy Mar 26 '15 at 00:21
  • 2
    Apparently I never did a string replace in javascript, but I found the regular expression approach for what you're doing. Given `var s = '1/1/0001';` this expression `s = s.replace(/(\/)/g,'-');` replaces all `/`. – ThisClark Mar 26 '15 at 02:03
  • Yep, that's the one... warts and all. With all the slashes you might now understand why I initially went with my quick approach, lol. Production code could benefit from the regex, though. – vapcguy Mar 26 '15 at 02:28
-1

why don't you do this?

var lowerBound = moment('1776-6-4');
var dateField = moment($('#myDateField').val());
var lowerLimitBreached = moment(lowerBound).isAfter(dateField);

if (!lowerLimitBreached)
    $('form').submit();

You're already using moment, just convert the kendo picker's date to a moment object and use isAfter or isBefore.

If this doesn't work, please provide a date that the picker might return that's not working for you

Eonasdan
  • 7,563
  • 8
  • 55
  • 82
  • 1
    I think at this point the #myDateField value is 1/1/0001, so we need to do something about that problem. In moment or the Date constructor, both evaluate to 1901. – ThisClark Mar 25 '15 at 01:57
  • Moment will tell you if it couldn't parse the date. It might be that you need to include a format string in the second moment. What does the pickers value come back as – Eonasdan Mar 25 '15 at 02:04
  • It parses it, that's not the problem - it does put it into a date format. The problem is what ThisClark said. `dateField` shows with the 1901 date. Picker will deliver M/D/YYYY or whatever the user inputs. I was using `1/1/0001` for testing since that's what our testers were using. Typically the control uses slashes if you pick from the calendar, but does allow typing (unfortunately). – vapcguy Mar 25 '15 at 02:14
  • So the real problem is that the picker is allowing an invalid date to be entered. So why don't you test against the 1901 date or set a min date to the picker? – Eonasdan Mar 25 '15 at 02:17
  • Testing against 1901 says the value is true/allowed because the lower bound in my example is 1776, when the entered date, `1/1/0001`, is actually earlier than 1776. The min date on the picker actually is 1/1/1900, but they have the ability to type anything. So I have to set the min (which is actually lower than 1900) in the code. – vapcguy Mar 25 '15 at 02:32
  • Yes sorry I realized the 1901 was above your min date after I posted that – Eonasdan Mar 25 '15 at 02:36