Why can't JSON.parse() parse what date.toJSON() creates? - javascript

Tested using chrome Canary
I can convert a date to JSON:
> (new Date()).toJSON()
"2012-05-03T22:27:30.530Z"
I can convert it back to a Date:
> typeof (new Date("2012-05-03T22:27:30.530Z"))
object
Why can't I parse it as a Date using JSON.parse()? JSON.parse returns a string, not a Date:
> JSON.parse('{"DateValue":"2012-05-03T22:27:30.530Z"}').DateValue
"2012-05-03T22:27:30.530Z"

Because a Date is not a valid type in JSON. JSON only knows about strings, numbers, booleans, arrays, and generic objects (associative arrays/hashes/maps/dictionaries/pick-your-favorite-name). When you convert anything else to JSON, you get one of the above - which means if you want to get the "something else" back out as the type it started as, the receiver has to do some extra work to recreate it.
There are JSON libraries that abstract that work away, and include an extra attribute indicating what class something is, so if the receiver is using the same library they'll get that type back, but that's still the same work, just hidden by the library.

Because in the JSON, the date is a string, in the same way new Date("2012-05-03T22:27:30.530Z") parses a string. You're expecting JavaScript to know that the string in the JSON is a date.
You need to pass the JSON parsed string to the date object to get a date back out:
var date = new Date(JSON.parse('{"DateValue":"2012-05-03T22:27:30.530Z"}').DateValue);

The .toJSON method is only there to return a value that can be representated in JSON. Yet JSON does not know about data types, and is not possible to store object instance information (like the prototype) in a JSON string.
So, the toJSON method of Date could return a number (e.g. the Unix timestamp), a plain object with properties representing year, month, day etc. (not so good because not parsable with the Date constructor) or - what happens to be - a string, in here the ISO time format. With that, you can use new Date(JSON.parse(stringified_date)) to create a new Date object.
If you would delete Date.prototype.toJSON;, JSON.stringify(new Date) would result in "{}".

Related

To clear up some doubts about moment.js

