What could be the cause of the validateDate() function not to execute when called?
The purpose of validateDate() is to take a string like 01/01/2001 and call isValidDate() to determine if the date is valid.
If it's not valid, then a warning message will appear.
function isValidDate(month, day, year){
/*
Purpose: return true if the date is valid, false otherwise
Arguments: day integer representing day of month
month integer representing month of year
year integer representing year
Variables: dteDate - date object
*/
var dteDate;
//set up a Date object based on the day, month and year arguments
//javascript months start at 0 (0-11 instead of 1-12)
dteDate = new Date(year, month, day);
/*
Javascript Dates are a little too forgiving and will change the date to a reasonable guess if it's invalid. We'll use this to our
advantage by creating the date object and then comparing it to the details we put it. If the Date object is different, then it must
have been an invalid date to start with...
*/
return ((day == dteDate.getDate()) && (month == dteDate.getMonth()) && (year == dteDate.getFullYear()));
}
function validateDate(datestring){
month = substr(datestring, 0, 2);
day = substr(datestring, 2, 2);
year = substr(datestring, 6, 4);
if(isValidDate(month, day, year) == false){
alert("Sorry, " + datestring + " is not a valid date.\nPlease correct this.");
return false;
} else {
return true;
}
}
substr is not a function by itself; you must use string.substr(start_index, length).
Since the JavaScript substr method only takes two parameters, not three, this causes execution to halt at the first substr line, and you'll never get output from that function.
I found this by opening Firebug when running your code in a test HTML page. I highly recommend using Firebug for JavaScript debugging.
Try this in your validateDate function, or something similar:
month = datestring.substr(0, 2);
day = datestring.substr(3, 2);
year = datestring.substr(6, 4);
substr is not defined... you need
datestring.substr(0, 2);
you also have a problem with your second substring- it should start at character 3:
day = substr(datestring, 3, 2);
and, month really should be (month - 1) when you create your date
Looking at your code, your date format is "MMDD__YYYY". So your function needs to be as follows:
function isValidDate(month, day, year){
/*
Purpose: return true if the date is valid, false otherwise
Arguments: day integer representing day of month
month integer representing month of year
year integer representing year
Variables: dteDate - date object
*/
var dteDate;
//set up a Date object based on the day, month and year arguments
//javascript months start at 0 (0-11 instead of 1-12)
dteDate = new Date(year, month, day);
alert(d)
/*
Javascript Dates are a little too forgiving and will change the date to a reasonable guess if it's invalid. We'll use this to our
advantage by creating the date object and then comparing it to the details we put it. If the Date object is different, then it must
have been an invalid date to start with...
*/
return ((day == dteDate.getDate()) && (month == dteDate.getMonth()) && (year == dteDate.getFullYear()));
}
function validateDate(datestring){
month = datestring.substring(0, 2);
day = datestring.substring(2, 4);
year = datestring.substring(6, 10);
alert(year)
if(isValidDate(month, day, year) == false){
alert("Sorry, " + datestring + " is not a valid date.\nPlease correct this.");
return false;
} else {
return true;
}
}
validateDate("0202__2010");
If your date is in a more regular format, you can do the following to test if ((new Date("MM/DD/YYYY")) != "Invalid Date")
Related
I am working on a system at the moment, that has rules based around dates ranges,
a user can submit a form, I need to check to date inputs fit within 1 of 3 dates ranges. Basically the 2 dates need to be within 1 of the 3 following rules,
01/01 - 30/04
01/05 - 30/09
01/10 - 31/12,
I need to workout what month the start date has and what month the end date has basically, and if the end date is outside of the it's range log it.
So basically, if a user submitted 01/01/2017 as a start date and 10/02/2017 as an end date, that would be a valid input, but if a user entered 01/01/2017 as a start date, and 01/06/2017 as end date that would be invalid as the date spans more than one date range.
Is it possible to check this kind of thing with javascript? I have gone through various scenarios, but the ranges in arrays and checking against array values, but I keep getting myself in a mess.
You can simply check if a date is in range with getTime()
JSBin
const isDateInRage = (startDate, endDate) => (dateToCheck) => {
return dateToCheck >= startDate && dateToCheck <= endDate
}
const isInRangeOne = isDateInRage('2016-01-01', '2016-04-30')
console.log('inRange', isInRangeOne('2016-01-02'))
console.log('outtOfRange', isInRangeOne('2016-07-02'))
Try this
// parse string 'XX/XX/XXXX' to create date object
function parseDate(str) {
var mdy = str.split('/');
return new Date(mdy[2], mdy[0]-1, mdy[1]);
}
function daysBetween(date1, date2) {
return Math.round((parseDate(date1)-parseDate(date2)) / (1000*60*60*24));
}
if(daysBetween('01/01/2017', '01/06/2017') > 1) {
// Your code here
}
Consider a function to test the start and end dates for each of the ranges and return true as soon as it fits in one of them. You'll need to correctly parse the strings, and also use the year from either the start or end date and apply it to the ranges.
The function below uses the start date and returns true if the start and end fit in one of the ranges, and false otherwise. If either the supplied start or end dates are invalid, it throws an error.
// Parse date in yyyy-mm-dd format as local date
function parseYMD(s) {
var b = s.split(/\D/);
var d = new Date(b[0], --b[1], b[2]);
return d && d.getMonth() == b[1]? d : new Date(NaN);
}
// Check start and end date are within one of the valid ranges
var checkInRange = (function () {
// Bespoke parser
function parsePart(p, y) {
p = p.split(/\D/);
return new Date(y, p[1]-1, p[0]);
}
// Valid ranges as d/m, year is taken from start date
var validRanges = ['01/01 - 30/04','01/05 - 30/09','01/10 - 31/12'];
return function (startDate, endDate) {
var dStart = parseYMD(startDate);
var dEnd = parseYMD(endDate);
// Throw error if input dates aren't valid
if (isNaN(dStart) || isNaN(dEnd)) {
throw new Error('start or end date is invalid')
}
var year = dStart.getFullYear();
// Return true if range is within valid ranges
return validRanges.some(function(range) {
var r = range.split(' - ').map(function(s){return parsePart(s, year)});
return dStart >= r[0] && dEnd <= r[1];
});
}
})();
// Some tests
[['2016-01-01','2016-04-30'],['2016-03-30','2016-04-30'],['2017-04-30','2017-05-01']].
forEach(function(dates) {
console.log('Start and end: ' + dates[0] + ' - ' + dates[1] +
'\nValid range?: ' + checkInRange(dates[0],dates[1]));
});
Do not use the Date constructor (or Date.parse) to parse strings. Their behaviour is largely implementation dependent. An ISO 8601 format date will be parsed as UTC, which is OK in this context as long as all of the strings are parsed identically, however if they aren't, users will
I'm trying to check the users input field to see if it is in the future and if it is in dd/mm/yyyy format but I have no idea why the format part of my code doesn't fire at all! In fact nothing seems to be working on Jsfiddle but at least my "check date in the future" function works locally.
I don't know the correct way of going about this.
to explain this, I've created this FIDDLE
And this is my full javascript code. I need to stay with pure javascript by the way:
function checkdate(){
//var sendDate = document.getElementById('send_year').value + '/' + document.getElementById('send_month').value + '/' + document.getElementById('send_day').value;
var sendDate = document.getElementById('returning_date').value;
sendDate = new Date(Date.parse(sendDate.replace(/-/g,' ')))
today = new Date();
today.setHours(0,0,0,0)
if (sendDate < today) {
//alert('The date can\'t be in the past. Please pick another date.');
document.getElementById('error8').innerHTML = 'The date can\'t be in the past. Please pick another date.';
return false;
}
else
{
document.getElementById('error8').innerHTML = '';
}
if(sendDate.match(/^[0-9]{4}\-(0[1-9]|1[012])\-(0[1-9]|[12][0-9]|3[01])/))
{
alert('works out');
}
}
could someone please advise on this issue?
Thanks in advance.
One problem is that you are trying to run sendDate.match, but sendDate has been converted into a Date object so it does not have a match method.
You should run your regular expression before you convert it to a Date, in validation, you typically check that the input conforms to a format before you run further validation like range validation.
Date strings should always be manually parsed, you should never allow the Date constructor or Date.parse to parse strings (the Date constructor parses strings in exactly the same way Date.parse does).
To parse and validate a date string is fairly straight forward, just parse the string and see if you get a valid date:
/* Parse a string in d/m/y format. Separator can be any non–digit
** Avoid conversion of two digit dates to 20th century
** Returns an invalid Date if string is not a valid date (per ECMA-262)
**
** #param {string} s - Date string to parse
** #returns {Date}
*/
function parseDMY(s) {
var b = s.split(/\D/);
var d = new Date();
d.setHours(0,0,0,0);
d.setFullYear(b[2], --b[1], b[0]);
return d && d.getMonth() == b[1]? d : new Date(NaN);
}
// Test valid date
document.write(parseDMY('23/01/2016'));
// Test invalid date
document.write('<br>' + parseDMY('35/12/2016'));
Note that this will accept a date like 1/5/16 and treat is as 1 May, 0016. If you want to guarantee that the day and month values have two digits and the year for, then add:
/^\d\d\D\d\d\D\d{4}$/.test(s)
to the validation test at the end. However, I don't like forcing 2 digits for day and month as people don't usually write dates as "01/08/2016", they use "1/8/2016".
First of all, the function needs to be wrapped in <head> (hit the cog in the js tab), otherwise the function can't be found.
But your main problem is that you are using European style of date formatting, so you'll get a "Invalid Date" exception when creating the date. Refer to this question on how to convert it to USA-style and make it available for the Date object (check the reference for all possible uses)
My proposal is:
Date.prototype.fromString = function(str) {
var m = str.match(/([0-9]{2})(-|\/)([0-9]{2})(-|\/)([0-9]{4})/);
if (m == null) {
return null;
}
for (var i = 0; i < m.length; i++) {
if (typeof(m[i]) === 'undefined') {
return null;
};
};
var year = parseInt(m[5]);
var month = parseInt(m[1]) - 1;
var day = parseInt(m[3]);
if (month == 0 || day == 0) {
return null;
}
return new Date(year, month, day);
}
function checkdate(e, obj, errMsgSel){
var sendDate =obj.value;
sendDate = (new Date()).fromString(sendDate);
if (sendDate == null) {
if (e.type == 'blur') {
obj.value = '';
}
return;
}
today = new Date();
today.setHours(0,0,0,0)
if (sendDate < today) {
//alert('The date can\'t be in the past. Please pick another date.');
document.getElementById(errMsgSel).innerHTML = 'The date can\'t be in the past. Please pick another date.';
return false;
}
else
{
document.getElementById(errMsgSel).innerHTML = '';
}
} $(function () {
});
<input onblur="checkdate(event, this, 'error8');" onKeyUp="checkdate(event, this, 'error8');" type='text' name="text1" placeholder='dd/mm/yyyy' id='returning_date'>
<span id='error8' style='color:red;'>format</span> <br><Br>
The user is able to determine the parameters of a query, such as:
StartTime
EndTime
ProductId
He can set any date to StartTime and EndTime but he also wants to refer the current date something like StartTime=#Today.
He also wants to add or substract days from it such as StartTime=#Today-30 so when the query runs it will always select the last 30 days.
These parameters are processed by javascript code.
How would you parse these placeholders (#Today, #CurrentMonth, #ThisWeek, etc), convert them to DateTime and do calculations on them?
DateJS, has some very powerful functions for parsing/manipulating dates. The following excerpt is from their homepage:
// What date is next thursday?
Date.today().next().thursday();
// Add 3 days to Today
Date.today().add(3).days();
// Is today Friday?
Date.today().is().friday();
// Number fun
(3).days().ago();
// 6 months from now
var n = 6;
n.months().fromNow();
// Set to 8:30 AM on the 15th day of the month
Date.today().set({ day: 15, hour: 8, minute: 30 });
// Convert text into Date
Date.parse('today');
Date.parse('t + 5 d'); // today + 5 days
Date.parse('next thursday');
Date.parse('February 20th 1973');
Date.parse('Thu, 1 July 2004 22:30:00');
By using your own values, you will be able to write a program/function that will accomplish what you need using this library
You could use a simple regex to match them:
var date = input.replace(/#(Today|ThisWeek|CurrentMonth)([+-]\d+)?/, function(_, expr, days) {
var curr = new Date();
if (expr == "Today")
curr.setHours(0, 0, 0, 0); // to Midnight
else if (expr == "ThisWeek")
curr.setDate(curr.getDate() - ((curr.getDay()+6) % 7)); // to Monday
else if (expr == "CurrentMonth")
curr.setDate(1); // to first of month
else
return "unknown keyword";
if (days)
curr.setDate(curr.getDate() + parseInt(days, 10));
return formatDate(curr);
});
function formatDate(d) {
return d.getFullYear()+"-"+("0"+(1+d.getMonth())).slice(-2)+"-"+("0"+d.getDate()).slice(-2);
}
This is very weird I don't know what I'm doing wrong. I have a function to grab the date (i.e in this format: 06/24/2011), here's the function:
function checkDate(input){
var d = new Date();
var dspl = input.split("/");
if(dspl.length != 3)
return NaN;
d.setDate(dspl[1]);
d.setMonth(Number(dspl[0])-1);
if(dspl[2].length == 2)
d.setYear("20"+(dspl[2]+""));
else if(dspl[2].length == 4)
d.setYear(dspl[2]);
else
return NaN;
var dt = jsToMsDate(new Date(d));
return dt;
}
If I enter any date of the month, it would parse the date correctly, but if I enter 31st, i.e "01/31/2011", then it would turn into "01/01/2011". I'm not sure what to do and not really sure where the problem might be.
JavaScript's Date objects allow you to give invalid combinations of months and days; they automagically correct those for you (so for instance, if you set the day of the month to 31 when the month is June, it automatically makes it July 1st). That means if you set the fields individually, you can run into situations where that automagic correction gets in your way.
In your case, if you're going to set all three of those fields, you're better off using the form of the Date constructor that accepts them as arguments:
var dt = new Date(year, month, day);
(If you want hours, minutes, seconds, and milliseconds, you can add them as parameters as well.)
So looking at your code, an off-the-cuff update:
function checkDate(input){
var year, month, day, d, dt;
var dspl = input.split("/");
if(dspl.length != 3)
return NaN;
year = parseInt(dspl[2], 10);
month = parseInt(dspl[0], 10) - 1;
day = parseInt(dspl[1], 10);
if (isNaN(year) || isNaN(month) || isNaN(day)) {
return NaN;
}
if (year < 100) {
year += 2000;
}
d = new Date(year, month, day);
var dt = jsToMsDate(d);
return dt;
}
Some other notes on that update:
It's best to use parseInt to parse numbers from end users, and to always specify the radix (10 for decimal). (No, parseInt is not slower than Number or the unary + trick. People assume it is, but it isn't.)
No need to muck about with strings to add 2000 to years given with only two digits. But you can if you like. Note I weakened the validation there, allowing one-digit years for (say) 2001 and three-digit years for (say) 300 AD. So if you need it to be that strong, you'll need to readjust that.
No need to feed the date instance into new Date() again.
You need to set the month before setting the day (or as Marc B points out in his comment, use the Date(yearval, monthval, dayval) constructor).
When you create a Date object, it defaults to the current date. At the time of writing that's in June, so when you try to set the day to 31 it wraps.
...And because of similar behaviour in leap years, you should set the year before setting the month or day.
(It's a good job you developed this code in June rather than in July - the bug would have lurked undiscovered until September, and it would probably have been your users that found it rather than you. :-)
Right hierarchy is set year, then Month and at last add the Day.
This will return the exact date that you added.
function checkDate() {
//Wrong order- will return 1 May 2016
var start = new Date();
start.setDate(31);
start.setMonth(4);
start.setFullYear(2016);
alert(start)
//Right order - will return 31 May 2016
var end = new Date();
end.setFullYear(2016);
end.setMonth(4);
end.setDate(31);
alert(end)
}
<input type="button" value="Test" onclick="checkDate()" />
This is the right heirarchy to set date.
Why are you adding 1 the day position (position 1)? I think that is your problem.
d.setDate(dspl[1] + 1);
In JavaScript, what is the best way to determine if a date provided falls within a valid range?
An example of this might be checking to see if the user input requestedDate is part of the next valid work week. Note that this is not just checking to see if one date is larger than another as a valid date would be equal to or greater than the lower end of the range while less than or equal to the upper end of the range.
This is actually a problem that I have seen come up before a lot in my works and the following bit of code is my answer to the problem.
// checkDateRange - Checks to ensure that the values entered are dates and
// are of a valid range. By this, the dates must be no more than the
// built-in number of days appart.
function checkDateRange(start, end) {
// Parse the entries
var startDate = Date.parse(start);
var endDate = Date.parse(end);
// Make sure they are valid
if (isNaN(startDate)) {
alert("The start date provided is not valid, please enter a valid date.");
return false;
}
if (isNaN(endDate)) {
alert("The end date provided is not valid, please enter a valid date.");
return false;
}
// Check the date range, 86400000 is the number of milliseconds in one day
var difference = (endDate - startDate) / (86400000 * 7);
if (difference < 0) {
alert("The start date must come before the end date.");
return false;
}
if (difference <= 1) {
alert("The range must be at least seven days apart.");
return false;
}
return true;
}
Now a couple things to note about this code, the Date.parse function should work for most input types, but has been known to have issues with some formats such as "YYYY MM DD" so you should test that before using it. However, I seem to recall that most browsers will interpret the date string given to Date.parse based upon the computers region settings.
Also, the multiplier for 86400000 should be whatever the range of days you are looking for is. So if you are looking for dates that are at least one week apart then it should be seven.
So if i understand currenctly, you need to look if one date is bigger than the other.
function ValidRange(date1,date2)
{
return date2.getTime() > date1.getTime();
}
You then need to parse the strings you are getting from the UI, with Date.parse, like this:
ValidRange(Date.parse('10-10-2008'),Date.parse('11-11-2008'));
Does that help?
var myDate = new Date(2008, 9, 16);
// is myDate between Sept 1 and Sept 30?
var startDate = new Date(2008, 9, 1);
var endDate = new Date(2008, 9, 30);
if (startDate < myDate && myDate < endDate) {
alert('yes');
// myDate is between startDate and endDate
}
There are a variety of formats you can pass to the Date() constructor to construct a date. You can also construct a new date with the current time:
var now = new Date();
and set various properties on it:
now.setYear(...);
now.setMonth(...);
// etc
See http://www.javascriptkit.com/jsref/date.shtml or Google for more details.