Why is my custom validation in Angular2 not working - javascript

Here are two angular2 custom validations that I wrote, the first one validateAge works, but the second one validateDob does not ... the difference is the validateAge uses the component that I am on and is a text based field, the second one needs to use a Date Entry field and find the difference between today's date and the birthdate to find the actual age and then measure it against the age field. but something is not right ... any ideas
function validateAge(control: FormControl): { [s: string]: boolean } {
if (parseInt(control.value) <= 0) {
return {invalidAge: true};
}
}
function validateDob(control: FormControl): {[s:string]: boolean}{
var today = new Date();
var calcAge = today - control.value;
if (calcAge != parseInt([{age}]) ){
return {invalidDate: true}
}
}

The issue you have here is that your control.value is not a Date object, but rather the string representation.
var today = new Date();
Difference in milliseconds between the current timestamp and the entered value
var diff = today - new Date(control.value);
divide by ms per year and take the floor
var calcAge = Math.floor(diff/ (1000*60*60*24*365)));
Now do whatever comparison you need against the appropriate value. You didn't show us what your age object is so I don't actually know what comparison you're looking for.
if (calcAge < someAgeThreshold) ){
return {invalidDate: true}
} else {
return null;
}
Also note that with custom validation the validator returns no error when you return null and anything with a value is considered to have an error.

Related

Combine array of dates sorted in ascending order into array of date ranges

