typescript 1+1 = 11 not 2 - javascript

I have a TypeScript class without any import statement at the top. When I new calculateDate() and execute addMonth(new Date(), 1), it adds 11 months to today instead of 2. The m variable is always a result of string concatenation, instead of math addition operation. I even tried parseInt() with the string form of the two operands, it still performs string concatenation. Please help. Thanks.
export class calculateDate {
addMonth(thisDate:Date, monthCount:number){
if (thisDate && monthCount && monthCount != -1) {
let m : number = thisDate.getMonth() + monthCount;
console.log('m=', m);
let newDate: Date = new Date(thisDate.setMonth(m));
return newDate;
}
else
return null;
}
}

You are adding up two strings, try to parse them as int or use this syntax +thisDate.getMonth() + (+monthCount)

Related

Convert String to Number / Date or Null if invalid

I have the following TypeScript interface:
export interface Model {
numberValue: number;
dateValue: Date;
}
I created instances of this interface defining the properties from empty strings:
let model1: Model = {
numberValue: +'',
dateValue: new Date('')
};
console.log(model1);
model1 output: { dateValue: Invalid Date; numberValue: 0 }
And from strings containing invalid values:
let model2: Model = {
numberValue: +'A',
dateValue: new Date('A')
};
console.log(model2);
model1 output: { dateValue: Invalid Date; numberValue: NaN }
I need to get for both empty strings and strings with invalid values the following:
model output: { dateValue: NaN; numberValue: NaN }
or
model output: { dateValue: null; numberValue: null }
I am sending model as Json to an API. When the values are empty or converted from invalid values I need to send null.
EDIT: There are libraries like moment.js that can help you a lot when it comes to the fairly tricky topic of Dates. But you can do a basic conversion yourself like this...
parseUTCDate(year: string = "1970", month: string = "01", day: string = "01") {
let tempYear = year;
let tempDay = "";
let tempMonth = "";
// In case a Month shorter than 10 is added, we prepend a 0 to minimize errors
if (month.length < 2) {
tempMonth = "0" + month
} else {
tempMonth = month
}
// What we did to the month, we do for the day as well...
if (day.length < 2) {
tempDay = "0" + day
} else {
tempDay = day
}
// We construct our to-be-parsed date...
let dateToBeParsedS: string = `${tempYear}-${tempMonth}-${tempDay}Z`;
let date: Date = new Date(dateToBeParsedS);
// We check if the Date is even valid. A proper Date value is always equal to itself
if(date.getTime() === date.getTime()) {
// if successful, we return the date
return date;
} else {
// if not... well, we return an undefined or NaN if we like
return undefined;
}
}
However, this method doesn't include all cases that can come up with a date. It's meant as an example of what you can do.
String to numbers is easier... but let's go the extra mile as well.
returnNumberOutOfString(inputNumber: string) {
// The Numberclass can parse numbers... that's what we will use
let tempNumber = new Number(inputNumber)
// Of course, we want to know if the number was valid...
if (isNaN(tempNumber.valueOf())) {
return undefined;
} else {
// If successful, we return the primitive data value of the Number object
return tempNumber.valueOf();
}
}
And with that, you've got basically all you need to convert and validate...
I'm a bit confused in terms of what you're trying to achieve. Also, to remain faithful to semantics, you're NOT creating a new instance of the interface. You've created an object of the TYPE model. It's not the same. But let's keep this going...
You said, IF the value is empty for whatever reason, it should return a null...
"numberValue": numberValue != undefined ? someNum : null
What does this line do? In case the value referenced in the object is not undefined, it should return the number. However, if the case isn't fulfilled, it will return a null.
In case you wish to know, if your date is a valid date, you can handle it in a similar fashion...
"dateValue": dateValue.getTime() === dateValue.getTime() ? dateValue : null
The idea here is, that a proper date will always be equal to itself, otherwise it will NaN

convert number to string returns empty if number 0

