Issues with Date() when using JSON.stringify() and JSON.parse() - javascript

I am trying to calculate the difference between two times using JavaScript. It's just basic math but I seem to have some issues with that while using JSON.stringify() and JSON.parse().
If you're wondering why am I applying the JSON.stringify() function to the date, it's because I using local storage to store some data on the client side and use it whenever the client lands on my website again ( it's faster that way rather than making more requests to the server ). That data usually updates once in a while ( I'm grabbing the data through API from another website ), so I set up a data_update variable and I'm storing it together with the other data.
That way I'm grabbing the stored data from the local storage and check if the difference between data_update ( which is a date / time ) and the time / date when the check it's made and see if it's greater than a week / day /etc .
So that is the reason why I'm using the JSON functions. My problem is that when I'm parsing the data from the local storage, the date seems to be different from a Date() object.
I'm trying to do the next operation per say :
var x = JSON.parse(JSON.stringify(new Date()));
var y = JSON.parse(this.get_local_storage_data(this.data_cache_key)); // the data object stored on local storage
var q = y.data_update; // this is the variable where the Date() was stored
console.log(Math.floor((x-q)/1000));
The above will return null. Also when I want to see the Math.floor(x) result, it returns null again.
So what can I do in this situation ? Is there a fix for this ?

If you look at the output of JSON.stringify for a Date, you'll see that:
JSON.stringify(new Date())
Results in a string. JSON does not have a primitive representation of Date objects that JSON.parse will turn back into a Date object automatically.
The Date object's constructor can take a date string, so you can turn those string values back into dates by doing:
var x = new Date(JSON.parse(JSON.stringify(new Date())));
Then the arithmetic will work.
x = new Date(JSON.parse(JSON.stringify(new Date())))
y = new Date(JSON.parse(JSON.stringify(new Date())))
y - x
=> 982

JSON.stringify(new Date())
returns
"2013-10-06T15:32:18.605Z"
Thank God is: Date.prototype.toISOString()

As the recommended answer suggests, the date is simply converted to a string when using JSON.stringify.
Another approach that would maybe fit this use case is to store the time in milliseconds using Date.now():
// Date.now() instead of new Date()
const millis = Date.now();
console.log(millis);
// same output as input
console.log(JSON.parse(JSON.stringify(millis)));
That way you can be sure that what goes into JSON.stringify comes out the same when using JSON.parse.
This also makes it easy to compare dates, if you have two millisecond values, using < and >.
Plus you can convert the milliseconds to a date at any time (usually before you render it to the user):
const millis = Date.now();
console.log(millis);
console.log(new Date(millis));
NOTE: using milliseconds as your date representation is usually not recommended, at least not in your database: https://stackoverflow.com/a/48974248/10551293.

Related

how to send date as timestamp in svelte?

The svelte application is supposed to send these data to create an event to be stored in a database.
let eventName=document.querySelector('#eventName')
let timeFrom=document.querySelector('#timeFrom')
let timeTo=document.querySelector('#timeTo')
let repeatedEvery=document.querySelector('#repeatedEvery')
let startFrom=document.querySelector('#startFrom')
let endOn=document.querySelector('#endOn')
const status="upcoming"
let isRepeated=true
The dates should be sent as UNIX timestamps, I can do that just fine. The problem is to do that I had to add toString() to the variables which gives me an error of "this element is null", without it gives me 5 overload errors. I tried declaring the variable in a function that would do this process but the variables are not global anymore.
I don't want to fix the current code, I'll write the whole thing from scratch if I have to, my question is how do I actually approach this in the first place?
the dates input fields are datetime-local, and needless to say the timestamps should be a number, all the other types of data go through just fine.
Date.prototype.valueOf() returns what you need.
const dNow = new Date();
dNow.valueOf(); // 1673445066359
If you are getting null values in variables that are supose to be Dates, you can default them to a value.
const dDateDefaultToNow = theSourceValueThatYouAreUsing || new Date();
const dDateDefaultToZero = theSourceValueThatYouAreUsing || 0;
This way, if theSourceValueThatYouAreUsing is null then it will default to new Date() or 0.
For more help, please share more of your code.

How to check if timestamp of SQL fetched dateTime object is older than another one with moment.JS?

