Calculate unique time given multiple start and end dates - javascript

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)

Related

I am trying to loop though api data for tide Hight in a set time frame and find all the data for each day of the month

for (let i = 1; i < data.values.length; i++) {
TimeStart = data.values[i].time;
HightStart = data.values[i].value;
TimeEnd = data.values[i].time;
HightEnd = data.values[i].value;
if (TimeStart.slice(11, 16) == start) {
Date = TimeStart.slice(0, 10);
TimeStart = TimeStart.slice(11, 16);
tidedata1.innerHTML = `${TimeStart} - ${HightStart}m`;
tidedata1Full.innerHTML = `${TimeStart}am - ${HightStart}m`;
}
if (TimeEnd.slice(11, 16) == end) {
Date = TimeEnd.slice(0, 10);
TimeEnd = TimeEnd.slice(11, 16);
tidedata2.innerHTML = `${TimeEnd} - ${HightEnd}m`;
tidedata2Full.innerHTML = `${TimeEnd}pm - ${HightEnd}m`;
}
}
if (i < day) {
square.classList.add("disabled");
}
square2.append(tidedata1Full, tidedata2Full);
square.append(monthNum, tidedata1, tidedata2, square2);
inner_grid.append(square);
}
});
calendar.append(month, inner_grid);
At the moment it will get the correct data but only for one day and then it just repeats that same data over all of the days.
the data structure look like
Using a for-each loop to go over every point of data in the array.
And then append the data to where it needs to go. In this case to the calendar and its divs.
lowHigh.forEach(d =>{
let wDate = new Date(d.time).getUTCDate();
let wHour = 6;
let eHour = 18;
wHour = ("0" + wHour).slice(-2);
let wMintue = new Date(d.time).getUTCMinutes();
wMintue = ("0" + wHour).slice(-2);
if(wDate == i+1)
{
if(tidedata1.innerHTML == "")
{
tidedata1.innerHTML = `${wHour}:${wMintue} - ${d.value}m`
tidedata1Full.innerHTML = `${wHour}:${wMintue}am - ${d.value}m`
}
else
{
tidedata2.innerHTML = `${eHour}:${wMintue} - ${d.value}m`
tidedata2Full.innerHTML = `${eHour}:${wMintue}pm - ${d.value}m`
}
}
})
if(i < day)
{
square.classList.add("disabled");
}
square2.append(tidedata1Full, tidedata2Full)
square.append(monthNum,tidedata1,tidedata2, square2);
inner_grid.append(square);
}
})

Increase a number based on Date or Interval javascript (and keep it after refresh page)

I'm struggling for while trying to figure out how to increase a number based on a Date or based on a time (Using setInterval).
I don't know which option is easier. I made it by using setInterval:
HTML
<p class="counter"></p>
JS
let tickets = 35000;
const counter = document.querySelector('.counter');
let interval = setInterval(function(){
console.log(tickets);
if (tickets >= 60000) {
var textSoldOut = `<p>¡Todo vendido!</p>`;
counter.innerHTML = textSoldOut;
console.log("Sold out");
clearInterval(interval);
}else{
var text = `¡${tickets} tickets Sold!`;
contador.innerHTML = text;
console.log(text)
}
const random = Math.floor(Math.random()*(200-100+1)+100);
tickets += random;
}, 10000);
The thing is every time the page is refreshed the counter starts from 35000 again. I am trying to figure out how to storage the var tickets. I guess this would be made by using localStorage, but since I am a beginner in JS, I am not able to do it.
Other option would be by checking the date, and based on that, show a number:
function date() {
var d = new Date();
var month = d.getMonth();
var day = d.getDate();
const counter = document.querySelector('.contador');
const random = Math.floor(Math.random()*(200-100+1)+100);
for (let i = 350000; i <= 60000 ; i++) {
if (month == 0 & day == 28) {
var sum = i + random;
document.getElementById("contador").innerHTML = suma;
}else if (mes == 0 & dia == 30) {
...
} else if (...){
...
}
}
document.getElementById("dia").innerHTML = dia;
document.getElementById("mes").innerHTML = mes;
}
fecha();
Could someone help me out to reach the result?
I would really appreciate it
The Storage object accessible via the localStorage property offers two methods to save or retrieve data: setItem and getItem().
Usage is quite simple. If you want to save the numbers of tickets into a myTickets key on localStorage you have to do it like this:
localStorage.setItem("myTickets", tickets);
To retrieve that data later on:
localStorage.getItem("myTickets");
You just have to make sure to update the myTickets key on localStorage as you increase the number of tickets inside the setinterval callback function.
let tickets = 35000;
if (localStorage.getItem("myTickets") == null) {
localStorage.setItem("myTickets", tickets);
} else {
tickets = localStorage.getItem("myTickets");
}
const counter = document.querySelector('.counter');
let interval = setInterval(function() {
console.log(tickets);
if (tickets >= 60000) {
var textSoldOut = `<p>¡Todo vendido!</p>`;
counter.innerHTML = textSoldOut;
console.log("Sold out");
clearInterval(interval);
} else {
var text = `¡${tickets} tickets Sold!`;
console.log(text)
}
const random = Math.floor(Math.random() * (200 - 100 + 1) + 100);
tickets += random;
localStorage.setItem("myTickets", tickets);
}, 10000);

