Calculate new date after calendar event drop - javascript

I have a JavaScript/Math question.
I am stuck with one task for two days now and I guess I am complete idiot as I can't figure it out...Screenshot
I am creating a week calendar with shifts from 7am untill 8pm., but I can have shift which is for example 2 days long (or more).
The problem is that I can drag and drop the calendar event on the calendar and then I need to calculate new dateTo from dateFrom which I get from the div I placed it on.
The issues is that when I try to drag and drop the item to another time I need to place dateFrom to whenever I dragged it, but then I need to calculate hours so I get the same amount of time, but the problem is when the event is stretched over multiple days I need the event to finish next date after 7 am and not in the middle of the night. For example I had event from 3pm to 5pm of next day and then I moved it to 7pm of next day so I need the event to finish at 9 am of next day.
Does anyone has the same issue or solution for this?
Hope it makes sense, thank you very much.
Here is the code I am using right now, it almost works, but sometimes I get the wrong date/time (usually it removes 10 hours from date).
export function getCorrectDateAfterDrop(originalDateFrom, originalDateTo, dateFrom) {
const NIGHT_TIME = 11;
dateFrom = moment(dateFrom);
originalDateTo = moment(originalDateTo);
originalDateFrom = moment(originalDateFrom);
let hoursDiff = moment.duration(originalDateTo.diff(originalDateFrom)).asHours();
const sign = Math.sign(hoursDiff);
if (originalDateTo.isAfter(moment(originalDateFrom).hours(20))) {
hoursDiff = (hoursDiff > NIGHT_TIME) ? (hoursDiff - NIGHT_TIME) : hoursDiff;
}
let finalDateToBeChecked = moment(dateFrom).add((hoursDiff * sign), 'hours');
let isDateFromSameAsDateTo = moment(dateFrom).isSame(finalDateToBeChecked, 'day');
if (isDateFromSameAsDateTo && finalDateToBeChecked.hours() < 20) {
// I think the problem is here, but I can't figure it out :D
return finalDateToBeChecked.format();
} else {
const diffUntilShiftEnds = moment.duration(moment(dateFrom).hours(20).diff(dateFrom)).asHours();
hoursDiff -= diffUntilShiftEnds;
const finalDateFrom = moment(dateFrom).add(1, 'days').hours(7);
const finalDateTo = moment(dateFrom).add(1, 'days').hours(7).add(hoursDiff, 'hours');
return getCorrectDateAfterDrop(finalDateFrom, finalDateTo, finalDateFrom);
}
}

Maybe I do not fully understand your question, but I think something like the following should work:
function getCorrectDateAfterDrop(originalDateFrom, originalDateTo, dateFrom) {
return originalDateTo - originalDateFrom + dateFrom;
}
// verify it works:
var origFrom = Date.parse('01 Jan 2018 05:00:00');
var origTo = Date.parse('02 Jan 2018 07:00:00');
var newFrom = Date.parse('02 Jan 2018 01:00:00');
var newTo = getCorrectDateAfterDrop(origFrom, origTo, newFrom)
console.log((Date.parse('03 Jan 2018 03:00:00') === newTo)) // true
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.13.0/moment.min.js"></script>

Related

Doing math towards future date

I am trying to figure out how to calculate future date compared to current date. For Example: (think of Deadline as a Date field)
- If Deadline (value form) is in the future but <= 12/31 of the current year, “This Year”
- If Deadline (value form) is in the future but > 12/31 of the current year, “Future”
So far, I am unable to figure this out within my code.
I need help with var theFuture AND to create a var for "is future but <= 21/31 of current year.
var theFuture = new Date("January 01 2020");
//theFuture.setDate(today.getDate());
//Compare the two numbers
if (dateToCheck < rightNow || dateToCheck == rightNow) {
theTiming = "Overdue";
g_form.setValue('u_timing', theTiming);
}
else if (dateToCheck >= approaching) {
theTiming = "Deadline Approaching";
g_form.setValue('u_timing', theTiming);
}
else if (dateToCheck > theFuture){
theTiming = "Future";
g_form.setValue('u_timing, theTiming');
}
}
So, results should be: When the user selects a date from Deadline, another field called Timing will generate Text. Current, I am able to calculate if the date selected is today or before today, Timing will say "Overdue". Next, if the date selected is greater than today BUT within 180 days, Timing will say "Deadline Approaching". But, to get the rest that I mentioned above, I am stuck.
We use moment.js for working with dates it makes things a lot easier.
This will tell you if the date selected is today or not:
var iscurrentDate = moment().isSame(dateToCheck, "day");
if(iscurrentDate)
{
}
You can also do a similar thing for year
var iscurrentDate = moment().isSame(dateToCheck, "year");
if(iscurrentDate)
{
}
More info on moment here: https://momentjs.com/docs/

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;
},

