JavaScript sorting on date (but not the "usual" way) - javascript

I'm trying to sort a JS array, but in a different fashion. Here's my scenario:
Say we have the following dates in the array (these will be each item's expiryDate)
1. 2015/09/23
2. 2015/10/10
3. 2015/07/05
4. 2015/07/24
And the current date is 2015/07/04
And we select 2015/09 (which is vm.sortModel in the example) as the sorting date
The display order must be as follows -
3.
1.
4.
2.
Here's what I have so far, but it's obviously not working...
for (var i = 0; i < vm.tableData.length; i++) {
var entity = vm.tableData[i];
entity.items.sort(function(a, b) {
if (a.expiresThisWeek() < b.expiresThisWeek()) {
return 1;
}
//Now check for stuff in months AFTER the selected year/month combo
if (vm.sortModel) {
var tmp = vm.sortModel.split('/');
var currentDateSelection = new Date(tmp[0], tmp[1]);
if (a.getExpiryDateObject() >= currentDateSelection) {
return 1;
} else {
return -1;
}
}
if (a.getExpiryDateObject() < b.getExpiryDateObject()) {
return -1;
} else if (a.getExpiryDateObject() > b.getExpiryDateObject()) {
return 1;
}
return 0;
});
}
Basically, if an item expires in this week, it must be at the top of the table, then we should list all the items in the "selected month", then all the months AFTER that month, and then only the months before that.
Very strange, I know, but business gets what business wants.
Thanks for any help!
EDIT
Here's the expiresThisWeek method
model.expiresThisWeek = function() {
var todayDate = new Date();
//We want to check if the item expires within 7 days from today
var endDate = new Date(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate() + 7);
var date = model.getExpiryDateObject();
return todayDate < date && date < endDate;
}

Related

How to increment months using the Temporal API

I am creating a calendar in Angular that has a previous & next month button that currently displays the correct data of that month when I press either the next or previous button only once. The question that I have is how can I increment the months when clicking on either the previous or next button. I have looked at Temporal's Documentation a good bit but I still am confused on how to simply increment the months. Here is some of the code I have so far. Any help would be greatly appreciated!
currentMonth = Temporal.Now.plainDateISO();
nextMonth = this.currentMonth.add({ months: 1 });
previousMonth = this.currentMonth.subtract({ months: 1 });
daysInCurrentMonth = this.currentMonth.daysInMonth;
daysInNextMonth = this.nextMonth.daysInMonth;
daysInPreviousMonth = this.previousMonth.daysInMonth;
onStartMonth() {
for (let i = 1; i <= this.daysInCurrentMonth; i++) {
let div = this.calendarData.nativeElement;
let calendarDates = this.renderer.createElement('div');
this.add(calendarDates, 'dates');
this.set(calendarDates, 'innerText', i);
this.append(div, calendarDates);
}
}
onNextMonth() {
for (let i = 1; i <= this.daysInNextMonth; i++) {
let div = this.calendarData.nativeElement;
let calendarDates = this.renderer.createElement('div');
this.add(calendarDates, 'dates');
this.set(calendarDates, 'innerText', i);
this.append(div, calendarDates);
}
}
onPreviousMonth() {
for (let i = 1; i <= this.daysInPreviousMonth; i++) {
let div = this.calendarData.nativeElement;
let calendarDates = this.renderer.createElement('div');
this.add(calendarDates, 'dates');
this.set(calendarDates, 'innerText', i);
this.append(div, calendarDates);
}
}
Your comment: "Since the current month is August; when I press the next month button, I always get September, likewise when I press the previous month I always get July"
From that comment, your issue is not with the Temporal API. The problem is that you've essentially hard-coded the current, next and previous months when you should probably be updating these dynamically (as well as the respective days in month. When you press the next button you should update current month to be the next month and then recalcuate daysInCurrentMonth.
currentMonth = Temporal.Now.plainDateISO();
// Reset to this month
onStartMonth() {
this.currentMonth = Temporal.Now.plainDateISO();
renderCalendar();
}
// move to next month
onNextMonth() {
this.currentMonth = this.currentMonth.add({ months: 1 });
renderCalendar();
}
// move previous month
onPreviousMonth() {
this.currentMonth = this.currentMonth.subtract({ months: 1 });
renderCalendar();
}
// Render the calendar
renderCalendar(){
const daysInCurrentMonth = this.currentMonth.daysInMonth;
const div = this.calendarData.nativeElement;
for (let i = 1; i <= daysInCurrentMonth; i++) {
let calendarDates = this.renderer.createElement('div');
this.add(calendarDates, 'dates');
this.set(calendarDates, 'innerText', i);
this.append(div, calendarDates);
}
}
You now only care about the current tracked month and can easily navigate forward or backward any number of times. Your rendering got much simpler too as any changes you need to make can be made in that 1 function without having to be replicated multiple times.
If you still need next and previous month info (incl days in months) then you should probably recalculate these as well when current month changes.

Getting a variable from a list of div inside for loop to onClick()

i am trying to make a calendar and simply select a day (which is a ) to change its css class, having a reactjs class based component with daySelected as a state prop.
inside createCalendar() i get the day number using an indicator (date) and i increment it inside the for loop, having onClick() to pass the date to handleClick(date).
When i select any day i always get the last day as selected.
I want to have pass the variable date to handelClick(date) from the selected day, please suggest any solution.
ps : i need to make everthing inside a single component to control the state prop daySelected
handleClick = day => {
this.setState(state => ({
checked: !state.checked,
daySelected: day
}));
};
createCalendar(currentMonth, currentYear) {
let firstDay = new Date(currentYear, currentMonth).getDay();
let daysInMonth =
32 - new Date(currentYear, currentMonth, 32).getDate() - 1;
var days = [];
let date = 0;
for (let i = 0; i < 5; i++) {
for (let j = 0; j < 7; j++) {
if (i === 0 && j < firstDay) {
var x = (
<div className={"Day"}>
<p> </p>
</div>
);
} else if (date > daysInMonth) {
break;
} else {
date++;
var x = (
// I want to get the variable date from here
<div
value={date}
onClick={() => this.handleClick(date)}
className={this.state.daySelected == date ? "Day-checked" : "Day"}
>
<p>{date}</p>
</div>
);
}
days.push(x);
}
}
return days;
}
You're overwritting a x value in a loop (using one reference), you should use a function.
Just convert subcomponent definition to a function, sth like const x = (date) => {... and use it in a loop.

Changing the value of an object based on the time of day?

I'm creating a project that is a player attendance log. Every player is an object I created using class syntax and in theory the values of the object should change based on the time of day. This doesn't work because the values are either true or false regardless of what time of day it is. What is going wrong and how can I fix it? here's a link to my project https://github.com/bloodwolf616/project9
Problem code:
const today = new Date();
const hour = today.getHours();
const second = today.getSeconds();
for (let i = 0; i < attendance.length; i++){
if (hour > 10 && hour < 20) {
if(player1 && player2 && player3 && player4) {attendance[i]._online = true;}
} else {
attendance[i]._online = false;
}
if (second > 20 || second < 40) {
if(error) {
attendance[i]._online = true;}
} else {
attendance[i]._online = false;
}

Calculate unique time given multiple start and end dates

If you have an array of appointments with start and end dates how do you calculate the unique time for all of the appointments?
Example:
var appointments = {
0:{"start":"2015-01-20 09:00:00","end":"2015-01-20 09:30:00"},
1:{"start":"2015-01-20 09:15:00","end":"2015-01-20 09:42:22"},
2:{"start":"2015-01-20 10:00:00","end":"2015-01-20 10:25:00"},
3:{"start":"2015-01-20 10:10:00","end":"2015-01-20 10:53:00"}
}
So in this example I would want to get a unique time (activity) value of 1H 35M 22S.
Anyone know any formulas for this?
So far I have this, seems to work but I think dates have to be sorted by start time. Is this the most efficient way to calculate this?:
var totalElapsedAppointmentSeconds = 0;
var lastActiveTimestamp;
for (i in appointments) {
if (totalElapsedAppointmentSeconds == 0) {
totalElapsedAppointmentSeconds = new Date(appointments[i].end) - new Date(appointments[i].start);
lastActiveTimestamp = new Date(appointments[i].end);
} else {
if (new Date(appointments[i].start) < lastActiveTimestamp) {
if (new Date(appointments[i].end) > lastActiveTimestamp) {
totalElapsedAppointmentSeconds += new Date(appointments[i].end) - lastActiveTimestamp;
lastActiveTimestamp = new Date(appointments[i].end);
} else {
//nothing, already completely accounted for
}
} else {
totalElapsedAppointmentSeconds += new Date(appointments[i].end) - new Date(appointments[i].start);
lastActiveTimestamp = new Date(appointments[i].end);
}
}
}
totalElapsedAppointmentSeconds = totalElapsedAppointmentSeconds/1000;
var totalElapsedTime = Math.floor(totalElapsedAppointmentSeconds / 3600) + "H " + Math.floor((totalElapsedAppointmentSeconds % 3600)/60) + "M " + (totalElapsedAppointmentSeconds % 3600) % 60 + "S";
console.log("totalElapsedTime",totalElapsedTime);
unclear what you are asking but this demonstrates calculating a time difference
EDIT whoops javascript says these are invalid dates, where did they come from?
moment.js is a good option to parse them if you must use these as inputs
var data = {
"appointments": {
0:{"start":"2015-01-20 09:00:00","end":"2015-01-20 09:30:00"},
1:{"start":"20-01-2015 09:15:00","end":"20-01-2015 09:42:22"},
2:{"start":"20-01-2015 10:00:00","end":"20-01-2015 10:25:00"},
3:{"start":"20-01-2015 10:10:00","end":"20-01-2015 10:53:00"},
}
}
function secondsDifference(ts1, ts2){
startMs = new Date(ts1).valueOf();
endMs = new Date(ts2).valueOf();
deltaMs = endMs - startMs;
deltaS = deltaMs /1000;
deltaS = Math.floor(deltaS);
return deltaS;
}
var a = data.appointments[0];
var result = secondsDifference(a.start, a.end);
console.log('first appointment length seconds:', result)

JavaScript Rental Date Logic

So, basically I'm building a rental form where you have three basic dropdowns for Month, Day, Year for a "rent from" and then another three for "rent till."
That's easy enough and I've even got decent leap year support and such. The issue comes with generating the "rent till" based on the "rent from." I'd like the "rent till" to show only the next five days in a dropdown afterwords and I'm having serious difficulty working out logic to do it efficiently.
Also, the range is variable, so I'm trying to work a function in that takes a 'length of rental' parameter to effect the changes. The code also uses reference points. So that the pick up dropdowns are "pick_up_day", "pick_up_month" etc. This is to try to make the code portable to multiple projects with consistently ID'd HTML elements.
Here's my basic logic and what I've got so far:
This is the code that sets up the from-dates and such.
function populate_dates(identifier) {
"use strict";
var i, currentday, node, textbox, maxdays;
while (document.getElementById(identifier + "days").hasChildNodes()) {
document.getElementById(identifier + "days").removeChild(document.getElementById(identifier + "days").firstChild);
}
currentday = new Date();
switch (parseInt(document.getElementById(identifier + "month").value, 10)) {
case 2:
if (new Date(currentday.getFullYear(), 1, 29).getDate() === 29) {
maxdays = 29;
} else {
maxdays = 28;
}
break;
case 9:
case 4:
case 6:
case 11:
maxdays = 30;
break;
default:
maxdays = 31;
break;
}
for (i = 1; i <= maxdays; i = i + 1) {
node = document.createElement("option");
textbox = document.createTextNode(i);
node.value = i;
node.appendChild(textbox);
document.getElementById(identifier + "days").appendChild(node);
}
}
window.onload = function() {
"use strict";
var currentday, i, node, textbox;
currentday = new Date();
for (i = 0; i <= 1; i = i + 1) {
node = document.createElement("option");
textbox = document.createTextNode(currentday.getFullYear() + i);
node.value = currentday.getFullYear() + i;
node.appendChild(textbox);
document.getElementById("pick_up_year").appendChild(node);
}
document.getElementById("pick_up_month").onchange = function () {
populate_dates("pick_up_");
};
populate_dates("pick_up_");
};
Now for the logic regarding the 'till' date I have worked out some pseudocode like this, but it seems overly complex for such a simple task:
function a(referencer, ref1, ref2, rentlength) {
//Make datetime object out of ref1's current date;
datetime.setDays(datetime.getDate() + rentlength)
for (i = 0; i <= rentlength; i = i + 1) {
datetime.setDays(datetime.getDate() + i);
outmatrix[outmatrix.length] = [getDates, getMonth, getYear];
}
outmatrix.removeduplicates;
date_generator(ref2, outmatrix)
}
function date_generator(referencer, inputmatrix) {
Clean up referencer
Loop through, create nodes based on array[y+1][x];
}
Is there a better way to do this that I'm just not seeing? What is a good way to turn a Datetime object into three dropdowns while removing duplicates? Is there a better way to handle this than the way I am currently?
In terms of the logic, you'll need to set the date to the sum of the start date and the rental time, in DATE format.

Categories