How to filter array of dates by date range?

I have an array of objects. Each object contains a Date attribute.
I need to return an array of objects with date attributes. however, objects that have date attributes that are consecutive days (1 day apart), need to be within their own array.
example input:
const inputArray = [ObjectwDate, ObjectwDate, ObjectwDate, ObjectwDate, ObjectwDate, ObjectwDate, ObjectwDate, ObjectwDate];
example expected output:
// example output
const finalArray = [ObjectwDate, ObjectwDate, [ObjectwDate, ObjectwDate, ObjectwDate], ObjectwDate, [ObjectwDate, ObjectwDate]];
I'm really lost on how to get this to work in all cases. So far I have something similar to the following:
const rangeArray = [];
const finalArray = [];
// sort input array for oldest date
const format = inputArray.sort((a, b) => (
new Date(a.date) - new Date(b.date)
));
format.sort((aDate, bDate) => {
if (differenceInDays(bDate.date, aDate.date) === 1) {
rangeArray.push(aDate, bDate);
}
finalArray .push(bDate);
});
I feel as though this is not the most efficient way to solve my problem. I'm wondering if there is a better way to loop through the array, and put all objects with consecutive dates in their own array.
Any help would be appreciated.
EDIT:
I am using date-fns to calculate the difference in days:
https://date-fns.org/v1.29.0/docs/differenceInDays
After you sor your array, it should be fairly straight foward from there. Iterate through and push consecutives into an array. When you encounter a non-consec, push the current array into an array and start with a new one. If the array that you're pushing has a length of one, just push the item inside. Will provide sample code shortly
UPDATE:
Something along these lines, but still have to do something for the very last value, because there is no i + 1. The code below isn't functional :D
function GroupConsecutiveDates(arrayOfDates)
{
let outerArray = [];
let innerArray = [];
for(let i = 1; i < arrayOfDates.length; i++)
{
let currentDate = arrayOfDates[i];
let nextDate = arrayOfDates[i + 1];
let dateDifference = currentDate - nextDate;
if(dateDifference > 1)
{
switch(innerArray.length)
{
case 0:
break;
case 1:
outerArray.push(innerArray[0]);
default:
outerArray.push(innerArray);
}
innerArray = [currentDate];
continue;
}
innerArray.push(currentDate);
}
function randomDate(start, end) {
return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
}
let dates = [];
for (let i = 0; i < 20; i++)
{
dates.push(randomDate(new Date(2018, 1, 5), new Date()));
}
dates = dates.sort((a, b) => a - b);
function GetDateDifference(date1, date2)
{
var timeDiff = Math.abs(date2.getTime() - date1.getTime());
var diffDays = Math.ceil(timeDiff / (1000 * 3600 * 24));
return diffDays;
}
function CollectNearDates(arr)
{
if(arr.length <= 1) return arr
let outer = [];
let inner = [arr[0]];
let previousDate = inner[0];
for(let i = 1; i < arr.length; i++)
{
let currentDate = dates[i];
let difference = GetDateDifference(previousDate, currentDate);
if(difference <= 1)
{
inner.push(previousDate);
previousDate = currentDate;
continue;
}
switch(inner.length)
{
case 0:
break;
case 1:
outer.push(inner[0]);
break;
default:
outer.push(inner);
}
previousDate = currentDate;
inner = [currentDate]
}
if(inner.length === 1) outer.push(previousDate);
else inner.push(previousDate);
return outer;
}
console.log(CollectNearDates(dates))

Generate "Unique" 5 digits ID with javascript (99999 combinations) in random order

I want to generate an Unique 5 digits ID + 784 at the begining, the constraint, I can execute the script only one time, and I have to avoid the first 100 numbers so It can't be 00100 and lower. Since I use timestamp and I can execute only my script one time how I can handle this ?
I did this it's maybe dumb but at least I tried.
ConcatedID();
function ConcatedID()
{
var uniqID = checkProtectedRange();
if (checkProtectedRange())
{
var BarcodeID = 784 + uniqID;
return BarcodeID;
}
else
checkProtectedRange();
}
function checkProtectedRange()
{
var uniqueID = GenerateUniqueID();
var checkRange = uniqueID.substr(uniqueID.length - 3);
var checkRangeINT = parseInt(checkRange);
if (checkRangeINT <= 100)
return (false);
else
return (true);
}
function GenerateUniqueID()
{
var lengthID = 5;
var timestamp = + new Date();
var ts = timestamp.toString();
var parts = ts.split("").reverse();
var id = "";
var min = 0;
var max = parts.length -1;
for (var i = 0; i < lengthID; ++i)
{
var index = Math.floor(Math.random() * (max - min + 1)) + min;
id += parts[index];
}
gs.log('Generate ID ' + id);
return id;
}
Without being able to track previously used IDs, you're left with chance to prevent duplicates. Your shenanigans with Date doesn't really change that. See the birthday problem.
Given that, just follow the most straight-forward method: Generate a random string consisting of five digits.
function GenerateUniqueID() {
return ('0000'+(Math.random() * (100000 - 101) + 101)|0).slice(-5);
}
Or, if you want just the final integer with constraints applied:
function GenerateUniqueID() {
return (Math.random() * (78500000 - 78400101) + 78400101)|0;
}

Javascript Refactoring Assistance Needed

I've programmed this code (javascript countdown) and I have to put 141 of them on page. Doese anybody know if there is some way(program, script etc) that will do the following:
Change from function cdtd1 to function cdtd2 and var sad1 = new Date(); to var sad2 = new Date(); etc.
var d = new Date();
var n = d.getDay();
if(n == 1 || n == 2 || n == 3 || n == 4 || n == 5){
var timer1;
function cdtd1() {
var sad1 = new Date();
var dolazak1 = new Date(sad1.getFullYear(),sad1.getMonth(),sad1.getDate(),23,00,00);
var timeDiff1 = dolazak1.getTime() - sad1.getTime();
if (timeDiff1 <= 0) {
clearInterval(timer1);
$('#dani1Box').remove();
$('#sati1Box').remove();
$('#minute1Box').remove();
$('#sekunde1Box').remove();
}
var sekunde1 = Math.floor(timeDiff1 / 1000);
var minute1 = Math.floor(sekunde1 / 60);
var sati1 = Math.floor(minute1 / 60);
var dani1 = Math.floor(sati1 / 24);
sati1 %= 24;
minute1 %= 60;
sekunde1 %= 60;
$("#dani1Box").html(dani1);
$("#sati1Box").html('7-Dubrava ' + sati1 + ':');
$("#minute1Box").html(minute1 + ':');
$("#sekunde1Box").html(sekunde1);
timer1 = setTimeout(cdtd1, 1000);
}
$(document).ready(function() {
cdtd1();
});
}
I believe what you are looking for is a javscript looping operation.
for(var i = 1; i <= 141; i++) {
console.log(i);
// put code in here that has to run 141 times modifying the html target elements by using string concatenation
$('#target' + i); // This would be come #target1, #target2, #target3 etc up to 141
}
You ask specifically about the variable renaming which would not be necessary in this case since you are reusing the variable in each pass through the loop.
Since you are working with time information you may want to check out this Javascript library: http://momentjs.com/ and work through some of the information on this specific section: http://momentjs.com/docs/#/durations/
JetBrains Webstorm has great javascript refactoring features, including renaming of objects.

Categories