Javascript Date auto-updating unexpectedly - javascript

I am baffled. I have a "ready" function, from jQuery, which sets an HTML5 sessionStorage variable to the .valueOf() result of a new Date (as shown below). Somehow, though, the variable keeps refreshing and updating the time while my page is open. The sessionStorage variable doesn't even know it's a Date, it just stores the milliseconds, and the "ready" function is only called once at the beginning (I've checked using an alert window). There is no logic in my code to make this happen, but the value on the page stays up-to-date in real time. Any ideas?
// Initialize default date range
if (sessionStorage.minDate == null) {
d = new Date();
sessionStorage.minDate = (d.valueOf() - 172800000);
delete d;
}
if (sessionStorage.maxDate == null) {
d = new Date();
sessionStorage.maxDate = d.valueOf();
delete d;
}
UPDATE:
Still not fixed, but I've tried giving the milliseconds as a literal, and it still does the same thing. So it must have something to do with the fact that I'm creating a new Date later on using the millisecond count.
Any thoughts are much appreciated. I really have to get this working for work.

Apparently I was storing the number of milliseconds as a string, and wasn't parsing it back into an integer, so when I tried to create a new Date with it, javascript didn't know what to make of it and just created a Date with no parameters: the current date and time.

Related

Manipulate JS Date internal time

I am trying to sync my client app time to my server time (it matters because the app is serverless and has offline-work). On the app startup I calculate the time difference and then override the Date.now() method to add the difference into original now. For example assume this code:
Date.__serverDifference = calculateServerDifference();
Date.__now = Date.now;
Date.now = () => Date.__now() + Date.__serverDifference;
and it works fine. But the problem is about other Date functionalities. For example if I use new Date() it will return original time and it doesn't care the overridden now method.
As the MDN documentation says:
JavaScript Date objects represent a single moment in time in a
platform-independent format. Date objects contain a Number that
represents milliseconds since 1 January 1970 UTC.
Is there any way to override the js Date Class to return all current times according to this new calculation?
The best approach would be to create helper methods that include the offset for all functions for which the built-in functions don't return the desired value. Your Date.__now is a start, but you could also have:
const offset = calculateServerDifference();
const newDateIncludingOffset = (...args) => {
const date = new Date(...args);
date.setMilliseconds(date.getMilliseconds() + offset);
return date;
};
And then replace all instances of new Date(...args) with newDateIncludingOffset(...args). If you have a lot of references to new Date already - bite the bullet and change them appropriately.
While you could change methods on the prototype, that's not such a good idea - using your own functions and methods while not changing the built-ins is a much better approach.
You could also replace window.Date entirely with something new, with your own methods, allowing you to change the Date constructor to factor in the offset you need - but again, that's not a great idea and can lead to fragile code and incompatibility issues.

How to add 30 minutes to startdate in update/delete dialog in fullcalendar 3.10 javascript

In the update window I would like to automatically add 30 minutes to the event start date:
$('#updatedialog').dialog({
autoOpen: false,
width: 680,
buttons: {
"update": function () {
var eventToUpdate = {
id: currentUpdateEvent.id,
title: $("#eventName").val(),
description: $("#eventDesc").val(),
color: $("#colorPicker").val(),
start: new Date($("#eventStart").val()),
end: new Date($("#eventEnd").val()),
//end: new Date($("#eventEnd").val(moment(event.start).add(30, "m").format("YYYY-MM-DD[T]HH:mm"))),
//end: new Date($("#eventEnd")).setMinutes($("#eventStart").val() +30),
note: $("#EditEventNote").val(),
/*start: moment($("#eventStart").val(), "DD/MM/YYYY HH:mm"),*/
};
PageMethods.UpdateEvent(eventToUpdate, updateSuccess);
$(this).dialog("close");
currentUpdateEvent.title = $("#eventName").val();
currentUpdateEvent.description = $("#eventDesc").val();
currentUpdateEvent.color = $("#colorPicker").val();
currentUpdateEvent.note = $("#EditEventNote").val();
currentUpdateEvent.start = new Date($("#eventStart").val());
currentUpdateEvent.start.setMinutes(currentUpdateEvent.start.getMinutes() + 30);
$('#calendar').fullCalendar('updateEvent', currentUpdateEvent);
$('#calendar').fullCalendar('refetchEvents');
},
But this code doesn't work.
Firstly this is largely a momentJS issue, not a fullCalendar one.
You need to clone the start date, mutate it by 30 minutes, and then format it for output.
N.B. event.start doesn't actually appear anywhere in your code, so I'm assuming you actually wanted to use the value from the "eventStart" textbox instead. And I've gone back to setting the date format the way we agreed in your earlier question about this code. It's unclear why you've stopped doing it that way, because you already made clear it didn't work to set the start/end dates using new Date(...).
Therefore your code would look this like:
"update": function () {
var start = moment($("#eventStart").val()); //parse the start date
var end = moment(start); //clone the start date to make the end date
end.add(30, "m"); //add 30 minutes to the end date
//create the event object with formatted dates
var eventToUpdate = {
start: start.format("YYYY-MM-DD HH:mm"),
end: end.format("YYYY-MM-DD HH:mm")
//...etc
};
$("#eventEnd").val(end.format("YYYY-MM-DD[T]HH:mm")); //only include this line if you actually want to set the value of the eventEnd textbox.
//...etc
Minimal demo: https://codepen.io/ADyson82/pen/PojKGXY
Relevant documentation:
https://momentjs.com/docs/#/parsing/moment-clone/
https://momentjs.com/docs/#/manipulating/add/
P.S. I want to make a more general point about your approach to programming, based on what you've shown here, and your various previous questions where I've intervened.
This attempt:
//end: new Date($("#eventEnd").val(moment(event.start).add(30, "m").format("YYYY-MM-DD[T]HH:mm")))
contains a jumble of code all packed together in what appears to be a giant piece of guesswork, or possibly a "throw everything at it until something sticks" approach. Neither of those techniques are going to make you a good programmer. Programming is a science / engineering discipline, not an art form or a hit-and-hope game. You need to be methodical and precise. If the best you can say about it is that it "doesn't work", then it's clear you haven't analysed it at all. To solve problems in your code, you need to analyse it and debug it piece by piece.
So what you need to do with that code, to see why it's not working, is take it all apart, read the documentation properly for each of the many functions you've used there, and work out what they output and whether that's relevant to your situation - and/or whether each one gives suitable input to the thing you've included it within.
When testing JavaScript / jQuery code you should also be checking in your browser's Console (in the Developer Tools) for errors, and using the built-in debugger to step through the code line by line to see the values of your variables, and spot where the code and the values don't do what you expected them to. (If you don't know what you expect a particular part of the code to do, then you should either scrap that part and write something you can understand, or go and read documentation and try examples using that code until you do understand it. Otherwise you're just back to guessing again, and that's pointless.)
You can test each part of the code individually to verify your understanding. Putting large numbers of function calls together in one line like in the example above makes it very difficult to debug - for testing, you should split it into invidiual lines and see what each one produces, before deciding whether it's useful to put into the next step. For example if we break down that code into separate steps, we'd end up with:
var moment1 = moment(event.start);
moment1.add("30", "m");
var formattedDate = moment1.format("YYYY-MM-DD[T]HH:mm");
var x = $("eventEnd").val(formattedDate);
var dt = new Date(x);
var eventToUpdate = {
//...
end: dt
}
Now let's pick apart the logical flaws, one by one:
event.start doesn't appear to exist in the context you've shown (unless you've omitted some outer code). So you're probably starting with a blank to begin with. As I mentioned above, I'm guessing you actually meant to use the value from the eventStart textbox instead.
If event.start does exist in this context, then it looks like it probably came from fullCalendar, and fullCalendar v3 (as per its documentation) already gives you dates as momentJS objects - so you don't need to wrap them in the moment() constructor all over again. Whilst it does no harm, it's also inefficient and clutters up your code for no reason.
$("eventEnd").val() will set the value of a field on the page. It's not clear whether this was intentional or not, since your stated objective was to add 30 minutes to the event's start date (presumably to form an end date ready to send to the server, although your wording could be interpreted to mean you actually want to modify the start date itself, not use it as an end date).
.val() doesn't return a value (it only sets a value when used the way you've done it). Therefore x will always be empty.
Because x is empty, new Date(x) won't do anything useful.
You don't want new Date anyway, because you need to send a pre-formatted Date as a string to your server - we already discussed this in one of your previous questions so it's not clear why you've tried this again now - apart from, as I've assumed above - that you still don't really understand any of these individual pieces of code and are still guessing randomly without testing them properly or reading anything about what they do. I will speak candidly and say that you will never achieve anything as a programmer until you learn to do both of those things. Once you start doing them, your tasks will suddenly start to seem a lot easier.
As you can see, once we break this down one by one, it's a lot easier to find the problems on their own than when it's all together in one line and you can't tell which part is doing what. Once you've got something that works, then it's fine to reduce it down into less lines if you think it saves space or makes the code neater. But don't do that until you're sure it's going to do what you want.

"new Date().toLocaleString()" returning same time every time

I'm pretty new to coding and I'm running a Discord bot on Discord.js
I have a command that prints the current date and time by using new Date().toLocaleString(); but I noticed that it prints the exact same date and time every time it's used. Am I using this wrong? I initially had it using message.createdAt but didn't like the format it displayed the date and time in.
EDIT:
It's literally just
var currentdate = new Date().toLocaleString();
if(command === "date") {
message.channel.send(currentdate);
}
But it's only ever accurate on the first use and every use after that prints the first given date and time.
Screenshot of the problem
EDIT 2:
Okay so it worked by just using new Date().toLocaleString(); and not bothering with the variable. Thanks everyone.
I'll try to guess (you provided too few lines btw) : you assign to "currentDate" the value of the exact moment in which it is called. But you don't repeat the check somewhere, so "currentDate" is always the same.
Its working properly.could you please provide code where your trying

Calculate date difference in jQuery

The question is; there are 2 fields in my application, one is date (Field1) and second is a label (Field2). So, I want that when user selects a date in field 1, then field 2 should be automatically populated (current date - date from field 1).
Can anyone help on how to implement it.
I'm using jQuery to display date:
// This displays the date dialog when user clicks on Field1
$('#Field1').click(function () {
$('#Field1').simpleDatepicker();
});
// Tried following code but it didn't worked
$('#Field1').click(function () {
$('#Field1').simpleDatepicker({
onSelect: function () {
$('#Field2').value(calculateDays($('#Field1').toString))
}
});
});
function calculateDays(dateString) {
var today = new Date();
var inputDate = new Date(dateString);
var days = today - inputDate;
return days;
};
This may look like pathetic code to some folks but I'm just a beginner, so any suggestions/comments are welcome.
Also please tell me if this can be done using html only and no need to go to jQuery. It is my understanding that the calculating days (difference between dates) code will go in jQuery since this needs to be fired after selecting date ('onSelect' event). Please correct if wrong.
I'm assuming that you're trying to use Karl Seguin's jquery.simpleDatePicker (it came top when searching for "simpledatepicker" on Google).
As Jimbo remarks in the comments, it's hard to advise on an MVC approach here — you say you want to do this purely with HTML, but HTML alone can't dictate behaviour (I'd say that's extremely un-MVC). HTML5 forms do allow some limited behavioural control (validation etc), and they also offer <input type="date"/>, but none of these help your situation.
So for this answer I'm just going to fix the mistakes in your code:
The plugin is initialised with the simpleDatePicker jQuery method — you forgot to capitalise the 'P';
The plugin itself caters for the click event. You should initialise it directly without waiting for user input;
There was no onSelect initialisation option in the source code: I chose to use a change event listener on the input to capture this;
You use the jQuery method value — that's native DOM Javascript — you should be using val instead;
toString won't work on DOM elements or jQuery objects — again, use the val method;
The native Date object can't parse dates in arbitrary formats — nor would your code produce a number of days if it did (it would just produce the difference in milliseconds). For this kind of functionality you should use a good date library: I've opted for Moment.
Resulting code (as demonstrated here):
$('#Field1')
.simpleDatePicker()
.on('change', function passValue(){
$('#Field2').val(calculateDaysFromNow($('#Field1').val()))
});
function calculateDaysFromNow(dateString){
return moment.duration(moment(dateString,'MMM DD YYYY').diff()).days();
}
A bit of elaboration on how I've used moment:
First of all, we want to parse #Field1's formatted date for an actual quantifiable date object:
moment(dateString,'MMM DD YYYY')
Next, we want to differentiate that from now. Like Date, moment assumes now if we pass no argument:
moment(dateString,'MMM DD YYYY').diff()
We don't want this as a date, but as a duration, so we'll pass it to moment's duration method:
moment.duration(moment(dateString,'MMM DD YYYY').diff())
…and finally, we want this expressed in days:
moment.duration(moment(dateString,'MMM DD YYYY').diff()).days()
I'm not sure but this:
$('#Field2').value(calculateDays($('#Field1').toString)) should be like this:
$('#Field2').value(calculateDays($('#Field1').val())) or $('#Field2').value(calculateDays($('#Field1').text()))
Here is solution for setting same date in second field.
Link:jquery: using two datepicker with two fields ( field 1 , field2 + 1 day ) like booking.com
Change the format according to your need.

"Can't execute code from a freed script" when calling date.getHours() in IE9

I pass a Date object to a method which calls date.getHours() or any other method such as date.getFullYear() and it throws an error "Can't execute code from a freed script". It seems that IE9 does not properly support date objects used by date picker.
I'm new to javascript/general coding and have had a problem which only seems to occur in IE9. I am warning everybody about this as I may have gone about solving it in completely the wrong way...
I tried various different things in an attempt to solve this problem, such as:
if (date.getHours()=="undefined") {
var localDate = new Date(date);
var hours = localDate.getHours();
// etc
}
I now have a solution (it may not be the best, but it does the job) and will post it below, however I would like to know if anybody else has encountered the same problem and how they have resolved it?
In my experience, the problem happens when the Date object you've got was constructed in a different window, such that since its construction that other window has been closed or reloaded with a new page.
The solution is to send object inter-window in some string form, reconstituting them as necessary in the destination context.
(It isn't just Date instances of course; it's any object type. Primitives don't have the problem, if I recall.)
My solution was as follows...
I created a new method:
function getValidDate(date) {
try {
date.getHours();
return date;
} catch (e) {
return new Date(date);
}
}
I then called getValidDate() in any method which was affected by the original problem:
date = getValidDate(date);
It is as Pointy described, I just returned a new Date populated by the original date which had been passed into the method. I could then call any method such as getHours(), getFullYear() etc on this new date.
I am new to the world of programming so although this might seem simple, I hope this is helpful for others if they are in a similar situation.

Categories