Trying to convert string to a number, works fine apart from when the number is zero it returns an empty string;
I understand 0 is false, but I just need a neat way of it returning the string "0"
I'm using:
const num = this.str ? this.str.toString() : '' ;
I even thought of using es6 and simply ${this.str} but that didn't work
Because 0 is "false-y" in JavaScript, as you've already figured out, you can't utilized it in a conditional. Instead, ask yourself what the conditional is really trying to solve.
Are you worried about null / undefined values? Perhaps this is better:
const num = (typeof this.str !== "undefined" && this.str !== null) ? this.str.toString() : "";
Odds are you really only care if this.str is a Number, and in all other cases want to ignore it. What if this.str is a Date, or an Array? Both Date and Array have a .toString() method, which means you may have some weird bugs crop up if one slips into your function unexpectedly.
So a better solution may be:
const num = (typeof this.str === "number") ? this.str.toString() : "";
You can also put your code in a try catch block
const num = ''
try {
num = this.str.toString();
} catch(e) {
// Do something here if you want.
}
Just adding to given answers - if you do:
x >> 0
you will convert anything to a Number
'7' >> 0 // 7
'' >> 0 // 0
true >> 0 // 1
[7] >> 0 // 7
It's a right shift bit operation. You can do magic with this in many real life cases, like described in this article.
In my case, the zero (number) that I wanted to converted to a string (which was the value of an option in a select element) was a value in an enum.
So I did this, since the enum was generated by another process and I could not change it:
let stringValue = '';
if (this.input.enumValue === 0) {
stringValue = '0';
} else {
stringValue = this.input.enumValue.toString();
}

How can I check if a date is greater than the other?

I have 2 dates. Both are in yyyy-mm-dd format. I applied a simple check that if
if ('2017-01-15' > '2016-12-15') {
return true;
} else {
return false;
}
But it is giving me a syntax error. What should I do?
Given the format of the date string and your code structure, what you have should be working. If you're getting an error, check that it's coming from the section of code you've shown in your question.
That being said, you can improve the code by changing the strings to Date objects before comparing them. You can also shorten the code by just returning the result of the comparison. Try this:
function dateComparison() {
return new Date('2017-01-15') > new Date('2016-12-15');
}
console.log(dateComparison());
As per the MDN
The return statement ends function execution and specifies a value to be returned to the function caller.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return
So you must be getting this error if you are not using the if condition within a function.
Operators like ==, !=, ===, and !== require you to use date.getTime() like this:
var x = new Date('2017-01-15');
var y = new Date('2016-12-15');
var same = x.getTime() === y.getTime();
var notSame = x.getTime() !== y.getTime();
You could convert them to Date objects and then compare.
var dateStrA = "2017-01-15 00:00:00";
var dateStrB = "2016-12-15 00:00:00";
if (new Date(dateStrA) > new Date(dateStrB))
{
...
}
else
{
...
}
Comparing using equals, such as === will not work on Date objects. You can also use Date.compare()
You can use the moment.js library to help you achieve it:
return moment('2017-01-15').format('YYYY-MM-DD') > moment('2016-12-15').format('YYYY-MM-DD');
Try this...worked for me.
var startDate = "2019-03-23";
var endDate = "2019-03-24";
if(Date.parse(endDate) >= Date.parse(startDate)) {
console.log('endDate is greater');
} else {
console.log('startDate is greater');
}
You can try this
if(d1.getTime()>d2.getTime())

How to increment a numeric string by +1 with Javascript/jQuery

