I am trying to check the week object's minutes and hours and I cannot figure out what I am doing wrong. The week object can contain variations of Day1 - Day7 so I dont want to check them specifically. I want to check the nested Hours/Minutes. I also don't want to use jquery and it has to work with ie8. Any help would be greatly appreciated.
week = {
Day1: {
Hours: 6,
Minutes: 20
},
Day2: {
Minutes: 45
},
Day3: {
Hours: 8,
Minutes: 15
}
};
hoursInValid = false;
minutesInValid = false;
for (var item in week) {
if (week.hasOwnProperty(item)) {
for (var i = 0; i < week[item].length; i++ )
{
if (week[item][i].Hours > 6) {
hoursInValid = true;
break;
}
if (week[item][i].Minutes > 20) {
minutesInValid = true;
break;
}
}
}
}
I don't see the need for the internal for loop. This is the solution I came up with. I added checks to make sure the DayN objects have Hours and Minutes properties.
week = {
Day1: {
Hours: 6,
Minutes: 20
},
Day2: {
Minutes: 45
},
Day3: {
Hours: 8,
Minutes: 15
}
};
hoursInValid = false;
minutesInValid = false;
for (var item in week) {
if (week[item].hasOwnProperty('Hours')) {
if (week[item].Hours > 6) {
hoursInValid = true;
break;
}
}
if (week[item].hasOwnProperty('Minutes')) {
if (week[item].Minutes > 20) {
minutesInValid = true;
break;
}
}
}
Try this:
for (var day in week) {
for (var unit in week[day]) {
if (unit === 'Hours' && week[day][unit] > 6) {
hoursInvalid = true;
} else if (unit === 'Minutes' && week[day][unit] > 20) {
minutesInvalid = true;
}
}
}
The break statements may not allow you to iterate over all the properties.
Do this instead:
var invalidHours = {}, invalidMinutes = {};
for(var i in week){
var w = week[i];
if(w.hasOwnProperty('Hours')){
invalidHours[i] = w.Hours > 6 ? true : false;
}
else{
// no hours
}
if(w.hasOwnProperty('Minutes')){
invalidMinutes[i] = w.Minutes > 20 ? true : false;
}
else{
// no minutes
}
}
if(invalidHours.Day1) // day 1 hours are invalid
if(invalidMinutes.Day2) // day 2 minutes are invalid
Related
I need help with this between function. My clock here is 24 hours.
I always get the "else" option. What is wrong with the code?
// Get time
var today = new Date();
var time = today.getHours();
console.log(time); // 8 o clock right now when I am testing
// Between function
Number.prototype.between = function(first, last) {
return first < last ? this >= first && this <= last : this >= last && this <= first;
};
// Do something
if (time.between(7, 9)) {
console.log("between(7, 9)",time.between(7, 9))
}
if (time.between(9, 15)) {
console.log("between(9, 15)",time.between(9, 15))
}
if (time.between(15, 18)) {
console.log("between(15, 18)",time.between(15, 18))
}
// and so on
else {
console.log("else")
}
The else only connects the last if. Just write else ifs
// Get time
var today = new Date();
var time = today.getHours();
console.log(time); // 8 o clock right now when I am testing
// Between function
Number.prototype.between = function(first, last) {
return first < last ? this >= first && this <= last : this >= last && this <= first;
};
// Do something
if (time.between(7, 9)) {
console.log("between(7, 9)",time.between(7, 9))
}
else if (time.between(9, 15)) {
console.log("between(9, 15)",time.between(9, 15))
}
else if (time.between(15, 18)) {
console.log("between(15, 18)",time.between(15, 18))
}
// and so on
else {
console.log("else")
}
I'm looking if there is an alternative to write this code cleaner and efficient.
My goal is to set different values based on the hour of the day.
var hour = new Date().getHours();
var user = 'User4';
if (hour >= 4 && hour < 6) {
user = 'User1';
}
if (hour >= 6 && hour < 13) {
user = 'User2';
}
if (hour >= 13 && hour < 19) {
user = 'User3';
}
if (hour >= 19) {
user = 'User4';
}
I found this article online, but I couldn't achieve logical operators into this.
let values = {
a: 1,
b: 2,
};
let foo = values[ bar ] || 3;
Really appreciate your help! Thanks 😗
You can use else if to make code shorter and cleaner
var hour = new Date().getHours();
var user;
if (hour < 4 || hour >= 19) {
user = 'User4';
} else if (hour < 6) {
user = 'User1';
} else if (hour < 13) {
user = 'User2';
} else if (hour < 19) {
user = 'User3';
}
console.log(user)
Using switch(true)
var hour = new Date().getHours();
var user;
switch(true) {
case (hour < 4 ||
hour >= 19): user = 'User4'; break;
case (hour < 6) : user = 'User1'; break;
case (hour < 13) : user = 'User2'; break;
case (hour < 19) : user = 'User3'; break;
}
console.log(user)
What about using conditional operators
var hour = new Date().getHours();
var user = 'User4'
user=(hour >= 4 && hour < 6)?'User1': (hour >= 6 && hour < 13)?'User2':(hour >= 13 && hour < 19)?'User3':(hour >= 19)?'User4':''
console.log(user)
If you mean you want to do it by ternary operators, you can try
let user = hour <13? (hour >= 6 && hour < 13)? "User 2" : "User 1" : (hour >= 13 && hour < 19)? "User 3" : "User 4"
This should be the simplest way to achieve the desired result, however you may continue with your own example and do something like
let values = {
a: "User 1",
b: "User 2",
c: "User 3",
d: "User 4"
};
let bar = hour <13? (hour >= 6 && hour < 13)? "b" : "a" : (hour >= 13 && hour < 19)? "c" : "d"
let foo = values[ bar ] || 3;
If you want to write this as an object, you need to list all 24 hours, making the code simpler, but longer:
var hour = new Date().getHours();
var name = 'User';
var id = {
0: 4,
1: 4,
2: 4,
3: 4,
4: 1,
5: 1,
6: 2,
7: 2,
8: 2,
9: 2,
10: 2,
11: 2,
12: 2,
13: 3,
14: 3,
15: 3,
16: 3,
17: 3,
18: 3,
19: 4,
20: 4,
21: 4,
22: 4,
23: 4
};
var user = name + id[ hour];
console.log(user);
As mentioned in the article you linked, I feel this is one of those logic blocks where ternaries make things ugly.
So personally i would prefer the if/else version below since its the most readable as if it were 'plain english'.
Here is an alternative that doesn't use if or switch:
var periods = [
{ from: 0, to: 4, user: 'User4' },
{ from: 4, to: 6, user: 'User1' },
{ from: 6, to: 13, user: 'User2' },
{ from: 13, to: 19, user: 'User3' },
{ from: 19, to: 23, user: 'User4' }
];
var hour = new Date().getHours();
var user = periods.find(p => hour >= p.from && hour < p.to).user;
You could move the conditions inside of an own function for getting the user and return early if the condition match.
function getUser(hour) {
if (hour < 4) return 'User4';
if (hour < 6) return 'User1';
if (hour < 13) return 'User2';
if (hour < 19) return 'User3';
return 'User4';
}
var hour = new Date().getHours(),
user = getUser(hour);
console.log(user);
I don't get what #Asaf is asking but if he want something like below one
let values = {
a: 1,
b: 2,
};
let foo = values[ bar ] || 3;
he can try something like this (This is not prefered way to do)
var hour = new Date().getHours();
let values = {
4 : 'User1',
5 : 'User1',
6 : 'User2',
7 : 'User2',
8 : 'User2',
9 : 'User2',
10 : 'User2',
11 : 'User2',
12 : 'User2',
13 : 'User3',
14 : 'User3',
15 : 'User3',
16 : 'User3',
17 : 'User3',
18 : 'User3',
};
let foo = values[ hour ] || 'User4';
console.log(foo);
From a Code golf point of view, chaining the ternary operator could be the shortest method.
But it doesn't help with the readability if it's used in one long line.
But a bit of code indentation helps.
var hour = new Date().getHours();
var user = (hour >= 4 && hour <= 5 ? "User1"
: hour >= 6 && hour <= 12 ? "User2"
: hour >= 13 && hour <= 18 ? "User3"
: hour >= 19 ? "User4"
: "User4");
console.log(hour, user);
Or this shorter version:
var hour = new Date().getHours();
var user = (hour < 4 || hour > 18 ? "User4"
: hour < 6 ? "User1"
: hour < 13 ? "User2"
: "User3");
console.log(hour, user);
Your current approach is fine and is efficient. An alternative approach you could take is a functional one, where you define each range using a function like so:
const hour = new Date().getHours();
const I = x => x;
const K = x => y => x;
const setRange = (x, y, out) => (f, h) => f(h >= x && h < y)(out);
const createRanges = (...ranges) => def => h => {
for(const rf of ranges)
if(rf(K, h)) return rf(K(I), h);
return def;
}
const getUser = createRanges(
setRange(4, 6, 'User1'),
setRange(6, 13, 'User2'),
setRange(13, 19, 'User3')
)("User4"); // default/else "User 4"
const user = getUser(hour);
console.log(hour, user);
I have an array of time ranges with start & end values.
var timeRanges = [{
start: 120,
end: 140
},{
start: 180,
end: 220
},{
start: 250,
end: 300
}]
Need to check whether the selected range overlap the time range or not. And also the selected range should be in between the timeRange intervals. (Ex: 140-180, 220-250)
var selected = {
start: 150,
end: 170
}
Time interval B 'overlaps' A if:
B starts after A starts but before A finishes.
B starts before A starts and finishes after A starts.
So you can write a function which decides exactly that.
function areOverlapping(A, B) {
if(B.start < A.start) {
return B.finish > A.start;
}
else {
return B.start < A.finish;
}
}
const overlaps = timeRanges.some( range =>
(range.start < selected.start && range.end > selected.start) ||
(range.start < selected.end && range.end > selected.end) ||
(range.start > selected.start && range.end < selected.end)
);
Assuming that your time ranges are sorted, this solution will work. Otherwise, you need to implement time range sorting as well.
function isValidRange(timeRanges, selectedRange) {
var isValid = true;
var minStart = timeRanges[0].start;
var maxEnd = timeRanges[timeRanges.length - 1].end;
if(selectedRange.start < selectedRange.end && selectedRange.start > minStart && selectedRange.end < maxEnd) {
for(var i=0; i<timeRanges.length; i++) {
if((selectedRange.start >= timeRanges[i].start && selectedRange.start <= timeRanges[i].end)
|| (selectedRange.end >= timeRanges[i].start && selectedRange.end <= timeRanges[i].end)) {
isValid = false;
break;
}
else if(i != timeRanges.length - 1) {
if(selectedRange.start > timeRanges[i].end && selectedRange.start < timeRanges[i+1].start) {
if(selectedRange.end < timeRanges[i+1].start) {
break;
}
else {
isValid = false;
break;
}
}
}
}
}
else {
isValid = false;
}
return isValid;
}
var timeRanges = [{
start: 120,
end: 140
},{
start: 180,
end: 220
},{
start: 250,
end: 300
}];
var selected = {
start: 141,
end: 222
};
alert(isValidRange(timeRanges, selected));
Why don't you run your selection through the array and calculate what you need?
timeRanges.forEach(function(aRange, index)) {
if (selected.start > aRange.start && selected.end < aRange.end)
console.log('Selection falls within the item ' + index):
}
I'm trying to write a function that returns an array of equally chunked up dates and number of days pertaining to those dates. Should there be a remainder of those days they get appended to the array as follow.
Expected outcome:
[{
'startDate' : 20160719 //dates generated from momentjs
'numOfDays': 5
},{
'startDate' : 20160724
'numOfDays': 5
},{
'startDate' : 20160729
'numOfDays': 3
}]
Below is the function I've written in which you can pass in a start date (momentjs), the total number of days (daysToDisplay) and number of days to be divided by (numOfDays).
function buildQueue(startDate, numOfDays, daysToDisplay) {
if (!startDate || !numOfDays || !daysToDisplay) {
throw new Error('All params required!');
}
var num = numOfDays > daysToDisplay ? daysToDisplay : numOfDays;
var div = Math.floor(daysToDisplay / num);
var count = daysToDisplay;
var rem = daysToDisplay % num;
var lastItem;
var i;
var arr = [];
for (i = 0; i <= daysToDisplay; i += num) {
arr.push({
startDate: moment(startDate, 'YYYYMMDD').add(i, 'days').format('YYYYMMDD'),
numOfDays: numOfDays,
count: i
})
if (rem === count) {
break;
}
count -= num;
}
if (count > 0) {
lastItem = arr[arr.length - 1];
var leftover = daysToDisplay - lastItem.count;
arr.push({
startDate: moment(lastItem.startDate, 'YYYYMMDD').add(num, 'days').format('YYYYMMDD'),
numOfDays: rem,
count: leftover + lastItem.count
});
}
return arr;
}
A working example is here (https://jsfiddle.net/zv5ghqpa/1/). The code appears to work in scenarios where daysToDisplay is dividable by more than 2.
When daysToDisplay is only dividable by one, we get an additional item in the returned array basically due to the zero index in the for loop. The expected outcome if I call buildQueue('20160719', 5, 8) should be:
[{
'startDate': 20160719
'numOfDays': 5
}, {
'startDate': 20160724
'numOfDays': 3
}]
Instead its returning:
[{
'startDate': 20160719
'numOfDays': 5
},{
'startDate': 20160724
'numOfDays': 5
}, {
'startDate': 20160729
'numOfDays': 3
}]
I hope i've given enough info... this is really doing my head in.
Thanks in advance!
I think this is code you're looking for:
function buildQueue(startDate, numOfDays, daysToDisplay) {
if (!startDate || !numOfDays || !daysToDisplay) {
throw new Error('All params required!');
}
var num = numOfDays > daysToDisplay ? daysToDisplay : numOfDays;
var div = Math.floor(daysToDisplay / num);
var count = daysToDisplay;
var rem = daysToDisplay % num;
var n = 0;
var i;
var arr = [];
for (i = 0; i <= daysToDisplay; i += num) {
arr.push({
startDate: moment(startDate, 'YYYYMMDD').add(i, 'days').format('YYYYMMDD'),
numOfDays: daysToDisplay % num,
count: i
})
console.log(rem + ' ' + count);
if (rem === count) {
count = 0;
break;
}
count -= num;
}
if (count > 0) {
var leftover = daysToDisplay - arr[arr.length - 1].count;
arr.push({
startDate: moment(arr[arr.length - 1].startDate, 'YYYYMMDD').add(num, 'days').format('YYYYMMDD'),
numOfDays: daysToDisplay % num,
count: leftover + arr[arr.length - 1].count
});
}
return arr;
}
//console.log(buildQueue(moment(), 80, 100));
console.log(buildQueue(moment(), 5, 8));
//console.log(buildQueue(moment(), 15, 100));
//console.log(buildQueue(moment(), 30, 100));
//console.log(buildQueue(moment(), 45, 100));
I think the 'Expected outcome' was correct before you edited the question. I also note the sample code produced a count property that you don't want in the output.
Perhaps this code does what you want?
function buildQueue(startDate, numOfDays, daysToDisplay) {
var arr = []
while (daysToDisplay > 0) {
arr.push({
startDate: moment(startDate, 'YYYYMMDD')
.add(numOfDays * arr.length, 'days')
.format('YYYYMMDD'),
numDays: Math.min(numOfDays, daysToDisplay)
})
daysToDisplay -= numOfDays
}
return arr
}
Assume i have a function checkTime like the one below where i have to check for multiple condition simultaneously.
var result=0;
function checkTime(time1, time2) {
if (time1 >= 0 && time2 <= 0) {
result = 1;
}
else if (time1 >= 0 && time2 <= 1) {
result = 4;
}
else if (time1 >= 2 && time2 <= 3) {
result = 5;
}
else if (time1 >= 4 && time2 <= 6) {
result = 6;
}
else if (time1 >= 7 && time2 <= 9) {
result = 7;
}
else if (time1 >= 11 && time2 <= 12) {
result = 8;
}
else if (time1 >= 13 && time2 <= 15) {
result = 9;
}
else if (time1 >= 16 && time2 <= 17) {
result = 10;
}
else if (time1 >= 19 && time2 <= 20) {
result = 11;
}
return result;
}
(The above given example is hypothetical)
The function i have used totally works,but:
Is there a better method or procedure or formula to replace this?(where it doesnt have to be this lengthy or ugly)
Thanx!
You can use an array to represent all the combination:
tests = [
{ time1: 0, time2: 0, result: 1 },
{ time1: 0: time2: 1, result: 4 },
...
];
for (var i = 0; i < tests.length; i++) {
if (time1 >= tests[i].time1 && time2 <= tests[i].time2) {
return tests[i].result;
}
}
If the code is identical, and only the values change, you could do something like this:
function checkTime(time1, time2) {
[
[0, 0, 0],
[0, 1, 0]
].forEach(function (it) {
if (time1 >= it[0] && time2 <= it[1]) {
return it[2];
}
});
}
Well, first off you have the possibility of an undefined result, so that makes things ambiguous. Should result start at 0 instead? This is an important detail. Second, you seem to be working with boundaries, so it would help to change the <= to < to make this clearer. (If so, the 7-9/11-12 section has a bug.) Third, you have an implicit comparison of time1 and time2, so make that explicit.
var result = 0;
var diff = time2 - time1;
var bounds = [21, 19, 16, 13, 11, 7, 4, 2, 0];
if (diff <= 0) result = 0; // unexpected outcome
else
for (position = 1; position < bounds.length; ++position) {
if (time1 >= bounds[position]) {
if (time2 < bounds[position - 1]) {
result = 3 + (bounds.size - position);
}
break;
}
}
return result;
Other implementations are possible, but it's hard to tell based on your question exactly what problem you're solving.
follow-up
This section of code has a gap:
else if (time1 >= 7 && time2 <= 9) {
result = 7;
}
else if (time1 >= 11 && time2 <= 12) {
result = 8;
}
If time = 10 and time2 = 10, there is no match. It's easy to miss this type of error when you are repeating yourself. Specifying lower and upper bounds for each condition is unnecessary repetition. Since I couldn't see a pattern to the bounds (which could be delegated to a function), I just put the lower bounds into an array and made sure it was sorted descending so that the loop could stop after the first match.