I am developing a application. In this application have a input field. where the user can input the dates by different formats like
ddmmyy, ddmmyyyy, dd-mm-yy, mm-dd-yy
And I need to verify the date whether that valid or not. I can able to validate this way:
YYYY-MM-DD using:
var myDate = new Date("1987-08-06") // it returns me the date while this valid.
But I can't able to validate with other formats. how can i validate that?
example:
var myDate = new Date("08-06-1987")..etc?
I developed my app using jQuery. I am looking some solution without using a plug-in. since i used no.of plugins already.
thanks in advance!
I would do it with regular expressions. You could define a regexp pattern for each of your formats. Then you can test if the String from the input field matches any of the pattern.
Somthing like this:
var regExpDDMMYY = /[0-9]{2}[0-1][0-9][0-9]{2}/g;
var regExpddmmyyyy = ...;
...
...
if (regExpDDMMYY.test(yourInputStringFromDateField)) {
// handleDateAs DDMMYY
} else if (regExpddmmyyyy .test(yourInputStringFromDateField)) {
...
} else {
throw new YourException();
}
You can find an example here:
http://www.w3schools.com/js/js_regexp.asp
Unfortunately, there's no "parseExact" in native JS, that would also be crossbrowser. So you either need to use Date.js library or write some converter.
For this task i'd recommend you to use "Chain of responsibility" pattern
function DateTimeParser() {
this.parse = function (input) {
for (var key in Parsers) {
var result = Parsers[key].parse(input);
if (result !== null)
return result;
}
return null;
};
this.parseExact = function (input, format) {
var parser = Parsers[format];
return parser ? parser.parse(input) : null;
};
var ConcreteDateTimeParser = function (expression, parser) {
this.parse = function (input) {
if (!input.match(expression))
return null;
var result = parser(input);
return isNaN(result.getDate()) ? null : result;
};
};
var Parsers = {
"dd-mm-yyyy": new ConcreteDateTimeParser(/\d{2}\-\d{2}\-\d{4}/, function (input) {
var dd = parseInt(input.slice(0, 2)),
mm = parseInt(input.slice(3, 5)),
yyyy = parseInt(input.slice(-4));
return new Date(yyyy, mm, dd);
}),
"ddmmyyyy": new ConcreteDateTimeParser(/\d{8}/, function (input) {
var dd = parseInt(input.slice(0, 2)),
mm = parseInt(input.slice(2, 4)),
yyyy = parseInt(input.slice(-4));
return new Date(yyyy, mm, dd);
})
};
};
var instance = new DateTimeParser();
instance.parse('22122012');
instance.parseExact('22122012', 'ddmmyyyy');
instance.parseExact('22122012', 'dd-mm-yyyy'); // null
From this you can extend your Parsers lib with additional parsers. You also can use different sets of parsers by passing them into DateTimeParser as a constructor argument. My code is pretty trivial, for i didn't want to write it mega-deep, just wanted to show the way =)
Related
I am trying to parse a date from a text format to see if milliseconds and seconds were included in it.
For e.g.
let text = '2016-02-02 14:30:34.234';
const timezone = 'America/Los_Angeles';
// const hasMS = utcParse('%Y-%m-%d %H:%M:%S.')(text);
// const hasSeconds = utcParse('%Y-%m-%d %H:%M:')(text);
const hasMS = !!moment.tz(text, 'YYYY-MM-DD HH:MM:ss.', timezone);
console.log('hasMS', hasMS);
const hasSeconds = !!moment.tz(text, 'YYYY-MM-DD HH:MM:', timezone);
console.log('hasSeconds', hasSeconds);
Basically I am trying to replace the commented code. utcParse() from d3.time-format would check if the date text has milliseconds and seconds in it. I tried a couple of things for momentjs library, but it doesn't seem to work.
By using Regular expressions you can check if certain parts of the string are present.
If you call matchDateTime() with the string you get an array back with all the matched groups.
let text_min = '2016-02-02 14:30';
let text_sec = '2016-02-02 14:30:34';
let text_ms = '2016-02-02 14:30:34.234';
function matchDateTime(text) { return text.match(/(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/); }
function hasSeconds(text) { return !!matchDateTime(text)[6]; }
function hasMilliSeconds(text) { return !!matchDateTime(text)[7]; }
function testTimeString(text) {
console.log(text, "hasSeconds=", hasSeconds(text));
console.log(text, "hasMilliSeconds=", hasMilliSeconds(text));
}
testTimeString(text_min);
testTimeString(text_sec);
testTimeString(text_ms);
console.log(matchDateTime(text_ms));
I am using full calendar and I am trying to see if an event created is overlapping with the lunch breaks which I have defined as part of business hours. This is my code
function isCalendarEventOverlappingBusinessHour(event)
{
var evts = businessHoursArr;
for (i in evts)
{
var start_moment=moment(evts[i].start, 'MMM DD').format();
var end_moment=moment(evts[i].end);
if (event.start.isBefore(end_moment) && event.end.isAfter(start_moment))
{
return true;
}
}
return false;
}
I am not able to compare the event start and business hour start since in business hours, the time is defined in string format as 08:00:00. I want to convert it into a moment so that I can compare the times. Can anyone suggest a method?
My event is in the following format:
events.push({
id: guid(),
title: eventTitle,
start: moment(date),
end: moment(date).add(defaultTimedEventDuration,'hours'),
stick: true,
});
And my businesshoursarr looks like
{
dow:[1,2,3,4,5]
start:08:00:00
end:12:00:00
},
{
dow:[1,2,3,4,5]
start:13:00:00
end:17:00:00
}
I'd suggest moment(value, 'HH:mm:ss').valueOf() which will return an integer and you could just compare numbers at that point.
It'd also help if you provided an example of what businessHoursArr and event look like.
Update: Taking your code and making a few modifications, this should give you the general idea.
function isCalendarEventOverlappingBusinessHour(event) {
var evts = businessHoursArr;
var overlapping = false;
var dayFormat = 'YYYYMMDD';
var secFormat = dayFormat + 'HH:mm:ss';
var eventStartDate = event.start.format(dayFormat);
var eventEndDate = event.end.format(dayFormat);
for (i in evts) {
var start_moment = moment(eventStartDate + evts[i].start, secFormat);
var end_moment = moment(eventEndDate + evts[i].end, secFormat);
if (event.start.isBefore(end_moment) && event.end.isAfter(start_moment)) {
overlapping = true;
break;
}
}
return overlapping;
}
I'm trying to combine the Datepicker and Timepicker directives to get the date from the first and the time from the second in a combined Date object. I came across some examples that are not using these directives like this one Combining Date and Time input strings as a Date object. However when I try to apply something similar to my case it's not working. Console returns "TypeError: $scope.dt.split is not a function". Above is the function I try to use which is called by $watch.
function tryCombineDateTime() {
if ($scope.dt && $scope.mytime) {
var dateParts = $scope.dt.split('-');
var timeParts = $scope.mytime.split(':');
if (dateParts && timeParts) {
dateParts[1] -= 1;
$scope.fullDate = new Date(Date.UTC.apply(undefined, dateParts.concat(timeParts))).toISOString();
}
}
}
Here is a plunker showing the problem. http://plnkr.co/edit/tnbE3LWQTTzLhLWXLCQB?p=preview
I would prefer a solution based on my Plunker as I don't want to install other components like DateTimePicker.
Date format has been changed, so exception is being thrown, Try this
function tryCombineDateTime() {
if ($scope.dt && $scope.mytime) {
var date = $scope.dt.toString();
var time = $scope.mytime.toString();
var dateParts = date.split(' ');
var timeParts = time.split(' ');
if (dateParts && timeParts) {
dateParts[4] = timeParts[4]
$scope.fullDate = new Date(dateParts.join(' ')).toISOString();
}
}
}
your tryCombineDateTime function sould be like this:
function tryCombineDateTime() {
if ($scope.dt && $scope.mytime) {
$scope.fullDate =new Date($scope.dt.getFullYear(), $scope.dt.getMonth(), $scope.dt.getDate(),$scope.mytime.getHours(),$scope.mytime.getMinutes()).toISOString();
}
}
this a working demo forked from your plunker
I am new to javascript. I am fixing bug programmed by others. I see validation code in javascript as:
function validateTime(str) {
var pattern = new RegExp(/^(([0-9])|([0-1][0-9])|([2][0-3])):(([0-9])|([0-5][0-9]))$/);
if (pattern.test(str)) {
return true;
}
else {
return false;
}
}
But it does't validate time:- 22-05-2015
How can it be done?
You can use the Date object's parse method to verify a date string.
You can then check if the value of Date.parse(str) is equal to "Invalid Date" to see if it is malformed. No need for regex at all.
Your regex validates time, not date. To check against date in your format, use this:
var pattern = new RegExp(/^(0[1-9]|[12][0-9]|3[01])-(0[1-9]|1[012])-(19|20)\d\d$/);
You can check this pattern here:
https://regex101.com/r/kB5nV2/1
function parseDate(str) {
var m = str.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/);
return (m) ? new Date(m[3], m[2]-1, m[1]) : null;
}
The function validateTime(str) used in your code is for time validation. Try the parseDate(str) for date validation.
I've just written this regular expression in javaScript however it doesn't seem to work, here's my function:
function isGoodDate(dt){
var reGoodDate = new RegExp("/^((0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])[- /.](19|20)?[0-9]{2})*$/");
return reGoodDate.test(dt);
}
and this is how I call it in my form validation
if(!isGoodDate(userInput[1].value)){
alert("date not in correct format of MM/dd/YYYY");
return false;
}
now I want it to return MM/DD/YYYY however if I put a valid date in it raises the alert? Any ideas anyone?
Attention, before you copy+paste: The question contains some syntactic errors in its regex. This answer is correcting the syntax. It is not claiming to be the best regex for date/time parsing.
Try this:
function isGoodDate(dt){
var reGoodDate = /^((0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])[- /.](19|20)?[0-9]{2})*$/;
return reGoodDate.test(dt);
}
You either declare a regular expression with:
new RegExp("^((0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])[- /.](19|20)?[0-9]{2})*$")
Or:
/^((0?[1-9]|1[012])[- /.](0?[1-9]|[12][0-9]|3[01])[- /.](19|20)?[0-9]{2})*$/
Notice the /
Maybe because you are declaring the isGoodDate() function, and then you are calling the isCorrectDate() function?
Try:
function isGoodDate(dt){
var reGoodDate = /^(?:(0[1-9]|1[012])[\/.](0[1-9]|[12][0-9]|3[01])[\/.](19|20)[0-9]{2})$/;
return reGoodDate.test(dt);
}
Works like a charm, test it here.
Notice, this regex will validate dates from 01/01/1900 through 31/12/2099. If you want to change the year boundaries, change these numbers (19|20) on the last regex block. E.g. If you want the year ranges to be from 01/01/1800 through 31/12/2099, just change it to (18|20).
I agree with #KooiInc, but it is not enough to test for NaN
function isGoodDate(dt){
var dts = dt.split('/').reverse()
,dateTest = new Date(dts.join('/'));
return !isNaN(dateTest) &&
dateTest.getFullYear()===parseInt(dts[0],10) &&
dateTest.getMonth()===(parseInt(dts[1],10)-1) &&
dateTest.getDate()===parseInt(dts[2],10)
}
which will handle 29/2/2001 and 31/4/2011
For this script to handle US dates do
function isGoodDate(dt){
var dts = dt.split('/')
,dateTest = new Date(dt);
return !isNaN(dateTest) &&
dateTest.getFullYear()===parseInt(dts[2],10) &&
dateTest.getMonth()===(parseInt(dts[0],10)-1) &&
dateTest.getDate()===parseInt(dts[1],10)
}
Add this in your code, it working perfectly fine it here.
click here http://jsfiddle.net/Shef/5Sfq6/
function isGoodDate(dt){
var reGoodDate = /^(?:(0[1-9]|1[012])[\/.](0[1-9]|[12][0-9]|3[01])[\/.](19|20)[0-9]{2})$/;
return reGoodDate.test(dt);
}
I don't think you need a regular expression for this. Try this:
function isGoodDate(dt){
var dts = dt.split('/').reverse()
,dateTest = new Date(dts.join('/'));
return isNaN(dateTest) ? false : true;
}
//explained
var dts = dt.split('/').reverse()
// ^ split input and reverse the result
// ('01/11/2010' becomes [2010,11,01]
// this way you can make a 'universal'
// datestring out of it
,dateTest = new Date(dts.join('/'));
// ^ try converting to a date from the
// array just produced, joined by '/'
return isNaN(dateTest) ? false : true;
// ^ if the date is invalid, it returns NaN
// so, if that's the case, return false
Validate (DD-MM-YYYY) format :)
function isGoodDate(dt) {
var reGoodDate = /^(?:(0[1-9]|[12][0-9]|3[01])[\-.](0[1-9]|1[012])[\-.](19|20)[0-9]{2})$/;
return reGoodDate.test(dt);
}
Try the below code which accepts following date formats:
MM-DD-YYYY, MM-DD-YY, DD-MM-YYYY, DD-MM-YY, MM/DD/YYYY, MM/DD/YY,
DD/MM/YYYY, DD/MM/YY, MM\DD\YYYY, MM\DD\YY, DD\MM\YYYY, DD\MM\YY
function isGoodDate(dt) {
var reGoodDate = /(?:((0\d|[12]\d|3[01])|(0\d|1[012]))[\-|\\|\/]((0\d|1[012])|(0\d|[12]\d|3[01]))[\-|\\|\/](((19|20)\d{2})|\d\d))/;
return reGoodDate.test(dt);
}
(/^(0[1-9]|1[012])- /.- /.\d\d$/)
You can use this will work definitely and this is for MM/DD/YYYY