JavaScript - Moment.js - isBetween() method check if time falls in a range

I am trying to see if timeNow falls between a time range opening and closing :
var timeFormat2 = "HH:mm:ss";
var timeNow = "23:12:00"; //(11:12:00 pm)
var opening = "08:00:00"; //(08:00:00 am) morning time
var closing = "00:12:00"; //midnight time (i.e 12:12:00 am)
var isAvailable = moment(timeNow, timeFormat2).isBetween(moment(opening, timeFormat2), moment(closing, timeFormat2));
console.log("will show false >>>> ", isAvailable); //it shows 'false'
var closing1 = "23:45:00";
var isAvailable1 = moment("23:12:00", timeFormat2).isBetween(moment(opening, timeFormat2), moment(closing1, timeFormat2));
console.log("Should show true >>>> ", isAvailable1);
Here is a JSfiddle to check it out:
https://jsfiddle.net/1wuf0rzg/8/
You need to introduce the concept of "next day". Here I have set the date to be the first day of the month. If the closing time is before the opening time, then I move the closing time to the 2nd day of the month.
function isAvailable(opening, closing, now){
var openingTime = moment(opening, timeFormat2).date(1);
var closingTime = moment(closing, timeFormat2).date(1);
var nowTime = moment(now, timeFormat2).date(1);
if(closingTime.isBefore(openingTime)){
closingTime.date(2);
}
return nowTime.isBetween(openingTime, closingTime);
}
https://jsfiddle.net/1wuf0rzg/14/
There's not enough data to compute.
00:12:00 means 12 minutes less than 8 hours before the opening time of the current Date.
Because of that, 23:12:00will fall out of range.
It would help using different kind of data:
opening time.
working hours (amount).
time now,
in order to be able to determine - if the 'time now' falls inside the time interval with ease.

Timezone specific hide/show element script

Hi first time posting here so bear with me.
I've got a live stream that I want to show on Sundays between 6am and 2pm (CEST - Central European Summer Time)
I've got the first part down but how do I make it timezone specific? Make sense?
$(document).ready(function() {
var d = new Date();
var n = d.getDay();
var hour = d.getHours();
if(n == 0 && hour >= 6 && hour < 14)
{
$(".stream").show();
} else {
$(".stream").hide();
}
} );
PS I understand this doesn't hide it completely outside of those times and that's fine. I'm just looking for a solution that works on the client side.

Unix offset with fullCalendar difference

I want to place a check when I'm getting a momentjs instance through fullCalendar.
I'm at the eventRender callback
var calendar = $('#calendar').fullCalendar('getCalendar');
var atime = calendar.moment();
var atime_h = atime.format("HH:mm");
atime = atime.unix();
var start = calendar.moment(event.start);
var start_u = start.unix();
var start_h = start.format("HH:mm");
console.log(atime);
console.log(atime_h);
console.log(start_u);
console.log(start_h);
Now what that logs is this:
1408024477
15:54
1407888000
00:00
1408024477 == Thu Aug 14 15:54:37 2014 == is correct
But 1407888000 == Wed Aug 13 02:00:00 2014, where I would expect 00:00 instead of 02:00
So there's a difference between the event .unix()/format.() and the moment I created.
Anyone got a clue what's going on?
Edit:
So what happens is that if I create two new moments: moment() and a moment().utc(), I get the same timestamp for both. But when I then display them, there is a difference of two hours.
The .utc one returns two hours in the past, the one without the correct one for me. The timestamp is not two hours back.
But with the event.start (which has _isUTC=true, the timestamp is two hours in the future (!), and it displays it correct when formatted.
So maybe I need to have my event.start to be not UTC and two hours back somehow?
Edit by request in comment, this is what I use now:
var start = calendar.moment(event.start);
console.log(start);
start_utc = new Date(start.year(), start.month(), start.date(), start.hour(), start.minute(), start.second());
var start = calendar.moment(start_utc);
console.log(start);
Try converting your event.start date to utc first, here's how to do it in vanilla js:
start_utc = new Date(start.getUTCFullYear(), start.getUTCMonth(), start.getUTCDate(), start.getUTCHours(), start.getUTCMinutes(), start.getUTCSeconds());
Then you can call .unix() on it and it should give you the expected timestamp.

Categories

Resources