I got stuck in my project, due to some doubts related to moment.js. I'll state some conclusions here I made during writing backend on project, and please can someone correct me if something is wrong?
For example, if I get datetime string from fronted, in format:
"THU 18 MAR 2017 09:20 AM", I should create moment object passing this string to it and corresponding token "ddd DD MMM YYYY HH:mm A" as passed string is not in standard ISO 8601 format.
var datetime = moment(datetimeFromFrontend, "ddd DD MMM YYYY HH:mm A");
Now I have moment object that can be formated in way I want, calling format() function on moment object.
If I want to do some manipulations with datetime generally (for example, compare to today's datetime, or compare only time part), is it mandatory to convert all manipulating datetimes, times or whatever to moment object with same format and using isBefore, isEqual and so on, or can I somehow compare them using >, <, <=, =< ?
If I need to compare (>, < etc) datetime or just time part with value retrieved from SQL database (which is DATETIME or TIME data type), should I pass both comparing values to moment object, convert them in same format and then do manipulations?
And how to save to SQL database column which is DATETIME, or TIME type? Should do some transforms from moment object to string using format()? SQL will automatically convert passing string to corresponding data type?
Example:
var now = moment();
I assume that "now" can't be passed to sql query directly as it is moment object, it should be converted to string (and rely on SQL automatic conversion from string/nvarchar to datetime) or should I save it as moment().toDate() ?
If I need to compare (>, < etc) datetime or just time part with value retrieved from SQL database (which is DATETIME or TIME data type), should I pass both comparing values to moment object, convert them in same format and then do manipulations?
You might want to lookup the docs for that
You have Query functions that can compare moments and even Date objects, for example, this is the entry for the .after function
moment().isAfter(Moment|String|Number|Date|Array);
as you can see, you can pass anything to .isAfter and it will do that job for you
moment().isAfter(new Date(2017, 2, 4))
// true
moment(new Date(2016, 2, 4)).isAfter(new Date(2017, 2, 4))
// false
Of course the easiest way to compare >, < or === is to get the timestamp using Date::getTime, but that's ugly code
And how to save to SQL database column which is DATETIME, or TIME type? Should do some transforms from moment object to string using format()? SQL will automatically convert passing string to corresponding data type?
I think it depends how you SQL works and how your server communicates to it, ORACLE, you should refer to any documentation about storing date objects inside your sql, eventually dates and formats are all about making unix-timestamps human readable/understandable.
I assume that "now" can't be passed to sql query directly as it is moment object, it should be converted to string (and rely on SQL automatic conversion from string/nvarchar to datetime) or should I save it as moment().toDate() ?
Ask yourself what kind of benefits you or anyone that may use you API will gain from getting agnostic Date objects from your DB rather then just plain strictly formatted strings?

JSON.stringify returns wrong value for the Date Object

the below code returns one day earlier,
var myJSON = JSON.stringify(new Date("02/02/1997"));
alert(myJSON);
myJSON variables returns "1997-02-01T18:30:00.000Z"
Why its returning wrong value.
Here, what does the meaning of "T18:30:00.000Z"
Is there any other way of converts the Date object to the String.
Try this..
var myJSON = JSON.stringify(new Date("02/02/1997").toLocaleString());
alert(myJSON);
It is converting your Date object to UTC date.
You should convert Date object to String value using predefined methods of Date Object. Like:
JSON.stringify(new Date("02/02/1997").toLocaleString());
JSON.stringify(new Date("02/02/1997").toDateString()); // to get date portion
Recommend you take a look at moment.js. The framework provides a very nice API for:
Parse, validate, manipulate, and display dates in JavaScript.
Convert your date into the desired string format and then JSON.stringify.

How to get date object from moment.js after formatting it

Using typescript, I am formatting my date with moment.js like this.
function getCreatedDate(objContainingDate: any): Date {
// Following line does not work since it is returning string,
// I need formatted date object to return
return moment(objContainingDate.createdDate).format("L")
}
The format method returns a string, how to convert it back to date object ?
This might be a delayed response.But, I think it can help others who still needs an answer.
https://momentjs.com/guides/#/lib-concepts/internal-properties/
To retrieve a native Date object from Moment, use .toDate()
You can directly get the Date object from Moment.
Using the date object with moment clones it and the original object is left intact to continue to use. But to convert it back just pass the formatted moment string into a new date object.
var myDateObj = new Date(2011, 9, 16);
var now = moment(myDateObj);
#Now convert it back to date object
var newDateObj = new Date(now.format("YYYY-MM-DDTHH:mm:ssZ"));

Parse this value with moment doesn't work

I have a date value like this value.game_date = 2013-10-27 03:39:35 and I'm trying to parse it as follow:
moment().format(value.game_date, 'DD-MM-YYYY');
But I get this as result 29-10-2013 00:00:00 where I'm looking for this format: 29-10-10-29 without hour, what I'm doing wrong?
I think you have some typos or misinformation in your post regarding the output you're getting and what you're desiring.
Based on what appears to be a misunderstanding of moment, however, I am pretty sure that what you want is:
value.game_date = '2013-10-27 03:39:35';
var formatted_game_date = moment(value.game_date).format('DD-MM-YYYY');
// produces '27-10-2013'
moment() is a factory function which takes a date string and returns a moment instance. That moment instance then has various methods available, such as format() which takes a format string as the first param.
So your code is producing a moment instance representing current date/time (because you're not passing any params to moment()), then you ask .format() to return a string formatted using your date stamp as the formatter. Your date string doesn't have any of the things in it which format would parse and replace, so you just get back your date string.
The code I gave passes the date string to moment to produce the instance, then asks .format() for a formatted string using your desired format template.

Proper way to format date from database using javascript/jquery

I am calling my database which contains a datetime datatype. The date looks like this:
2005-05-23 16:06:00.000
I would like to display this in a table when a user selects a certain item from a list. I call my controller action and return Json of all the times and put them in a table. The problem is the date is completely wrong. What is displayed is this:
/Date(1255470180000)/
The date that is returned isn't even parsable (which I don't want to do anyway) so I can't even get the data if I wanted to. Any ideas?
The date you're getting back is serialized to a marker and a number of milliseconds since midnight 1st Jan 1970 (in UTC). If you isolate the numeric portion, convert it into a number, and feed it into the Date constructor you'll get an actual date to work with, which you can then format as you like.
var ticks, dt;
// Isolate the numeric portion of the value
ticks = /[0-9]+/.exec(json.dateValue)[0];
// Convert to a number
ticks = parseInt(ticks);
// Convert to a date
dt = new Date(ticks);
Alternately, if the JSON serializer on the server supports a "replacer" parameter as Crockford's and ECMAScript 5th edition's do, you could supply a replacer that formatted the date into a string server-side and handle it there, since you said you don't want to parse the date client-side (although the jQuery tag suggested to me maybe you did).
The other alternative is to return the formatted string from the controller action. You could even leave the timestamp and return a second field as "Formatted Timestamp" or something similar.
var listFromDb = ...
return new Json(listFromDb.Select(itemFromDb => new List { new
{ Date = itemFromDb.Date, FormattedDate = FormatDate(itemFromDb.Date), ...}
I ended up formatting the code in the controller action instead.
I just cast the datetime property to a string using .ToString() and got the desired results.
Thanks for the help though guys.

Categories