I have one array of dates, I want to create object containing start and end by checking continue dates.
EX.
dateArray = [
"2020-01-22T00:00:00.000Z",
"2020-01-23T00:00:00.000Z",
"2020-01-28T00:00:00.000Z",
"2020-01-29T00:00:00.000Z",
"2020-01-30T00:00:00.000Z",
"2020-01-31T00:00:00.000Z",
"2020-02-01T00:00:00.000Z",
"2020-02-02T00:00:00.000Z",
"2020-02-03T00:00:00.000Z",
"2020-02-04T00:00:00.000Z",
"2020-02-05T00:00:00.000Z",
"2020-02-06T00:00:00.000Z",
"2020-02-07T00:00:00.000Z",
"2020-02-16T00:00:00.000Z",
"2020-02-17T00:00:00.000Z",
"2020-02-18T00:00:00.000Z",
"2020-02-19T00:00:00.000Z",
"2020-02-20T00:00:00.000Z"
]
myRequirement = [{
start: "2020-01-22T00:00:00.000Z",
end: "2020-01-23T00:00:00.000Z"
},
{
start: "2020-01-28T00:00:00.000Z",
end: "2020-02-07T00:00:00.000Z"
},
{
start: "2020-02-16T00:00:00.000Z",
end: "2020-02-20T00:00:00.000Z"
}
]
I want to do this using in node.js.
I tried this using some nested for loops.
First i am running loop on main dateArray, Then checking is it first date or not, If it is first date then storing it as first objects start date, Then in next date case checking is it next most date of previous date or not.
let gapArray = [];
let startEndObj = {};
let tempStartDate;
let tempEndDate;
let tempNextDate;
await asyncForEach(finalAvailablityDatesArrayOFi.availeblityDatesArray, async (availeblityDatesArrayOFi) => {
console.log("availeblityDatesArrayOFi", availeblityDatesArrayOFi);
if (!tempStartDate) {
console.log("In if");
startEndObj.startDate = availeblityDatesArrayOFi;
tempStartDate = availeblityDatesArrayOFi;
let oneDatePlus = new Date(availeblityDatesArrayOFi).setDate(new Date(availeblityDatesArrayOFi).getDate() + 1);
tempNextDate = new Date(oneDatePlus);
console.log("startEndObj", startEndObj);
}
else if (tempStartDate) {
console.log("in else");
if (new Date(availeblityDatesArrayOFi).getTime() == new Date(tempNextDate).getTime()) {
console.log("Do nothing!");
tempStartDate = availeblityDatesArrayOFi;
tempEndDate = availeblityDatesArrayOFi;
let oneDatePlus = new Date(availeblityDatesArrayOFi).setDate(new Date(availeblityDatesArrayOFi).getDate() + 1);
tempNextDate = new Date(oneDatePlus);
}
else {
startEndObj.endDate = new Date(tempEndDate);
gapArray.push(startEndObj);
tempStartDate = '';
tempEndDate = '';
startEndObj = {};
}
}
});
Thank you!
Looks like a job for Array.prototype.reduce().
Note: hereafter assumption is made that few prerequisites are met:
source array items are valid ISO-formatted date strings or others, parseable by new Date() constructor, otherwise should be brought to one of supported format
source array items are sorted in ascending order, otherwise Array.prototype.sort() method must be applied in advance
array items do not include time of the day part (or this part is exactly the same for all items), otherwise consecutive date records may happen to have difference greater than 864e5 milliseconds (1 day) and more complex comparison is required
You may walk through your array and compare current items with previous/following, once you have a gap greater than 1 day you push new range into resulting array or modify end date for the last one:
const src = ["2020-01-22T00:00:00.000Z","2020-01-23T00:00:00.000Z","2020-01-28T00:00:00.000Z","2020-01-29T00:00:00.000Z","2020-01-30T00:00:00.000Z","2020-01-31T00:00:00.000Z","2020-02-01T00:00:00.000Z","2020-02-02T00:00:00.000Z","2020-02-03T00:00:00.000Z","2020-02-04T00:00:00.000Z","2020-02-05T00:00:00.000Z","2020-02-06T00:00:00.000Z","2020-02-07T00:00:00.000Z","2020-02-16T00:00:00.000Z","2020-02-17T00:00:00.000Z","2020-02-18T00:00:00.000Z","2020-02-19T00:00:00.000Z","2020-02-20T00:00:00.000Z"],
ranges = src.reduce((res,date,idx,self) => {
const rangeStart = !idx || new Date(date) - new Date(self[idx-1]) > 864e5,
rangeEnd = idx == self.length-1 || new Date(self[idx+1]) - new Date(date) > 864e5
if(rangeStart) res.push({startdate:date,enddate:date})
else if(rangeEnd) res[res.length-1]['enddate'] = date
return res
}, [])
console.log(ranges)
.as-console-wrapper {min-height:100%}
You need to be careful with this type of processing to determine all the business rules exactly. If the time component is not to be considered, then it should be removed, otherwise when comparing say 2020-01-01T00:00:00 to 2020-01-02T012:00:00 you will get a difference greater than 1 day but might not want it to be treated as the start of a new range.
For that reason, the "days difference" logic should be in a separate function, which also makes it easier to change date libraries if you're using one. The days difference is also signed, so make sure they are passed in the right order.
Otherwise, the following is pretty much the same as Yevgen's answer but a little more efficient I think as it only creates two Dates on each iteration instead of four.
let dateArray = [
"2020-01-22T00:00:00.000Z",
"2020-01-23T00:00:00.000Z",
"2020-01-28T00:00:00.000Z",
"2020-01-29T00:00:00.000Z",
"2020-01-30T00:00:00.000Z",
"2020-01-31T00:00:00.000Z",
"2020-02-01T00:00:00.000Z",
"2020-02-02T00:00:00.000Z",
"2020-02-03T00:00:00.000Z",
"2020-02-04T00:00:00.000Z",
"2020-02-05T00:00:00.000Z",
"2020-02-06T00:00:00.000Z",
"2020-02-07T00:00:00.000Z",
"2020-02-16T00:00:00.000Z",
"2020-02-17T00:00:00.000Z",
"2020-02-18T00:00:00.000Z",
"2020-02-19T00:00:00.000Z",
"2020-02-20T00:00:00.000Z"
];
// Simple difference in days function
function daysDiff(d0, d1) {
return Math.round((d1 - d0) / 8.64e7);
}
let ranges = dateArray.reduce((acc, curr, i, arr) => {
// If first date, initialise first object
if (!acc.length) {
acc.push({start: curr, end: curr});
} else {
let d0 = new Date(curr);
let d1 = new Date(arr[i-1]);
// If difference greater than 1 day, end previous range
// and start a new range
if (daysDiff(d1, d0) > 1) {
acc[acc.length - 1].end = arr[i-1];
acc.push({start: curr, end: curr});
}
}
return acc;
}, []);
console.log(ranges);

.diff is not a function in Moment.js

