Checking dates through script always coming up as zero - javascript

I have written a script in Pipedream to get the dates I put in a certain column in my Google Sheets. I want to count them to be able to determine how many time a certain date appears in that column but I still get as count 0 and I do not know where it is going wrong. I tried the 5th of February because I have it appearing 5 times in that column just to test the code but for in the future it needs to check every day how many times the date of today appears.
export default defineComponent({
async run({ steps, $ }) {
let count = 0;
let dates = steps.get_values_in_range.$return_value;
for (let date of dates) {
if (date === "02-05-2023") {
count++;
}
}
return {
count,
event: steps.trigger.event,
get_values_in_range: steps.get_values_in_range.$return_value,
};
},
});

You just need to change one line from your code.
if (date[0] === "02-05-2023") {
count++;
}

import datetime
def handler(pd):
count = 0
today = datetime.datetime.now().strftime("%d-%m-%Y")
get_values_in_range = pd.steps["get_values_in_range"]["$return_value"]
for range in get_values_in_range:
if range[0] == today:
count += 1
return {
"count": count,
"event": pd.steps["trigger"]["event"],
"get_values_in_range": get_values_in_range
}
Still thanks for the suggestions guys!

Related

How can i get the first nearest date in the past?

I have this arrays
const datesToBeChecked = ['2020-07-03','2020-07-06', '2020-07-13', '2020-07-20']
const dateToCheckFor = '2020-07-12';
I need to get the first nearest date in the past - so when the date is 2020-07-12 i need to get
2020-07-06 from datesToBeChecked.
WHAT I TRIED
I tried this code
datesToBeChecked.forEach(date => {
let diff = moment(dateToCheckFor).diff(moment(date), 'days');
console.log(diff);
if (diff > 0) {
if (nearestDate) {
if (moment(date).diff(moment(nearestDate), 'days') < 0) {
nearestDate = date;
}
} else {
nearestDate = date;
}
}
});
but that gives me the earliest date in the array - 2020-07-03. But i need the first BEFORE THE DATE I CHECK FOR
Actually your logic is almost there. You don't need the nested if conditional. In essense, what you want is to cache the difference, and compare the current difference with the cached difference. If the cached difference is smaller, then we know the current date is the nearest one. Otherwise, we continue for the search.
This solution will work even if the dates are not sorted in chronological order (oldest to newest):
const datesToBeChecked = ['2020-07-03', '2020-07-06', '2020-07-13', '2020-07-20']
const dateToCheckFor = '2020-07-12';
let nearestDate;
let cachedDiff = Infinity;
datesToBeChecked.forEach(date => {
let diff = moment(dateToCheckFor).diff(moment(date), 'days');
if (diff > 0 && diff < cachedDiff) {
cachedDiff = diff;
nearestDate = date;
}
});
console.log(nearestDate);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
The first element is the closest date in the past (at least yesterday, today results won't show up).
If empty then dateToCheckFor elements does not contain any date in past.
const mappedDates = dateToCheckFor
.map(d => moment(dateToCheckFor).diff(moment(d), 'days'))
.filter(diff => diff <= -1)
.sort()
.reverse();
You could try sorting all of the dates in a hash table first. So you would have a hash table:
{
date1: difference,
date2: difference,
...
}
then you would sort the objects values, such as here: Sorting object property by values
then take the first date from that, which is before the dateToCheckFor
I hope this is not too inefficient for you.
Here's one way with good ole vanilla js. Moment.js weighs 230+kb
const datesToBeChecked = ['2020-07-03', '2020-07-06', '2020-07-13', '2020-07-20']
const dateToCheckFor = '2020-07-12';
dateToCheckFor_d = new Date(dateToCheckFor).getTime();
let possibilities = datesToBeChecked.filter(dt => {
return (new Date(dt).getTime() < dateToCheckFor_d)
})
possibilities.sort().reverse()
console.log(possibilities[0])
In your code just update the below line
if (moment(date).diff(moment(nearestDate), 'days') < 0
to
if (moment(date).diff(moment(nearestDate), 'days') > 0

Check if date overlaps inside array JS

I have an array which contains a set of start/end date objects (time included)
i.e.
results["records"] =
[0] -[startDate,endDate]
[1] -[startDate, endDate]
I also have another two date objects stored locally as JS variables.
How do I check if these variables i.e. startDateObj && endDateObj OVERLAP with ANY record in the array, by that I mean crossover with any time between and including any start date or end date.
Thank you in advance
Initial attempt below
$(results['records']).each(function() {
console.log('end:' + this[1])
console.log('start:' + this[0])
if(startDateObj < this[1].end && endDateObj > this[0].start) {
alert('this overlaps')
}
});
EDIT: Answer added below
Have a great day!
I'm assuming this structure in your "dateArray" because to check overlaps you need to define a range of date and time.
dateArray: [{start: Date, end: Date}];
dateArray.forEach(date => {
if(startDateObj < date.end && endDateObj > date.start) {
//this is an overlap
}
});
The answer was the full date objects in the array where being treated as a string
so to convert and fix
function toDateString(date)
{
var formatedDate = new Date(date);
return formatedDate;
}
$(results['records']).each(function() {
if(startDateObj < toDateString(this[1]) && endDateObj > toDateString(this[0]))
{
//overlaps
}

How to detect 'current week' for render days conditionally?

I discovered the dayRender function today (in the v4.0.0beta4 of fullCalendar.io).
My goal is render the previous weeks with gray background, the current week with white background e the future weeks with a third backgroundcolor.
Is there something in fullcalendar.io objects that can help me?
Using
dayRender: function(dayRenderInfo) {
console.log( $(dayRenderInfo.el).data('date') );
return dayRenderInfo.el;
}
I know that dayRenderInfo contains el, so using jQuery I can read $(el).data('date') to retrieve the date of the rendered day 'cell'.
But then, in js, how to check it, for example '2019-03-20' is the current week or past or future ?
I posted the question using fullcalendar tag because I hope there is an helper proprerty or similar, otherwiser, anyway, a plain js solution is very appreciated.
My solution is use the dayRender function of fullCalendar.io (actually #v4.0.1)
The function receive an HTML element already rendered. But you can intercept and manipulate it.
I decided to append an attribute, data-date, to the element so I can check it at runtime.
Note: I'm using jQuery.
dayRender: function(dayRenderInfo) {
// Make a Date object from current rendered element
const day = dayRenderInfo.el;
const date_str_of_this_day = $(day).data('date');
const this_day = new Date(date_str_of_this_day);
const today_string = new Date().toISOString().slice(0, 10);
// 0 (Sunday) ... 6 (Saturday)
let number_of_weekday = this_day.getDay();
if (number_of_weekday ==0) {
// I shift to adapt to italian week
// 1 (Monday) ... 7 (Sunday)
number_of_weekday = 7;
}
// From today's date object, I can find monday
let first = this_day.getDate() - number_of_weekday + 1;
const monday_date = new Date(this_day.setDate(first));
const monday_string = monday_date.toISOString().slice(0, 10);
// From monday's date object I can find sunday
let last = monday_date.getDate() + 6;
const sunday_date = new Date(this_day.setDate(last));
const sunday_string = sunday_date.toISOString().slice(0, 10);
if (sunday_string < today ) {
// the current day being renderer is AFTER current week
dayRenderInfo.el.style.backgroundColor = '#ededed';
} else if (today < monday_string ) {
// the current day being renderer is BEFORE current week
dayRenderInfo.el.style.backgroundColor = '#f9e9d7';
} else {
// the current day being renderer is PART OF curremt week
dayRenderInfo.el.style.backgroundColor = 'white';
}
// return altered html rendered
return dayRenderInfo.el;
},

Determine if current time is within an array of time ranges

For a website blocking/productivity app written in javascript, I'd like to have a user input a series of time ranges available for free time (in his local time). Example:
06:00-06:30
12:30-13:00
23:45-00:15
24 format is not required (I'm just assuming it will be easier)
The program should then check the specified free time ranges against the current time to determine whether block mode is on or off.
My rough idea is to use an inbuilt Javascript function to grab the current DateTime, and convert it to 24 hour format if necessary. I think the time ranges will be in an array. I'm not sure how to check if the current date is within a range in the array.
The logic must also be able to handle the crossover from 23:00 to 0:00.
Anyways that is my line of thought. Thanks for any suggestions including ones that take a different path.
Anyways that is my line of thought. Thanks for any suggestions including ones that take a different path.
If you want to check if current time is in range then the range should be DATE + TIME as current time is DATE + TIME
Possible solution
You can convert all three datetimes to moment instances and just use
start.isBefore(current)
&& current.isBefore(end)
Moment docs on isBefore and isAfter : https://momentjs.com/
"I'm not sure how to check if the current date is within a range in the array."
You'd loop through the array and compare. I'd suggest storing the ranges as an array of objects where each individual range is something like {start: "10:15", end: "10:45"}.
JavaScript doesn't have time objects, only Date that includes date and time information. So I think it would be easiest to convert the current time to the "hh:mm" format as a string and then just do simple string compares against your range values, rather than worrying about converting the range values to date objects. So:
var timeRanges = [
{ start: "06:00", stop: "06:30" },
{ start: "12:30", stop: "13:00" },
{ start: "23:45", stop: "00:15" }
]
function isTimeInRange(time) {
for (var i = 0; i < timeRanges.length; i++) {
var range = timeRanges[i]
if ((time > range.start && time < range.stop)
|| (range.start > range.stop && (time > range.start || time < range.stop))) {
return true
}
}
return false
}
But you can make the code neater, and shorter, using the array .some() method, with or without arrow functions:
var timeRanges = [
{ start: "06:00", stop: "06:30" },
{ start: "12:30", stop: "13:00" },
{ start: "23:45", stop: "00:15" }
]
function isTimeInRange(time) {
return timeRanges.some(range =>
(time > range.start && time < range.stop)
|| (range.start > range.stop && (time > range.start || time < range.stop))
)
}
function pad(d) {
return ("0" + d).slice(-2)
}
function getCurrentTime() {
var now = new Date()
return pad(now.getHours()) + ":" + pad(now.getMinutes())
}
console.log("Current time in range? " + isTimeInRange(getCurrentTime()))
// test some other times
console.log(isTimeInRange("06:15")) // true
console.log(isTimeInRange("12:35")) // true
console.log(isTimeInRange("13:30")) // false
console.log(isTimeInRange("23:50")) // true
console.log(isTimeInRange("00:14")) // true
Obviously you can change < and > to <= and >= if desired.
Try it
start = "10:10";
end = "16:30";
function isInRange(start, end, current){
start = convertTimeToMinute(start);
end = convertTimeToMinute(end);
current = convertTimeToMinute(current);
return start <= current && current <= end;
}
function convertTimeToMinute(time){
return +time.slice(0,1)*60 + +time.slice(3,4);
}
console.log(isInRange(start,end, "15:20"));
console.log(isInRange(start,end, "20:20"));

Preventing Memory Leaks when removing DOM elements

I've been developing in Javascript for a while but the issue I am having with memory leaks is a little over my head. Apologies as this my be a long question but any help will be greatly appreciated.
I have a custom made table in a calendar format #sxpSolutionTblWrap which is dynamically populated using a template with details of each day. By default I load in 2 weeks, without weekends, so I populate 10 days worth of DOM elements.
Clicking on a day calls a function populateInfoPanel, in this function I call another function loadSingleSolutionRow where I find if a previous day has been selected in table and remove it, then populate it again with the basic info as if it weren't selected.
loadSingleSolutionRow
loadSingleSolutionRow: function(dow, dateValue, click, columnId) {
var self = this;
if (click === true) {
$('.sxpTableCol[data-colid="' + dow + '"]').empty();
}
//do stuff
var columnName = click === true ? '.sxpTableCol[data-colid="' + dow + '"]' : '#solCol' + columnId;
if (click === true) {
$(columnName).replaceWith(self.solutionTableRow({
dayId: dow,
date: selectedDate,
dateValue: dateValue,
statusClass: statusClass,
statusIconClass: statusIconClass,
trainerCountEarly: trainerCountEarly,
trainerListEarly: trainerListEarly,
roomCountEarly: roomCountEarly,
roomListEarly: rooomListEarly,
trainerCountLate: trainerCountLate,
trainerListLate: trainerListLate,
roomCountLate: roomCountLate,
roomListLate: rooomListLate,
protip: protip,
statusText: statusText,
}));
} else {
$(columnName).append(self.solutionTableRow({
dayId: dow,
date: selectedDate,
dateValue: dateValue,
statusClass: statusClass,
statusIconClass: statusIconClass,
trainerCountEarly: trainerCountEarly,
trainerListEarly: trainerListEarly,
roomCountEarly: roomCountEarly,
roomListEarly: rooomListEarly,
trainerCountLate: trainerCountLate,
trainerListLate: trainerListLate,
roomCountLate: roomCountLate,
roomListLate: rooomListLate,
protip: protip,
statusText: statusText,
}));
}
//Event listener for clicking on day
$('.sxpTableCol').off().on('click', '.sxpTableHeader', function (e) {
//populateInfoPanel
});
}
I then proceed to add events of each day to load onto the calendar in a for loop, that remove DOM elements previously in day and replaces it with new DOM element in the populateInfoPanel Function
populateInfoPanel
for (var j = 0; j < duration; j++) {
var dayCount = j + 1;
if (dayId !== undefined && daySolutions.Days[dayId].Solution !== undefined) {
//Getting day of solution in calendar grid
var daySolution = daySolutions.Days[dayId].Solution[j];
var solutionDayIndex = daySolution.DayIndex;
var solutionWeekIndex = daySolution.WeekNum;
var startWeek = moment(self.dto.startDate, 'YYYY-MM-DDTHH:mm').diff(moment(this.settings.findWhere({
Key: 'StartDate'
}).get('Value'), 'YYYY-MM-DD').startOf('isoWeek'), 'weeks') + 1;
var weekIndex = solutionWeekIndex - startWeek;
//var day = parseInt(dayId) + j;
var day = solutionDayIndex + (weekIndex * self.numDays);
//DO STUFF -- GETTING ROOM & TRAINER INFORMATION TO APPEND TO DOM
//DO STUFF -- GETTING POSITION OF ELEMENT ON THAT DAY
//DO STUFF -- GETTING LABELS THAT GO ONTO HEADER OF DAY
//APPEND DAY DETAILS TO CALENDAR
$(shiftData + day + '"]').append(self.selectedItemTpl({
dayCourse: dayCourse,
trainerList: trainerLabel,
roomList: roomLabel,
dayId: dayInfoId,
solutionId: j,
shiftId: shiftIndex,
day: day,
trainerIconClass: trainerIconClass,
roomIconClass: roomIconClass,
}));
}
}
The problem I am having is that when I click on a day and then another and another, it takes a little longer each time. This is fine when a solution only have 1 - 5 days on a 2 week grid, however it is very slow when a solution is 20 days long on a 5 week grid and the time when clicking through each day is more noticable.
The populateInfoPanel is about 500 lines long, unsure if that has anything to do with it. I am unsure if my method of removing elements isn't actually removing them from memory, if this is the case, how can I do this more effectively? Any help would be greatly appreciated.
From a 10 day solution on a grid of 5 weeks (25 days worth of DOM elements on Grid), here is the timeline view of clicking between days for 30 seconds, as you can see the first click takes 8 tenths of second, whereas the final click takes 1.5 seconds and gets more noticeable the more you click.
Below are some heap snapshots during 30 seconds of clicking between days, if you need to see anything further to get a better idea of what may be causing this issue, it would be very helpful
Before
Comparison

Categories

Resources