I query a dateTime object from PostgreSQL DB using an AJAX call which returns the following format:
2019-12-13T22:59:59Z // print type of: `undefined`
I now want to compare the timestamp of that object with the current time now and fire a function if the timestamp is not older than 5 seconds compared to the current time.
My idea is to calculate the difference in seconds and check the result for <> 5.
But how can I convert the database fetched dateTime object into a moment object to be able to compare them?
Edit:
Due to the conclusions from the comments provided, I changed my logic and end up with the following problem:
I have a timestamp in SQL which changes secondly. I fetch this timestamp with AJAX and would like to fire a function if the new timestamp is not older than 5 seconds than the previous one.
I set up moment.js objects to calculate the difference. Now my problem is that on the first iteration latestTick is not defined.
How can i design the loop that it compares both timestamps and always updates the latestTick with the lastTick for the next iteration (and also won't error on the first iteration)?
Javascript:
Ajax call...
[...]
lastTick = response[0].fields.account_lastTick.toString()
lastTick1 = lastTick.slice(0, 10)
lastTick2 = lastTick.slice(11, 19)
lastTick = lastTick1 + ' ' + lastTick2
lastTick = moment(lastTick, 'YYYY-MM-DD hh:mm:ss')
if ((lastTick.diff(latestTick, 'seconds')) != 0) {
console.log('not Zero')
} else {
console.log('Zero')
}
latestTick = moment(lastTick, 'YYYY-MM-DD hh:mm:ss')
[...]
To give you an idea on how to compare time in Moment.js. you can do this
import moment from "moment"
const dateTimeStr = "2019-12-13T22:59:59Z" // your DB already includes timezone in the response (UTC+00:00)
const dateTimeMoment = moment(dateTimeStr)
const next5MinsMoment = moment().add(5, 'minutes')
if(dateTimeMoment.isBefore(next5MinsMoment)) {
// fire function call
}

Attempt to sort firebase database is not working

I am trying to sort firebase date by date but it is not working.
I have firebase data structure in this format
I use this function to call the node
var awardsref = CatalogueDB.ref("cageawards/" + mycagecode).orderByChild('Awarddate');
awardsref.on('value', Awardstable, errData);
this is the output
is there a work around to sort the data based on this date format?
As #GerardoHerrera pointed out, Firebase don't support sorting by Date. However, if you parse the dates and convert them to milliseconds based on the UNIX epoch, you should be able to sort them lexicographically according to that.
const date1 = new Date("04-07-2018").getTime();
date1; // 1523084400000
const date2 = new Date("06-02-2018").getTime();
date2; // 1527922800000
Since date1 is less than date2, it will sort as being before date2 in ascending order. Store those converted millisecond time values in your Firebase and you should be able to sort your dataset by them.
e.g.
"7MFD4" {
...
"SPE7L018P1428" {
"Awarddate": "04-07-2018",
"AwarddateMS": 1523084400000
...
}
...
}
Then do orderByChild('AwarddateMS').
According to the following page, How query data is ordered, a date is not considered in any sorting way. It first orders null values, then false values, then true, numbers, strings and finally objects.
And all sorting is made following a Lexicographical Order.
So you may need to do the sorting on the client side by your own methods.
There´s another post where you can find an explanation on how to sort by date here

Comparing Dates with AngularJS

I am building an AngularJS/Rails web app, part of it is creating bookings (function bookings) and in the dashboard I am trying to display two different tabs one with Current Bookings and one with Previous Bookings. the booking model has a function_date attribute and I am retrieving it from the API into a $scope.bookings array.
How to I compare dates (run an if statement on it) to do if function_data > today's date store it into CurrentBookings array if not store it into PreviousBookings array?
Hope that makes sense.
P.S. I am still teaching myself how to program so it might be a stupid question for some.
many way solved this problem but i am using to convert time in milliseconds then easy to compare.
var n = Date.now();
its give the current
Return the number of milliseconds since 1970/01/01:
1460260009358
First, try converting your string into a date. Then compare it to now.
var date = new Date('2030-03-30'); //this is a Date object
if (date > new Date()) { //Date object comparison
//[...]
}
// or
if (date.getTime() > Date.now()) { //unix timestamp (integer) comparison
//[...]
}

Deep understanding: How code structure affects the content of date arrays created with loops

Background explanation
I have asked a question concerning defining an date array using a loop.
The array is defined on basis of a declared variable named "dateinterval". The way I designed the code resulted in an error message in relation to another loop and another user provided another loop for me which solved this.
Now that I have closely compared the two different solutions I simply do not understand why they do not produce the same outcome.
My code
I developed the below code to define an array of dates in UTC format. However the outcome is an array of dates in millisecs since January 1, 1970, 00:00:00. So in other words a number.
for (var i=0; i < difference; i++){
dateinterval[dateinterval.length] = dateinterval[0].setDate(datointerval[0].getDate() + i);
};
The proper solution
The below code is the proper one provided to me by another user (thank you again!) This code defines an array of UTC dates.
for (var i = 0; i < difference; i++) {
var dt = new Date(dateinterval[0]);
dt.setDate(dt.getDate() + i);
dateinterval[dateinterval.length] = dt;
};
What I don't understand
I have almost become blind from staring at the two different solutions to figure out what the difference is and I just don't get it.
To my untrained eyes it seems that the two pieces of code perform exactly the same operation and that the only difference is how they are structured. I have been informed that setDate returns millisecs and that in my code these millisecs were assigned to the array. But in the proper solution the variable DT is also assigned a setDate value which - as I understand it - should also be in millisecs. So why does the line:
dateinterval[dateinterval.length] = dt;
not assign millisecs to the dateinterval array?
Can anyone explain this to me so that I can better understand Javascript and not just replicate working solutions?
When you do:
dateinterval[dateinterval.length] = dateinterval[0].setDate(datointerval[0].getDate() + i);
you are assigning the return value of dateinterval[0].setDate(…) to dateinterval[…]. That return value is the timeclip or internal timevalue of the Date object (which is milliseconds since 1 January, 1970). See ECMA-262 §20.3.4.20.
So you need to modify the Date first:
dateinterval[0].setDate(datointerval[0].getDate() + i);
then assign a reference to the object:
dateinterval[dateinterval.length] = dateinterval[0];
Edit
It may help to see a simple case.
// Create a new Date for 2015-01-01
var date = new Date(2015,0,1);
// Change the date to 2015-01-02
var x = date.setDate(2);
// The return value from the method is the internal timevalue
console.log(x);
// Check the timevalue
console.log(new Date(x)); // 2 January, 2015
The OP seems to expect that setDate returns the original Date object, but it doesn't, it returns the timevalue. The original function will work if the return value from setDate is converted to a Date:
dateinterval[dateinterval.length] = new Date(dateinterval[0].setDate(datointerval[0].getDate() + i));
however that throws away the original Date object and creates a new one.

Categories

Resources