Why is this if statement not affected by my input? - javascript

I want to build an algorithm who convert AM/PM to the 24hours format. It's not finished, but the code I have so far is behaving strangely.
When I give the input "25:05:45PM", it should enter the first branch of the first if statement, but should not enter the second if statement. I've checked the condition, and it's definitely false. My brain is melting.
Here is the code :
function conversionTime(s) {
if (s.includes('PM')) {
let temp = s.slice(0, 8).split(':');
if (temp[0] >= 01 && temp[0] <= 12); {
temp[0] = Number(temp[0]) + 12;
return temp.join(':')
}
} else if (s.includes('AM')) {
let temp2 = s.slice(0, 8).split(':');
return temp2
}
}
console.log(conversionTime("25:05:45PM"))

Gotcha.
if (temp[0] >= 01 && temp[0] <= 12);
This semicolon is the culprit! It's saying "the if statement is over, no need to do anything", so your code is being interpreted like:
if (temp[0] >= 01 && temp[0] <= 12);
{
temp[0] = Number(temp[0]) + 12;
return temp.join(':');
}
The code in the block will always run. This feature exists so you can make full use of let's scoping:
let x = "outside";
console.log(x);
{
let x = "inside";
console.log(x);
}
console.log(x);
Well, really it exists because that's how C works – it predates the let statement – but that's what it's useful for these days.

I Will do that this way..
function conversionTime(timeAPM)
{
let [h,m,s,apm] = timeAPM.match(/(\d+)|(\w+)/g);
if (timeAPM !== `${h}:${m}:${s}${apm}`
|| isNaN(h) || isNaN(m) || isNaN(s)
|| (apm !== 'AM' && apm !== 'PM')
) return undefined;
if (apm === 'PM' && h <= 12 ) h = +h +12;
return `${h}:${m}:${s}`;
}
console.log(conversionTime("25:05:45PM"))
I don't know if it's intentional or not on his part, but the PO's code also returns undefined. Apart from his attachment to the AM/PM labels, the OP gives no explanation on the validity of the entry.
So this second version is content to check that there are indeed 3 numerical values, separate by :, and directly followed by AM or PM.
the number of digits of these numbers is unknown : His test uses an hour = 25 while it is an AM/PM presentation. So why not seconds or minutes expressed with 40 digits...
I'm not claiming my regex is the best in the universe.
I could also have added in my code:
console.log(conversionTime("10:31:25BAM")) // -> undefined
console.log(conversionTime("1:3:5abc")) // -> undefined
console.log(conversionTime("1:3zzzz")) // -> undefined
console.log(conversionTime("a:10:15PM")) // -> undefined
console.log(conversionTime("285::4875PM")) // -> undefined
// or more absurd:
console.log(conversionTime("285:1505:4875PM")) // -> 285:1505:4875

Related

Parameter comparing won't work

Everything works just fine - everything except this one if-else-statement:
else if ((day = 0 || day = 6) && (hour <= 19)) {
greeting = "We wish you a nice weekend and a nice " +
Weekdays[day] + ".";
}
Firefox's Error Message: 'ReferenceError: invalid assignment left-hand side'
..it should be really easy but till now I coudn't find the problem.
Thanks for helping and have a nice day!
Use == for comparison(by value) and = for assigning values.
So in your case, it should be:
...
else if ((day == 0 || day == 6) && (hour <= 19)) {
greeting = "We wish you a nice weekend and a nice " +
Weekdays[day] + ".";
}
...
If you need to compare by both type and value, you should use ===
In short:
var a = 10; // assigns value 10 to variable `a`
"1"==1 // true => Since == compares by value
"1"===1 // false => Since === compares by both type and value. In this case although value is 1, both are of different types (string and integer)

Extended Ternary expression

