I have this piece of code which iterates a chosen set of days and should ring true if today is part of the chosen set. However, isDay rings false regardless of the daysChosen or what today happens to be. So what am I missing here?..
var date = new Date;
var isDay;
var today=date.toString().substring(0,4)
//console.log(today)//good
for (var daysChosen of ['Sun','Mon','Tue','Wed','Thu'])
{
console.log(daysChosen)//good
isDay = today==daysChosen ? true : false
}
console.log(isDay)//bad, should be true if today is part of daysChosen
Update:
Ok, this is some BULL ****!!!... how on earth can this evaluate to true given that today is in the array!?...
for (var value of ['Sun','Mon','Tue','Wed','Thu','Fri'])
{
var _day = (today!=value) ? true : false
break;
}
console.log(_day)
You have a few major problems that are causing you issues in your code.
var today=date.toString().substring(0,4) - The days are 3 characters long, so your getting the extra space at the end. today === "Sun ", notice the extra space.
Your not breaking out of your loops once you find the correct value as other answers have pointed out.
You can simply use the indexOf method. It returns the index of the given string or -1 if its not contained in the array.
var date = new Date();
// first 3 characters from string for day of week
var today = date.toString().substring(0,3);
var days = ['Sun','Mon','Tue','Wed','Thu'];
var isInDays = days.indexOf(today) > 0; // indexOf returns -1 if not contained
Or to fix your existing code:
var date = new Date;
var isDay;
var today=date.toString().substring(0,3)
//console.log(today)//good
for (var daysChosen of ['Sun','Mon','Tue','Wed','Thu'])
{
console.log(daysChosen)//good
isDay = today==daysChosen ? true : false
if(isDay) break; // must break once you find it or you will keep overriding the value.
}
Your loop continue looping when isDay becomes true and in the next iterations could assign false to it. You could use break statement to exit loop:
var isDay = false;
for (var daysChosen of ['Sun','Mon','Tue','Wed','Thu'])
{
if (today == daysChosen) {
isDay = true;
break;
}
}
You can also use Array.prototype.find() function to check if array contains today. (!! is double negation):
var isDay = !!['Sun','Mon','Tue','Wed','Thu'].find(function(day) {
return day === today;
})
Unfortunately find is not compatible with all browsers.
If you have an array of things and want to check if it has something, I would use the new .includes() property on arrays:
["Sun", "Mon", "Tue", "Wed", "Thu"].includes(today);
Also, instead of extracting the day of the week from the string output, use Date.prototype.getDay().
If you don't want to include the polyfill, you can use this trick I learned from Codegolf.SE:
~["Sun", "Mon", "Tue", "Wed", "Thu"].indexOf(today);
The ~ is a binary NOT operator, which will transform the bits in a data type to their opposite. The binary NOT of -1, which is returned from .indexOf() when there are no instances of the search term, is 0. In JavaScript there's a concept called coercion, which means that when there's typal dissonance, like adding booleans, for example, there are values of one type that will convert to another. For example, all numbers that are not zero are coerced to true, and 0 coerces to false. Becuase of this, if you put the above text into an if statement, it will act as if it is an .includes().
A better way
You're extracting the day of the week from the Date.toString(), which is not good practice. Consider using array access and Date.prototype.getDay() to make the process a lot more logical:
let today = new Date().getDay();
// Sun., Mon., Tue., etc.
if ([true, true, true, true, true, false, false][today]) {
// Day is matched
} else {
// Day is not matched
}
This has some advantages
Ultimate Customizability. You can specify exactly which days you want to match
Doesn't rely on strings. Your method of extracting from the string is going to get tripped up in non-English user agents, becuase their Date Strings will be different.
Related
I want to check whether value : 30-08-2019 is present in array :['30-08-2019','25-09-2019','03-12-2019'].
This I could achieve by comparing the dates.
function isInArray(array, value): boolean {
return !!array.find(item => { return item.getTime() == value.getTime() });
}
But if my input date is 31-08-2019,then also the output should be true.
But if it is 31-08-2020, then the output should be false.
So, The check should be on the month and year and not the day.
Any help would be appreciated.
If you want to just check the month and the year, and if you can be sure that there are leading zeroes in all dates, you can simply use a substring of the date; cut off the initial three characters, which are the day and the hyphen.
If the leading zero might be omitted, you can split the string into components on the hyphen, and compare the second and third element of the resulting array instead.
You could for example do something along these lines:
let array = ["30-08-2019", "25-09-2019", "03-12-2019"];
const isMatch = (date) => array.some((e) => e.match(date.slice(2)));
console.log(isMatch("30-08-2019")); // true
console.log(isMatch("31-08-2019")); // true
console.log(isMatch("31-08-2020")); // false
You can compare month and year like that:
function isInArray(array, value): boolean {
return !!array.find(item => { return ((item.getMonth() == value.getMonth())&&( item.getYear() == value.getYear())) });
}
In the column where the hours/minutes are stored for some of the business facilities time stamp(s) are presented in this format 0000-0000. The first two digits represent hours and the other two minutes. Here is example of some business hours:
0700-2300 M-F 0700-1700 S&S
0600-2200
0600-2300 Mon-Fri 0700-2200 Sat&Sun
Local 1 0000-2359 Local 2 0630-2230
0700-2100
0600-2345
The original solution that I had was to convert the values in JavaScript and that it was pretty simple. The problem I have is when there is more than one set of time hours/minutes in the string. In the example above that is the case where hours/minutes are different during the weekend or for the different locations. The JS code example is here:
var time = calcDifference("0600-2345");
function calcDifference(time) {
var arr = time.split('-').map(function(str) {
var hours = parseInt(str.substr(0, 2), 10),
minutes = parseInt(str.substr(2, 4), 10);
var result = (hours * 60 + minutes) / 60;
return result.toFixed(2);
});
return arr[1] - arr[0];
}
console.log(time);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
The code above works just fine if I pass the argument with one time stamp. I'm wondering how to handle situation where I have two time stamps? What would be a good solution to search if string has more than one hours/minutes values and then convert each of them and return to the user.
Assuming the HHMM-HHMM format is consistent in the input, and you don't care about discarding the remaining information in the string, regex is probably the simplest approach (and much safer than your current approach of splitting on hyphens, which might easily occur in other parts of the string you don't care about.)
Note that you won't be able to distinguish between "weekend" and "weekday" times, because that information isn't in a consistent format in your input. (This looks like human input, which pretty much guarantees that your HHMM-HHMM format also won't be strictly consistent; consider allowing for optional whitespace around the hyphen for example, and logging strings which show no match so you can check them manually.)
var testinputs = [
"0700-2300 M-F 0700-1700 S&S",
"0600-2200",
"0600-2300 Mon-Fri 0700-2200 Sat&Sun",
"Local 1 0000-2359 Local 2 0630-2230",
"0700-2100",
"0600-2345"
]
var reg = /(\d\d)(\d\d)\-(\d\d)(\d\d)/g; // \d means any digit 0-9; \- matches a literal "-", parens capture the group for easier access later
for (input of testinputs) {
console.log("Input: ", input)
var matches;
while ((matches = reg.exec(input)) !== null) { // loop through every matching instance in the string
// matches[0] is the full HHMM-HHMM string; the remainder is
// the HH and MM for each parenthetical in the regexp:
console.log(matches)
}
}
There are plenty of ways to do this ( based on your point of view ), but this is my favourite one. you can manipulate the text then pass numbers individually.
var date = '0700-2300 M-F 0700-1700 S&S'.match( /[-\d]+/gi ).filter( e => ~e.search( /\d+/gi ) )
now you have an array of multiple timestamps saved on your database and you pass them individually to your function.
date.forEach( each => calcDifference( each ) );
You can use a regex like /\d{4}\-\d{4}/g to extract all of the digits from the string and map them to their time differences or replace text in the original.
const calcDifference = range => {
const time = range.split`-`
.map(e => (+e.substr(0, 2) * 60 + (+e.substr(2))) / 60)
return time[1] - time[0];
};
const diffs = `0700-2300 M-F 0700-1700 S&S
0600-2200
0600-2300 Mon-Fri 0700-2200 Sat&Sun
Local 1 0000-2359 Local 2 0630-2230
0700-2100
0600-2345`.replace(/\d{4}\-\d{4}/g, calcDifference);
console.log(diffs);
So I have this script:
function makeActive() {
var element, name, arr;
element = document.getElementById("liveChat");
name = "active";
arr = element.className.split(" ");
if (arr.indexOf(name) == -1) {
element.className += " " + name;
}
}
var currentTime = new Date();
var currentTimeFormatted = currentTime.toLocaleTimeString();
if(currentTimeFormatted >= '08:00:00' && currentTimeFormatted <= '16:30:00'){
makeActive();
}
Which works perfectly in Chrome, however in IE the class doesn't get added.
If I remove the
&& currentTimeFormatted <= '16:30:00'
IE also adds the class. Why would adding a second condition, break this script within IE?
To make this a tad easier than having to use && and || mix, or if your values are stored somewhere in a static file etc. You could create a kind of pseudo time, by multiply each section.
eg.
const cTime = new Date();
const ptime =
cTime.getHours() * 10000 +
cTime.getMinutes() * 100 +
cTime.getSeconds();
if (ptime >= 80000 && ptime <= 163000) {
console.log("Active");
} else {
console.log("InActive");
}
You are doing string comparisons, which means that the browser and locale dependent output of toLocaleTimeString() screws your code in IE, and possibly also in other browsers or regions, because this function is solely intended for producing a human-readable time representation.
So you should either:
(1) Use a string representation that is standardized, e.g. invoking toISOString(). This will also get rid of time zone problems, because the result will always be in UTC time:
var currentTimeFormatted = new Date().toISOString(); // 2018-11-07T12:28:12.448Z'
currentTimeFormatted = currentTimeFormatted.substr(currentTimeFormatted.indexOf('T') + 1, 8); // 12:27:12
Now the rest of your code will work (assuming you 08:00:00 and 16:30:00 are UTC times).
(2) Extract the hour and minute parts of the new Date() and compare those to integers:
var currentTime = new Date();
if(currentTime.getHours() >= 8
&& // similarly a comparison to < 16:30
) {
makeActive();
}
(3) Use the great solution by Keith (see below), which I think is the best way to go
IE's implementation of date.toLocaleTimeString() adds non-printable characters into the string. The easiest way to deal with them is to trim them from the string;
currentTimeFormatted = currentTime.toLocaleTimeString().replace(/[^ -~]/g,'')
When dealing with localized timezones and timezone comparison, it might be worth trying a library like moment.js which can also deal with comparing values using the isBetween funciton
Edit
As the other solutions have suggested - using toLocaleTimeString() is not a safe method of performing date comparison and should be avoided.
<script>
dfrom = datefrom.split("/");
dto = dateto.split("/");
//Checking Year Part;
if(parseInt(dfrom[2]) > parseInt(dto[2])){
alert("DateFrom Cannot greater than DateTo");
return false;
}
if((parseInt(dfrom[1]) > parseInt(dto[1])) && parseInt(dfrom[2]) == parseInt(dto[2])){
alert("DateFrom Cannot greater than DateTo");
return false;
}
if(parseInt(dfrom[0]) > parseInt(dto[0]) && (parseInt(dfrom[1]) == parseInt(dto[1])) && parseInt(dfrom[2]) == parseInt(dto[2])){
alert("DateFrom Cannot greater than DateTo");
return false;
}
</script>
This is my script code to compare dates and is working fine but when I check 07/04/2013 and 08/04/2013, it shows "DateFrom Cannot greater than DateTo" and only these dates are showing wrong result. Is any error in my script or something else?
Any help would be highly appreciable.
try this
dfrom = datefrom.split("/");
dto = dateto.split("/");
var x=new Date();
x.setFullYear(dfrom [2],dfrom [1]-1,dfrom [0]);
var y=new Date();
y.setFullYear(dto [2],dto [1]-1,dto [0]);
if (x>y)
{
alert("X is big ");
}
else
{
alert("Y is big");
}
see here
When interpreting the parseInt function's arguments, older browsers will use the octal radix (base-8 numbering system) as default when the string begins with "0" (e.g., '07', '08'). As of ECMAScript 5, the default is the decimal radix (10) (i.e., this is tricky, but at least now it is depreciated).
In other words, there is a chance that if you pass strings ("01") or numbers (01) that begin with 0 to parseInt without specifying the second parameter (radix, which means what numbering system), they will be interpreted as having radix 8. This means 07 === 7 and 08 probably has undefined behavior (0, "", undefined, who knows?).
To be safe, always set your radix in the second parameter to parseInt when dealing with dates (I know I do), for example parseInt(x, 10) for regular base 10.
By the way, leading numbers with 0 indicates the octal radix other languages, so it is a good to get rid of them when converting strings to numbers.
Good luck!
The easiest way to compare date strings is to turn them into date objects and compare those, so if your date strings are in the format d/m/y. you can do:
// s in format d/m/y
// e.g. 15/3/2013 or 15/03/2013
function toDate(s) {
var s = s.split('/');
return new Date(s[2], --s[1], s[0]);
}
var d0 = '3/3/2013';
var d1 = '15/3/2013';
// Compare dates
alert( toDate(d0) < toDate(d1) ); // true
alert( toDate(d1) < toDate(d0) ); // false
When used in a comparison or arithmetic operation, Date objects are coerced to a number that is their time value.
Using Jquery TableSorter, I am creating a custom parser to sort elapsed time <td>s that contain "'#' year(s) * '#' month(s)". When I use the function
$('.techtable td:nth-child(6)').each(function(){
// console.log($(this));
var that = $(this).text();
var myRegexp = /([\d]+) ([\w]+)(?: ([\d]+) ([\w]+))?/;
var match = myRegexp.exec($(this).text());
console.log(match);
});
from the command line, each index contains an array of length 5, looking like this:
["7 months", "7", "months", undefined, undefined]
to this:
["3 years 3 months", "3", "years", "3", "months"]
depending on whether or not the elapsed time has just a month or year element, and then the other. To parse the text, I use regex to gather each element, and then use JS to test whether there are multiple elements or not, and if 1 element only, then wheher it begins with "y" or "m", and return the number of months, so the parser can sort the <td>s by number of months in integer form.
The parser passes in each element into the function as parameter "s". when i try regex on "s" directly, it is not returning an array of length 5, it is truncating it to 3 (whether or not I am running the line that truncates it if index 3 is typeof 'undefined'). When I use the console to directly use this function:
$('.techtable td:nth-child(6)').each(function(){
// console.log($(this));
var that = $(this).text();
var myRegexp = /([\d]+) ([\w]+)(?: ([\d]+) ([\w]+))?/;
var match = myRegexp.exec($(this).text());
if (typeof match[3] == 'undefined') {match.length = 3;};
console.log(match);
});
the regex returns the arrays properly, with the array truncated if it only has 1 element (year or month). Here is the code for the custom parser:
var myRegexp = /([\d]+) ([\w]+)(?: ([\d]+) ([\w]+))?/;
var match = myRegexp.exec(s);
var order = [];
console.log(match);
if (typeof match[3] == 'undefined') {match.length = 3;};
// 1 element case:
// month
if (match.length = 3) {
if (match[2][0] == "m") {
order.push(match[1]);
}
// year
if (match[2][0] == "y") {
order.push(match[1]*12);
}
// both elements
} else {
order.push(match[1]*12 + match[3]);
}
s = order;
return s;
},
The fiddle is here. The Elapsed parser is second from the bottom of the JS panel. As you can see, since I can't get the months from the array (indices 4 and 5), I can not calculate the months, and thus the sorting only incorporates years, and the months are sorted by their original HTML placement. What am I missing? (I'm learning.... so direction is appreciated more than an fix, but I won't turn it down.)
Yes I realize the JS fiddle is loaded (first part is TableSorter, to maintain functionality for verification(click on headers to sort), but all you need to focus on is the last part of the code (reference the '//Table Sorter dateSorter' to see how a correct parser should look). The section '//Table Sorter elapsedSorter' is where my two attempts are, the first part is the working code I use in the console, and the seconde part is the parser, which is somehow deleting the last two indices in the array, thus loosing the month information to calculate.
Guess I'll have to add Regex, and a personal rating of 1, since I've wasted almost an entire day on this.
if (match.length = 3) {
You meant this?
if (match.length == 3) {
To help you further, when you write conditions with one constant and a variable, you can write them like this instead:
if (3 = match.length) {
This would now cause a JavaScript error instead of silently getting turned into an assignment that always yields true.
In JavaScript, 12 + '4' == '124', so you have to be careful with numbers and the + operator. In languages such as PHP you don't have this problem, because they have an operator for string concatenations ;-)
var myRegexp = /([\d]+) ([\w]+)(?: ([\d]+) ([\w]+))?/;
var match = myRegexp.exec(s);
var order = [];
if (typeof match[3] == 'undefined') {
if (match[2][0] == "m") {
order.push(parseInt(match[1]));
}
// year
if (match[2][0] == "y") {
order.push(parseInt(match[1])*12);
}
// both elements
} else {
order.push(parseInt(match[1])*12 + parseInt(match[3]));
}
s = order;
return s;
Btw use parseInt(x, 10) if you expect fields to have leading zeroes (which would otherwise result in 0 being returned). Thanks fudgey!