I have the following variable:
pageID = 7
I'd like to increment this number on a link:
$('#arrowRight').attr('href', 'page.html?='+pageID);
So this outputs 7, I'd like to append the link to say 8. But if I add +1:
$('#arrowRight').attr('href', 'page.html?='+pageID+1);
I get the following output: 1.html?=71 instead of 8.
How can I increment this number to be pageID+1?
Try this:
parseInt(pageID, 10) + 1
Accordint to your code:
$('#arrowRight').attr('href', 'page.html?='+ (parseInt(pageID, 10) + 1));
+ happens to be valid operator for both strings and numbers that gives different results when both arguments are numeric and when at least one is not. One of possible workarounds is to use operator that only have numeric context but gives same mathematical result, like -. some_var - -1 will always be same as adding 1 to some_var's numeric value, no matter if it is string or not.
$('#arrowRight').attr('href', 'page.html?='+ (pageID - -1));
All these solutions assume that your number you want to add 1 to is within the machine precision for an integer. So if you have a large enough number within that string when you add 1 to it won't change the number.
For Example:
parseInt('800000000000000000', 10) + 1 = 800000000000000000
So I wrote a quick solution to the problem
function addOne(s) {
let newNumber = '';
let continueAdding = true;
for (let i = s.length - 1; i>= 0; i--) {
if (continueAdding) {
let num = parseInt(s[i], 10) + 1;
if (num < 10) {
newNumber += num;
continueAdding = false;
} else {
newNumber += '0';
}
} else {
newNumber +=s[i];
}
}
return newNumber.split("").reverse().join("");
}
Now, using the same example above
addOne('800000000000000000') + 1 = '800000000000000001'
Note that it must stay as a string or you will lose that 1 at the end.
It needs to be a integer, not a string. Try this:
pageID = parseInt(pageID)+1;
Then you can do
$('#arrowRight').attr('href', 'page.html?='+pageID);
Simply, $('#arrowRight').attr('href', 'page.html?='+(pageID+1));
The parentheses makes the calculation done first before string concatenation.
let pageId = '7'
pageId++
console.log(pageId)
Nowadays, you just need to pageID++.
Just change your order of operations by wrapping your addition in parentheses; if pageID is already a number, parseInt() isn't necessary:
$('#arrowRight').attr('href', 'page.html?='+(pageID+1));
Demo
As long as your pageID is numeric, this should be sufficient:
$('#arrowRight').attr('href', 'page.html?='+(pageID+1));
The problem you were seeing is that JavaScript normally executes in left-to-right order, so the string on the left causes the + to be seen as a concatenator, so it adds the 7 to the string, and then adds 1 to the string including 7.

Javascript array not working ?? confused

Anybody got any clue why this won't work with more than 1 date...
it only takes the first date in the array...
var unavailableDates = ["10-6-2011","13-6-2011"];
function unavailable(date) {
dmy = date.getDate() + "-" + (date.getMonth() + 1) + "-" + date.getFullYear();
if ($.inArray(dmy, unavailableDates) == 0) {
return [false, "", "Unavailable"];
} else {
var day = date.getDay();
return [(day != 0 && day != 2 && day != 3 && day != 4 && day != 6)];
}
}
see full example below
http://offline.raileisure.com/lee.php
Thanks in advance
Lee
It doesn't work because you're interpreting the return value of "$.inArray()" incorrectly. The function returns -1 when the search target cannot be found, and the index in the array when it can. Thus, when it returns 0, that means it did find what the code was looking for.
A cute trick — for those who like cute tricks — for checking the return value from functions like "$.inArray()" is to apply the "~" operator:
if (~$.inArray(needle, haystack)) {
// found it
}
else {
// did not find it
}
The "~" operator forms the bitwise complement (or "1's complement") of its argument. Because "~-1" is 0, and "~n" is non-zero for any other integer, it effectively converts the return value to a "truthy/falsy" value appropriately. Don't use it if you don't like cute tricks :-)
Also, that "dmy" variable used in a couple functions should be declared in each one with the var keyword.
jQuery.inArray returns the index of the item found, ie, when it matches the second value, it is returning 1, not the 0 you test for.
You should change your test to be >= 0 rather than == 0 when you do
if ($.inArray(dmy, unavailableDates) == 0) { ...
Is it reading it in as mm-dd-yyyy?
If so - then 13-6-2011 would not be a valid date.
Edit Okay - looking at your page; clearly not since 10th June is not available as expected.
I deleted the answer but where dates are concerned I think this is a valuable thing to remember (e.g. on a US client presumably I'd be right?) so I undeleted it.
I'll get rid of it again though if the community feels I should.
Try this:
in pure javascript:
I made ​​some modifications to make your code faster
function inArrayOrStr (o, v) {
return ~o.indexOf(v);
}
unavailableDates = ["10-6-2011","13-6-2011"];
function unavailable(date) {
var dmy = [date.getDate() ,(date.getMonth() + 1) , date.getFullYear()].join("-");
if (inArrayOrStr(unavailableDates, dmy) {
return [false, "", "Unavailable"];
} else {
var day = date.getDay();
return [day > 7];
}
}

Categories

Resources