I know you can do ternary expressions in Javascript for an if - else statement, but how about an else- else if- else statement? I thought that surely this would be supported but I haven't been able to find any info about it and wasn't able to get it to work just hacking around.
In contrast to Robby Cornelissen's answer - there is no problems with readability if you format it properly (and not writing PHP, since it messed up the operator by making it left-associative in contrast to all other languages that have that construct):
var y =
x == 0 ? "zero" :
x == 1 ? "one" :
"other";
EDIT
What I was looking for is a shorter version of "if expression 1 is true, return expression 1. Else if expression 2 is true, return expression 2. Else return expression 3". Is there no clean way to do this?
There is: expression1 || expression2 || expression3. (It would have been nice if you had put this into your question in the first place.) This is commonly used for default values:
var defaults = null;
function hello(name) {
var displayName = name || (defaults && defaults.name) || "Anonymous";
console.log("Hello, " + displayName + ".");
}
hello("George");
// => Hello, George.
hello();
// => Hello, Anonymous.
defaults = {};
hello();
// => Hello, Anonymous.
defaults.name = "You"
hello();
// => Hello, You.
However, it is important to be aware of the conditions for truthiness. For example, if you expect "" or 0 to be a valid value that does not need to be replaced by a default, the code will fail; this trick only works when the set of possible non-default values is exactly the set of truthy values, no more and no less. E.g.
function increment(val, by) {
return val + (by || 1); // BUG
}
increment(10, 4);
// => 14
increment(10, 1);
// => 11
increment(10);
// => 11
increment(10, 0);
// => 11 <-- should be 10
In this case you need to be explicit:
function increment(val, by) {
return val + (typeof(by) === "undefined" ? 1 : by);
}
I wouldn't recommend it because of readability, but you could just nest ternary operators:
var y = (x == 0 ? "zero" : (x == 1 ? "one" : "other"));
This would be the equivalent of:
var y;
if (x == 0) {
y = "zero";
} else if (x == 1) {
y = "one";
} else {
y = "other";
}
You can extend a ternary condition if you're good. It gets to be messy though.
var number = 5;
var power = 2;
var ans = Math.pow(number,power);
var suggest = ( ans == 5 ? 5 : ans == 10 ? 10 : ans == 15 ? 15 : ans == 25 ? "works" : null);
console.log(suggest);
I may have added to many because I'm on my phone haha but try it in your developer panel.

Javascript switch

