getMonth doesnt recognize dates - javascript

So have my googledocs document with following 2 functions in javascript:
function test(date) {
return date.getMonth()+1
}
function hours_monthly(target_month, target_year, date_range, hour_range) {
r = 0;
for (i = 0; i < date_range.length ; i++){
if (target_month == date_range[i].getMonth() +1 && date_range[i].getYear() - 2000 == target_year ){
r += hour_range[i]
}
}
return r
}
So now I want to use the code. While the test function is just fine at reading the month of any given date, by assigning "= test(C9)" to cell. Where C9 is a cell which got the date of 6/9/16 assigned to it.
If use a the second funtion it says it can't find the getMonth() function of the exact same date C9 and just outputs ERROR. More precisly it says:
"can't find the getMonth() function in Tue Sept 06 2016 00:00:00 GTM +0200"
date_range is an array of dates, hour_range is an array of integers.
The problem porbably lies somewhere in the usage of arrays.
The same problem arrises when doing comparisions:
function test2(date1, date2) {
if (date1 > date2) {
return 1
}
else {
return 2
}
function hours_period(start_date, end_date, date_range, hour_range){
r = 0;
t = 0;
for (i = 0; i < date_range.length; i++){
if ( (date_range[i] >= start_date) && (date_range[i] <= end_date) ){
t += 1
r += hour_range[i]
}
}
return [t, r]
}
Now again the test2 function works totally fine but as soon as I feed an array (date_range) it stops working, in this case it doesnt give an ERROR instead it just outputs [0,0] no matter how many dates acutally fit the if-statement

You pass date as string and string don't have getMonth method.
Fix it by wrap the date in new Date(date)
function test(date) {
// I wrap the new date you pass with new Date(date)
return new Date(date).getMonth()+1;
}
function hours_monthly(target_month, target_year, date_range, hour_range) {
r = 0;
for (i = 0; i < date_range.length ; i++){
if (target_month == date_range[i].getMonth() +1 && date_range[i].getYear() - 2000 == target_year ){
r += hour_range[i]
}
}
return r
}
console.log(test("6/9/16"));

Related

How to get an array of 10 next Mondays in javascript

Here is my code but this array returns only the same elements, i am trying to create an array which contains 10 elements as the next mondays anyone know please help me
my code:
function getNextDayOfTheWeek(dayName, excludeToday = true, refDate = new Date()) {
const dayOfWeek = ["sun","mon","tue","wed","thu","fri","sat"]
.indexOf(dayName.slice(0,3).toLowerCase());
if (dayOfWeek < 0) return;
refDate.setHours(0,0,0,0);
refDate.setDate(refDate.getDate() + +!!excludeToday +
(dayOfWeek + 7 - refDate.getDay() - +!!excludeToday) % 7);
return refDate;
}
let arr=[]
for(let i=0;i<10;i++){
arr.push(arr[i]=getNextDayOfTheWeek("Monday",false))
}
console.log(arr)
getNextDayOfWeek is being given the same inputs and so will have the same outputs.
You need to:
Establish the base line date and pass it as the third parameter
Pass the resulting date on the subsequent calls so that it advances
Indicate that it should exclude the base line date if it matches the requested date
Insert a new Date into the result array, because Dates are objects and thus passed by reference. If you don't do this, each call of getNextDayOfTheWeek will be making changes to the same object stored in each position of the result array.
Note that your local time might cause the displayed date to appear to be before or after the expected date. You will likely need to decide how to account for local timezone (note that the result might show Z at the end of the time indicating UTC).
let arr=[]
let refDate = new Date()
for(let i=0;i<10;i++){
refDate = getNextDayOfTheWeek("Monday",false, refDate)
arr.push(refDate)
}
function getNextDayOfTheWeek(dayName, excludeToday = true, refDate = new Date()) {
const dayOfWeek = ["sun","mon","tue","wed","thu","fri","sat"]
.indexOf(dayName.slice(0,3).toLowerCase());
if (dayOfWeek < 0) return;
refDate.setHours(0,0,0,0);
refDate.setDate(refDate.getDate() + +!!excludeToday +
(dayOfWeek + 7 - refDate.getDay() - +!!excludeToday) % 7);
return refDate;
}
let arr=[]
let refDate = new Date()
for(let i=0;i<10;i++){
refDate = getNextDayOfTheWeek("Monday", i > 0 ? true : false, refDate)
arr.push(new Date(refDate))
}
console.log(arr)

Comparing simple date strings (e.g. console.log("24.3.2018" < "20.3.2017"))

I wanted to know if the method of comparing two string values of dates, mentioned in the title, is legit. I have tried multiple different versions of comparison and they all seem to work.
console.log("23.3.2018" > "24.3.2018")
//VM16380:1 false
//undefined
console.log("23.3.2018" < "24.3.2018")
//VM16381:1 true
//undefined
console.log("24.3.2017" < "24.3.2018")
//VM16384:1 true
//undefined
console.log("24.3.2018" < "20.3.2017")
//VM16385:1 false
Thank you!
You can parse your String date to Date Object and compare :
function CompareDate(dateStr1,dateStr2) {
var dateArry1 = dateStr1.split(".");
var dateArry2 = dateStr2.split(".");
//JavaScript counts months from 0 index so we have to do -1:January - 0, February - 1, and so on.....
var dateOne = new Date(dateArry1[2], dateArry1[1]-1, dateArry1[0]); //Year, Month, Date
var dateTwo = new Date(dateArry2[2], dateArry2[1]-1, dateArry2[0]); //Year, Month, Date
if (dateOne > dateTwo) {
console.log("Date One is greather then Date Two.");
return true;
}else if(dateOne < dateTwo) {
console.log("Date Two is greather then Date One.");
return false;
}else if(dateOne.toDateString() === dateTwo.toDateString()) {
console.log("Date are same.");
return false;
}
return false;
}
console.log(CompareDate("23.3.2018","24.3.2018"));
//VM16380:1 false
//undefined
console.log(CompareDate("23.3.2018","24.3.2018"));
//VM16381:1 true
//undefined
console.log(CompareDate("24.3.2017", "24.3.2018"));
//VM16384:1 true
//undefined
console.log(CompareDate("24.03.2018" , "20.3.2017"));
console.log(CompareDate("24.3.2018" , "24.03.2018"));
//VM16385:1 false
WARNING !
In some browsers, months or days with no leading zeroes may produce an error:
var d = new Date("2015-3-25");
So better to prepend zero in month and days in case of length is 1.
you can compare the date values in javascript like this :
var start= new Date('2018.3.23');
var end= new Date('2018.3.24');
if (start < end)
{
console.log(true);
}

Need help on Javascript prototype functions

function Weekday (name, traffic) {
this.name = name;
this.traffic = traffic;
}
function mostPopularDays(week) {
week = [];
week.push(this.name, this.traffic);
if(week.length > 1){
return week;
}else if(week.length === null || week === []){
return null;
}else {
return week[0];
}
}
var mon = new Weekday("Monday", 200);
mostPopularDays(mon);
/**
* Determines which day of the week had the most nnumber of people visiting the
* pet store. If more than one day of the week has the same, highest amount of
* traffic, an array containing the days (in any order) should be returned.
* (ex. ["Wednesday", "Thursday"]). If the input is null or an empty array, the function
* should return null.
* #param week an array of Weekday objects
* #return a string containing the name of the most popular day of the week if there is only one most popular day, and an array of the strings containing the names of the most popular days if there are more than one that are most popular
*/
I've been seriously learning Javascript for over 2 weeks now then I took this course in EDx and apparently, still can't solve this kind of problem. The code above is my own code and I know its wrong(except the Weekday function). A help would be gladly appreciated.Thanks
The mostPopularDays function never actually uses the provided argument as it is replaced on the first line.
function mostPopularDays(week) {
week = [];
Then there is an out of context this, the function mostPopularDays is not related in any way to the WeekDay, so the this you are referring to is actually the mostPopularDays function itself and not the intended WeekDay you provided.
From what I understand from the text describing the assignment there should be more than one argument to mostPopularDays in order to filter out the most most popular ones ("#param week an array of Weekday objects").
So, your TODO-list is as follows:
rename the argument to mostPopularDays to represent the input to be an array of WeekDay (I'd use weeks (+s) or weekList)
there is no need to push anything into the array from within mostPopularDays.
there is no use for this within mostPopularDays, you want to be referring to an item in the provided array of WeekDay objects
I don't known which ways of traversing an array your course had covered so far, there are several:
for (var i = 0; i < weekList.length; ++i) { ... }
weekList.forEach(function(week) { ... })
(If you've already covered the reducing and sorting of arrays, you may want to look into those, as that would be my preferred choice)
For test you should create objects(days) and array of objects.
Then sort objects and check if there is more than one day you should return.
I also made a condition to give full answer if there is more than one day with highest traffic.
var mon = new Weekday('Monday', 5);
var tue = new Weekday('Tuesday', 3);
var wed = new Weekday('Wednesday',8);
var thu = new Weekday('Thursday', 5);
var fri = new Weekday('Friday', 14);
var sat = new Weekday('Saturday', 14 );
var sun = new Weekday('Sunday', 0);
var weekDays = [mon, tue, wed, thu, fri, sat, sun];
function mostPopularDays(week) {
week.sort(compare);
var mostPopularDay = [];
var mostPopularDayValue = week[0].traffic;
week.forEach(day => {
if(day.traffic == mostPopularDayValue){
mostPopularDay.push(day.name);
}
});
if(mostPopularDay.length>1){
console.log('The most popular days are: '+ mostPopularDay);
} else{
console.log('The most popular day is '+ mostPopularDay);
}
}
function compare(a,b) {
if (a.traffic < b.traffic)
return 1;
if (a.traffic > b.traffic)
return -1;
return 0;
}
function Weekday (name, traffic) {
this.name = name;
this.traffic = traffic;
}
mostPopularDays(weekDays);
This is easy and you can understand quickly.
function mostPopularDays(week) {
if(week.length === 0){
return null;
}
var maxArray = [];
var max = '';
for(i=0; i < week.length; i++){
if(week[i].traffic === max){
maxArray.push(week[i].name);
}else if(week[i].traffic > max){
maxArray = [];
maxArray.push(week[i].name);
max = week[i].traffic;
};
}
if(maxArray.length === 1){
return maxArray[0];
} else {
return maxArray;
}
}

Find the next closest date in MM/DD/YYYY format JavaScript

I have an array of dates formatted as MM/DD/YYYY. I need to find the next closest date in the future starting from today. Say today was 1/22/2016 then 2/19/2016 would return.
2/3/2015
7/5/2015
1/21/2016
2/19/2016
7/1/2016
I've tried doing substrings to get the month, day, year separate and attempting a sort based off those values but surely there has to be a better way.
There is no need for a sorting algorithm. You only need to iterate once and find the closest date that is greater or equals today.
Pseudocode
closest <- infinity
foreach date in dates:
if (date >= now and date < closest) then
closest <- d
return closest
JavaScript
const dates = [
'2/3/2035',
'7/5/2035',
'1/21/2036',
'2/19/2036',
'7/1/2036',
'10/22/2039',
'08/12/2039',
];
const now = new Date();
let closest = Infinity;
dates.forEach(function(d) {
const date = new Date(d);
if (date >= now && (date < new Date(closest) || date < closest)) {
closest = d;
}
});
console.log(closest);
Personally I would use a library such as the very good Moment.JS library, to handle all the horrible complexity of dates.
It has a difference method:
http://momentjs.com/docs/#/displaying/difference/
e.g.
var a = moment([2007, 0, 29]);
var b = moment([2007, 0, 28]);
a.diff(b) // 86400000
It would then be trivial to Math.min() the differences of each date in your list.
There's also a moment.min, which might shortcut this entirely, if all your dates are in the future already:
http://momentjs.com/docs/#/get-set/min/
A naïve implementation would be to parse each date as a string and sort them in ascending order. Then, remove any dates that are in the past, and get the first child of the array of remaining dates. See this jsbin example:
var dates = [
'2/3/2015',
'7/5/2015',
'1/21/2016',
'2/19/2016',
'7/1/2016'
];
// parse each string as a Date object and sort them in ascending order
function sortDates(dates) {
return dates.map(function(date) {
return new Date(date).getTime();
}).sort(function(a, b) {
return a - b;
});
}
var orderedDates = sortDates(dates);
// remove any dates in the past, and get the first child of the array of remaining dates
var nextDate = orderedDates.filter(function(date) {
return (Date.now() - date) > 0;
})[0];
Keep in mind that this depends on the format of the date string that you pass to the Date object (in other words, is 1/12/2015 January 12th, or December 1st? JavaScript will parse it as January 12th.
You can use while loop, new Date()
var dates = ["2/3/2015","7/5/2015","1/21/2016","2/19/2016","7/1/2016"]
, d = "1/22/2016", n = -1, res = null;
while (++n < dates.length && new Date(dates[n]) < new Date(d));
res = dates[n] || d;
console.log(res)
Lots of answers, one more can't hurt.
Date strings should always be manually parsed. A library can help, but if you only have a single format, a simple function is all that's required.
The following uses reduce to loop over the array of dates and finds the closest future date. If no date is in the future, it returns null.
The returned value is the string from the array, not a Date.
function parseMDY(s) {
var b = (s || '').split(/\D/);
return new Date(b[2], b[0]-1, b[1])
}
function getClosestDateToToday(arr) {
var now = new Date();
now.setHours(23,59,59);
return arr.reduce(function (acc, s) {
var d = parseMDY(s);
return d < now? acc : (acc && d > parseMDY(acc)? acc : s);
}, null);
}
var dates = ['2/3/2015', '7/5/2015','1/21/2016',
'2/19/2016','7/1/2016'];
document.write(getClosestDateToToday(dates));
This really depends upon your dates and data structures (the ones shown in original example are not so great for me).
From the other answers...
To take the example from Josh, you could also keep a pointer to which date you are using, or simply shift off of a sorted queue of dates to make it work, but it's really adding noise to your code, disrupting the purpose.
Frederik.L answer is really beautiful code, but it would still have to be executed multiple times, so I cannot recommend it.
Feedback warning
I've been given feedback in comments that Date.parse can behave inconsistently. I'll move to passing a date parsing callback function, and demonstrate Date.UTC usage in the callback for OP-specific date format. Please be careful when defining your own callbacks, and please do not copy-paste.
Suggestion
I'd suggest utilizing Date functions i.e. Date.parse; but also try where possible to get data sources sorted without needing application-level sorting. Then you can store-once and step through the array using array.shift() or similar;
Ideally also YYYY-MM-DD
Four-Digit Year
Two-Digit Month
Two-Digit Day
... (continue from least occurring to most occurring)
sample code
var dates = [
'2/3/2015',
'7/5/2015',
'7/1/2016',
'1/21/2016',
'2/19/2016'
]; // unsorted garbage dates
var DateList = function( dateList, getDate ) {
var sortedDates = dateList.sort( function(a, b) {
return getDate(a) - getDate(b);
});
this.next = function() {
var dt = sortedDates.shift();
sortedDates.push(dt); // comment to remove cyclical nature
return dt;
}
};
// specific implementation parser for this format
var getDisgustingDateFormat = function(dStr) {
var dParts = dStr.split('/');
return new Date(Date.UTC(dParts[2],dParts[0],dParts[1]));
};
var dl = new DateList( dates, getDisgustingDateFormat );
Usage
dl.next(); // "2/3/2015"
dl.next(); // "7/5/2015"
dl.next(); // "1/21/2016"
dl.next(); // "2/19/2016"
dl.next(); // "7/1/2016"
dl.next(); // "2/3/2015"
Hope this helps (Updated for clarity)
What about this version using for of and momentjs:
const getClosestFutureDate = (dates) => {
if (dates.length === 0) {
return null;
}
let minDiff = 0;
for (const date of dates) {
minDiff += minDiff + 30;
var currentDate = moment(date);
if (currentDate.isAfter(moment()) && currentDate.diff(moment(), "days") <= minDiff) {
break;
}
}
return currentDate;
};
Assuming now = 2019-08-21
console.log(getClosestFutureDate(["2019-05-07", "2019-06-01", "2019-07-13", "2019-11-09", "2019-11-10", "2019-11-11"]));
// 2019-11-09
I am fan of momentjs, but this can be easily refactored to use only vanilla Date.
const FindDate = (date, allDate) => {
// moment().diff only works on moment(). Make sure both date and elements in allDate list is in moment
let nearestDate = -1;
allDate.some(d => {
const currentDate = moment(d)
const difference = currentDate.diff(date); // Or date.diff(currentDate) depending on what you're trying to find
if(difference >= 0){
nearestDate = d
}
});
console.log(nearestDate)
}
In Livescript:
x =
* "2/3/2015"
* "7/5/2015"
* "1/21/2016"
* "2/19/2016"
* "7/1/2016"
sim-unix-ts = (date-str) ->
# Simulate unix timestamp like concatenating
# convert "MM/DD/YYYY" to YYYYMMDD (integer)
# so we can simply compare these integers
[MM, DD, YYYY] = date-str.split "/"
MM = "0#{MM}".slice -2 # apply zero padding
DD = "0#{DD}".slice -2 # apply zero padding
parse-int "#{YYYY}#{MM}#{DD}"
today = sim-unix-ts "2/18/2016"
date-list = [sim-unix-ts(..) for x]
# find next date
next-dates = [.. for date-list when .. > today]
next-date = next-dates.0
next-date-orig = x[date-list.index-of next-date]
alert [next-date, next-date-orig]
..in Javascript:
var x, simUnixTs, today, dateList, res$, i$, x$, len$, nextDates, y$, nextDate, nextDateOrig;
x = ["2/3/2015", "7/5/2015", "1/21/2016", "2/19/2016", "7/1/2016"];
simUnixTs = function(dateStr){
var ref$, MM, DD, YYYY;
ref$ = dateStr.toString().split("/"), MM = ref$[0], DD = ref$[1], YYYY = ref$[2];
MM = ("0" + MM).slice(-2);
DD = ("0" + DD).slice(-2);
return parseInt(YYYY + "" + MM + DD);
};
today = simUnixTs("2/18/2016");
res$ = [];
for (i$ = 0, len$ = x.length; i$ < len$; ++i$) {
x$ = x[i$];
res$.push(simUnixTs(x$));
}
dateList = res$;
res$ = [];
for (i$ = 0, len$ = dateList.length; i$ < len$; ++i$) {
y$ = dateList[i$];
if (y$ > today) {
res$.push(y$);
}
}
nextDates = res$;
nextDate = nextDates[0];
nextDateOrig = x[dateList.indexOf(nextDate)];
alert([nextDate, nextDateOrig]);

Sort object array by hour

I have an array of objects with an hour(fc_start_time) property and I want to sort it by this property. I've tried this but it does not work for me.
This is the object structure:
Object {
id="540-events",
local_id=540,
title="Mas Flow",
fc_start_time="12:30 pm"
},
Object {
id="531-events",
local_id=531,
title="Slowly",
fc_start_time="04:30 pm"
},
Object {
id="531-events",
local_id=531,
title="Slowly",
fc_start_time="08:30 am"
}
Thanks in advance.
Dates and time, eh? I hate them. Let's try to figure this out.
How you sort an array? With help of array's sort method. By default this method sorts strings, but we need custom compare function here.
How can we compare time in strings? We can use Date object, parse time, get milliseconds from 1970, and compare them. But we have am-pm format here. So, to use Date.parse method, we need to convert time to 24 hour format first (or use Date.js library).
function convertTo24Hour(time) {
var hours = parseInt(time.substr(0, 2));
if(time.indexOf('am') != -1 && hours == 12) {
time = time.replace('12', '0');
}
if(time.indexOf('pm') != -1 && hours < 12) {
time = time.replace(hours, (hours + 12));
}
return time.replace(/(am|pm)/, '');
}
After we get 24h time, we can parse it like so (don't look at date before time, it doesn't matter, all we care about is time):
Date.parse( '9/19/2014 ' + convertTo24Hour(time) );
Now we can use this in array.sort compare function. We just compare two numbers, 1411129800000 ? 1411132800000, decide which one is bigger and sort array.
function compare(a,b) {
var atime = Date.parse('9/19/2014 ' + convertTo24Hour(a.time));
var btime = Date.parse('9/19/2014 ' + convertTo24Hour(b.time));
if (atime < btime) {
return -1;
}
if (atime > btime) {
return 1;
}
return 0;
}
What we got after all:
Use array.sort compare function to sort elements
Convert time to number so we can correctly compare them
To do so, convert 12h time format to 24 and use Date.parse
Here is jsfiddle to play with - http://jsfiddle.net/rqgmkdbs/
Try this compare function according to the same time input as your example. It compares on the Floating notation of you time value.
<script>
var objs = [
{id:"540-events",local_id:540,title:"Mas Flow",fc_start_time:"12:30 pm"},
{id:"540-events",local_id:540,title:"Mas Flow",fc_start_time:"10:30 pm"},
{id:"540-events",local_id:540,title:"Mas Flow",fc_start_time:"12:30 pm"},
{id:"540-events",local_id:540,title:"Mas Flow",fc_start_time:"14:30 pm"},
{id:"540-events",local_id:540,title:"Mas Flow",fc_start_time:"09:30 pm"}
]
function compare(a,b) {
var time1 = parseFloat(a.fc_start_time.replace(':','.').replace(/[^\d.-]/g, ''));
var time2 = parseFloat(b.fc_start_time.replace(':','.').replace(/[^\d.-]/g, ''));
if(a.fc_start_time.match(/.*pm/)) time1 += 12; if(b.fc_start_time.match(/.*pm/)) time2 += 12;
if (time1 < time2) return -1;
if (time1 > time2) return 1;
return 0;
}
objs.sort(compare);
console.log(objs);
</script>
var input = [{hour:1, minutes:10},{hour:4, minutes: 1}, ...];
input.sort(function (a, b)
{
// compare hours first
if (a.hour < b.hour) return -1;
if (a.hour > b.hour) return 1;
// else a.hour === b.hour, so compare minutes to break the tie
if (a.minute < b.minute) return -1;
if (a.minute > b.minute) return 1;
// couldn't break the tie
return 0;
});
Try this. You have to consider am and pm in your time.
<!doctype html>
</html>
<head>
<meta charset="utf-8">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
// The data
var data = [
{ id:"540-events", local_id:540, title:"Mas Flow", fc_start_time:"12:30 pm"},
{ id:"531-events", local_id:531, title:"Slowly", fc_start_time:"04:30 pm"},
{ id:"545-events", local_id:545, title:"Mas Flow 2", fc_start_time:"03:30 am"}
]
// Sort values
data.sort(function(a,b){
var aValue = new Number(a.fc_start_time.replace(/\d*/g,""));
var bValue = new Number(b.fc_start_time.replace(/\d*/g,""));
if( aTime.match(/.*pm/) ){
aValue + 12;
}
return aValue - bValue;
});
// Show values
for( var i = 0; i < data.length; i++){
$("ul").append("<li>"+data[i].fc_start_time+"</li>");
}
});
</script>
</head>
<body>
<ul>
</ul>
</body>
</html>

Categories

Resources