I'm trying to get the difference between two dates, but I'm getting the response: Uncaught TypeError: x.diff is not a function
On other topics I've seen I have to create a moment object, but for as far as I know, I'm doing that.
Code:
function datecheck(){
var y = moment($("#input_pickup_date").val(),"L").format("L");
var x = moment().format("L");
console.log(x.diff(y, 'days'));
}
Via the docs, moment().format() returns a String, so your x and y variables are both Strings. If you need to both do calculations on and display the values, separate them out into different variables:
function datecheck() {
var dateSubmitted = moment($("#input_pickup_date").val(), "L"), //your old x variable
now = moment(), //your old y variable
dateSubmittedDisplay = dateSubmitted.format("L"), //a string representing the submitted date in the format you wanted.
nowDisplay = now.format("L"); //a string representing now in the format you wanted.
console.log(x.diff(y, 'days'));
}

Format a date from a timestamp without BST in JavaScript

Consider the following timestamp I get back from the server:
2016-09-15T18:15:00.0000000
If I do the following:
function friendlyTime(timeslot) {
const time = timeslot,
timeDate = new Date(time),
timeHours = `0${timeDate.getHours().toString()}`.slice(-2),
timeMinutes = `0${timeDate.getMinutes().toString()}`.slice(-2);
return `${timeHours}:${timeMinutes}`;
}
const slot = friendlyTime('2016-09-15T18:15:00.0000000');
I get back:
19:15, when what I really want is a reflection of the timestamp without BST, like 18:15.
Is there an easy way to do this at all? My head explodes when it comes to dates and timezones in JavaScript.
It needs to look the same regardless of where anyone is in the world. It shouldn't be reflecting anyone's personal time settings.
Just manipulate the string, one possibility that would support 4 to 6 digit common spec years (or more).
function friendlyTime(timeslot) {
return timeslot.split('T').pop().split(':', 2).join(':');
}
console.log(friendlyTime('2016-09-15T18:15:00.0000000'));
Another, if you only need to support 4 digit years. (Javascript is spec'd for 4)
function friendlyTime(timeslot) {
return timeslot.slice(11, 16);
}
console.log(friendlyTime('2016-09-15T18:15:00.0000000'));
Instead of getHours() and getMinutes() use getUTCHours() and getUTCMinutes(). Also, as Mike McCaughan pointed out in comments, you have to add Z to the end of the string to make sure it will be parsed correctly in all browsers.
function friendlyTime(timeslot) {
const time = timeslot,
timeDate = new Date(time),
timeHours = `0${timeDate.getUTCHours().toString()}`.slice(-2),
timeMinutes = `0${timeDate.getUTCMinutes().toString()}`.slice(-2);
return `${timeHours}:${timeMinutes}`;
}
const slot = friendlyTime('2016-09-15T18:15:00.0000000Z');
console.log(slot);

Trying to add to dateTime in sheets

function getFirstEmptyRow() {
var spr = SpreadsheetApp.getActiveSpreadsheet();
var column = spr.getRange('A:A');
var values = column.getValues(); // get all data in one call
var ct = 0;
while ( values[ct][0] != "" ) {
ct++;
}
return (ct);
}
function getLatestTime() {
return SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].getRange(getFirstEmptyRow(),1).getValue();
}
function getLatestPoints() {
return SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].getRange(getFirstEmptyRow(),2).getValue();
}
function getLatestAverage() {
return SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].getRange(getFirstEmptyRow(),3).getValue();
}
function daysLeft(){
var pointsLeft = 24250 - getLatestPoints();
return (pointsLeft / getLatestAverage()) / 24;
}
function nextRedeem() { //Problem is with this function:
var redeemTime = getLatestTime() + daysLeft() + (2/24);
return redeemTime;
}
In my sheet I have a list of rows with 1)a date/time 2)a point value and 3)A running average of points per hour. I am trying to write a function that figures out how much time is left before the points reach a certain number and add it to the latest time to figure out at what time I expect to have that number of points.
I have little experience with java script and weak typing. My problem is that when I try to add a number to my returned date value I either get a string or just NaN. My other problem is that sheets seems to interpret dates into a number differently than Number() does.
If my nextRedeem() function simply returns getLatestTime(), I can get sheets to show it either as a date or the number of days since 1/1/1900 or whatever it is. At that point, in a cell I can add to it. I can add getLatestTime() and daysLeft() in a cell and it works fine. I can also add the timezone offset and it works, in a cell. But when I do it in this function nothing seems to work. I have tried adding .value to the function calls and using parseFloat() but that gives me NaN.
How do I do arithmetic with these function returns?
The issue is that isn't how Dates are handled in javascript.
var redeemTime = getLatestTime().setDate( getLatestTime().getDate() + daysLeft() + 12 );
This will set the Day of the Month of your DateTime object to whatever the original date was + daysLeft(). I'm not sure what you're referring to with 2/24 (as that's always 12) but I included it in case you have some other context. If you add days over the number of days in the month, it will go into the next month, and similarly if you add negative days below 0, it will go into the previous month.
For more information on handling dates with JavaScript, see this link at W3Schools.
So Date.parse gets me half way there, but it give me milliseconds since 1/1/1970, where google is days since 12/30/1899. So I just had to use some math which I left uncomputed for clarity.
function dateToNum(date) {
return (Date.parse(date)/1000/60/60/24 + 25569)
}
Now I can use dateToNum(getLatestTime()) and do whatever math I want to it. When this number is put into a cell that is formatted to datetime it will display correctly.

comparing current date and date inp [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Improve this question
i wanted to know whats the error in this code. i wanted to compare today's date with the user input date
<script type="text/javascript">
function validate()
{
if( document.myForm.name.value == "" )
{
alert( "Please provide your date of birth!" );
document.myForm.dob.focus() ;
return false;
}
var q = new Date();
var m = q.getMonth();
var d = q.getDate();
var Y = q.getFullYear();
var date = new Date(Y,m,d);
var r = document.getElementById(dates).value;
var m1 = r.getMonth();
var d1 = r.getDate();
var Y1 = r.getFullYear();
var mydate = new Date(Y1,m1,d1) ;
if(date<=mydate)
{
alert("greater");
return false;
}
else
{
alert("smaller");
return false;
}
return true;
}
</script>
<form name="myForm" method="post" onsubmit= "return(validate());">
Name: <input type="text" name="name"><br>
Date: <input type="date" id="dates" name="dates">
<br/>
<INPUT TYPE="submit" VALUE="Submit" >
</form>
i felt like "var r = document.getElementbyid(dates).value;" this piece of code is not working
The function name should be:
document.getElementById
(you are missing some capital letters)
Also, you are treating the result of document.getElementById(dates).value as though it will give you a Date object back, but it will actually give you are string - you need to convert this into a Date before you can call getMonth/getData/getFullYear on it - the answers to this question should help you here.
I have put comments below where the main errors in the code are.
function validate()
{
if( document.myForm.name.value == "" ) // Not an error per se, but you should use === to compare strings this way
{
alert( "Please provide your date of birth!" );
document.myForm.dob.focus() ;
return false;
}
var q = new Date();
var m = q.getMonth();
var d = q.getDate();
var y = q.getFullYear();
var date = new Date(Y,m,d); // The variable Y is not defined. You probably meant lowercase y.
var r = document.getElementbyid(dates).value; // Wrong case. Should be: document.getElementById
var m1 = r.getMonth();
var d1 = r.getDate();
var y1 = r.getFullYear();
var mydate = new Date(Y,m,d) ; // Same thing, probably meant lowercase y again.
if(date<=mydate)
{
alert("greater");
return false;
}
else
{
alert("smaller") // This statement is missing a semicolon
return false;
}
return true;
}
Also, it's not entirely clear what you are trying to do. At the end, assuming you fix those syntactical errors, you have three Date variables:
q, which is created with the current date and time.
date, which is just passed the same current date and time that was in q.
mydate, which... also holds the current date and time, since you just passed it the same values from q that you passed to date.
So since the two date objects you are comparing are set to the same date, you will always alert "greater" (which is not really greater, because they are equal, but that is a separate issue).
I also find it strange that this validation function returns false in all cases. Because of your if/else statement, there is no way to ever return true. For a function that is supposed to validate something, it seems odd to have the validation always return false.
Additionally, as #codebox stated in his answer, document.getElementById(dates).value is just returning a string, which you must then convert into a new Date object if you wish to read the date values from it into your m1, d1, and y1 variables (which, as of right now, are never even used).
You are having couple of typo and logic mistake. This code should work.
function validate()
{
if( document.myForm.name.value == "" )
{
alert( "Please provide your date of birth!" );
document.myForm.dob.focus() ;
return false;
}
var q = new Date();
var m = q.getMonth();
var d = q.getDate();
var y = q.getFullYear();
var date = new Date(y,m,d);
var r = Date.parse(document.getElementById("dates").value);
if(date<=r)
{
alert("greater");
return false;
}
else
{
alert("smaller");
return false;
}
return true;
}

Categories