I am working on a zodiac calendar that requires a switch 0-11 for the signs. I have written HTML code that drops down for the month and a text input for the year. The sign should use id 'output' and should also show up in text. I am not sure if I am using my switch correctly, of if my math is causing the problem or why it is not sending to output.
HTML CODE:
<div><label for="sign">Sign</label><input type="text"
name ="sign" id="sign"></div>
Javascript Code
if (year && year.value && (year.length == 4)){
year = parseInt(years.value);
month = parseInt(month.value);
if (month < 2) {
year = (year - 1);
}
year = ((year - 1924) % 12);
} else { // Show Error:
document.getElementById('year').value =
'Please enter valid values.';
}
switch (year){
case 0 :
block code;
break;
etc..
} // End Switch
if (output.textContent != undefined) {
output.textContent = sign;
} else {
output.innerText = sign;
}
return false;
}
Your regular expression could be failing to match your lowercased url. When that happens, the result would be null.
You should be checking the match() result before using it. Something like this:
var matches = url.toLowerCase().match(/https?:\/\/(.+?)[?#\/$]/);
if (!matches || matches.length < 2) {
// Handle error
...
} else {
// Keep going
var domain = matches[1];
...
}
Also, verify that your regular expression is actually doing what you intend.
Because of my javascript code innerText
if (output.textContent != undefined) {
output.textContent = sign;
} else {
output.innerText = sign;
}
I had to delete
<div><label for="sign">Sign</label><input type="text"
name ="sign" id="sign"></div>
and replace it with
<p>Sign: <span id="output"></span></p>
I could have easily changed the javascript code and document.getElementID('output') = sign.value;
The problem should be caused by domain checking instead of calculate function.
Remove domain checking and try again (see if it works).
Errors:
1) if (year && year.value && (year.value.length == 4)){
year = parseInt(year.value);
2) main html didn't declare element "output"

Javascript - Get a date from any kind of string

I would like to know if there is a way (I hope there is one, or I am in trouble :p), to find a date in any kind of string.
Here are some examples to make you understand what I am looking for :
var string1 = 'blabla-test-20140215.dat'
I would need to have access to '20140215'
var string2 = 'blabla_Test.20141212'
I would need to have access to '20141212'
Well, I would like to be able to find a date in a format yyyymmdd in a string, no matter the string.
Thank you if you have any clue, I haven't found anything on internet yet.
EDIT :
There can be other numbers in the string, but always less than 8.
for instance :
var string3 = 'blabla-2526-20141212'
The date I am looking for is always separated from other numbers. I can't have :
var string4 = 'blabla-252620141212'
I just want to find the numbers representing the date (in a format yyyymmdd, for instance in string3 I want 20141212, which refers to : 12/12/2014)
I'm note sure, but if your string contains digits only for date, you can use RexEx ?
may be like this :
var regex = /[0-9]+/;
var string1 ="blabla-test-20140215.dat";
var found = regex.exec(string1);
alert('Found: ' + found);
It is simple enough to extract a sequence of eight numbers from a string with regex, just use something like the following:
var dateString = (/\d{8}/.exec(string) || [])[0];
This will find the first eight-character-long string of numbers in a given string. If no such sequence exists, it will be undefined. You can then use it to create a Date object if necessary.
You should use Regex for this.
re = /(\d{4})(\d{2})(\d{2})/g //create a regex that matches: 4 digits followed by 2 digits followed by 2 digits
///// yyyy mm dd
result = re.exec(string1) //execute the regex
// now, access the different capture groups according to their indexes
console.log(result[1]) // yyyy
console.log(result[2]) // mm
console.log(result[3]) // dd
This solution will check for valid dates (not just any 8 arbitrary numbers):
function hasDate(input) {
var matches = input.match(/(\d{4})(\d{2})(\d{2})/),
indexOf = function (elem, arr) {
var len = arr.length, i;
for (i = 0; i < len; i++) {
if (arr[i] === elem) {
return i;
}
}
return -1;
},
months31 = [1, 3, 5, 7, 8, 10, 12],
idx, isLeapYear,
year, month, day;
if (matches) {
year = parseInt(matches[1]);
month = parseInt(matches[2]);
day = parseInt(matches[3]);
//Check invalid dates from the start
if (month < 1 || month > 12) {
return false;
}
else if (day < 1 || day > 31) {
return false;
}
idx = indexOf(month, months31);
isLeapYear = ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
//Month has 31 days, we are good
if (idx >= 0) {
return true;
}
//Feb - check for leap year
else if (month === 2 && (day <= 28 || (isLeapYear && day <= 29))) {
return true;
}
//All other months
else if (month !== 2 && day <= 30) {
return true;
}
}
//If we got this far, its a bad date
return false;
}
//return true
hasDate('blabla_Test.20141212');
//return false
hasDate('blabla_Test.20140229');
//return true
hasDate('blah_20140228');
//return true
hasDate('blah_20000229');

Is there a more compact way of checking if a number is within a range?

I want to be able to test whether a value is within a number range. This is my current code:
if ((year < 2099) && (year > 1990)){
return 'good stuff';
}
Is there a simpler way to do this? For example, is there something like this?
if (1990 < year < 2099){
return 'good stuff';
}
In many languages, the second way will be evaluated from left to right incorrectly with regard to what you want.
In C, for instance, 1990 < year will evaluate to 0 or 1, which then becomes 1 < 2099, which is always true, of course.
Javascript is a quite similar to C: 1990 < year returns true or false, and those boolean expressions seem to numerically compare equal to 0 and 1 respectively.
But in C#, it won't even compile, giving you the error:
error CS0019: Operator '<' cannot be applied to operands of type 'bool' and 'int'
You get a similar error from Ruby, while Haskell tells you that you cannot use < twice in the same infix expression.
Off the top of my head, Python is the only language that I'm sure handles the "between" setup that way:
>>> year = 5
>>> 1990 < year < 2099
False
>>> year = 2000
>>> 1990 < year < 2099
True
The bottom line is that the first way (x < y && y < z) is always your safest bet.
You could make your own method:
// jquery
$(function() {
var myNumber = 100;
try {
if (myNumber.isBetween(50, 150))
alert(myNumber + " is between 50 and 100.");
else
alert(myNumber + " is not between 50 and 100.");
} catch (e) {
alert(e.message());
}
});
// js prototype
if (typeof(Number.prototype.isBetween) === "undefined") {
Number.prototype.isBetween = function(min, max, notBoundaries) {
var between = false;
if (notBoundaries) {
if ((this < max) && (this > min)) between = true;
alert('notBoundaries');
} else {
if ((this <= max) && (this >= min)) between = true;
alert('Boundaries');
}
alert('here');
return between;
}
}
hope this helps.
Max
The fast and simple way to make this is to create a function like this:
function inRange(n, nStart, nEnd)
{
if(n>=nStart && n<=nEnd) return true;
else return false;
}
Then use that as follows:
inRange(500, 200, 1000) => this return true;
Or like this:
inRange(199, 200, 1000) => this return false;
If you don't like the boolean operator, you could always use nested if statements:
if (1990 < year)
{
if( year < 2099)
return 'good stuff';
}
From a similar solution here: http://indisnip.wordpress.com/2010/08/26/quicktip-check-if-a-number-is-between-two-numbers/
$.fn.between = function(a,b){
return (a < b ? this[0] >= a && this[0] <= b : this[0] >= b && this[0] <= a);
}

Categories