Difference between converting date into string with toISOString() and JSON.stringify() - javascript

I researched about converting date into string in ISO format, and I found two methods to do that giving me the same result '2022-07-29T06:46:54.085Z':
(new Date()).toISOString()
JSON.parse(JSON.stringify(new Date()))
Question:
Does JS make two approaches/algorithms of converting date or just one function code just call on different object JSON or Date, If So Which one is the best to use?

First of all: less code, easier to maintain
So, new Date().toISOString() is simplest way to return string in ISO format.
Regarding question:
No. The output is the same, because of JSON.stringify logic underneath that returns:
JSON.stringify(new Date())
'"2022-07-29T18:58:14.411Z"'
Because:
The instances of Date implement the toJSON() function by returning a string (the same as date.toISOString()). Thus, they are treated as strings.
Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
(new Date).toJSON()
'2022-07-29T18:58:14.411Z'

JSON.parse(JSON.stringify(new Date())) is just the same as new Date().toJSON(). And in the docs for that method we can see
Calling toJSON() returns a string (using toISOString()) representing the Date object's value.
So they're having exactly the same result, calling toISOString() directly is just much more straightforward.

If an object passed to JSON.stringify has a toJSON method, then it's used to set the value within the JSON text (see SerializeJSONProperty step 2.b).
Date instances have a toJSON method that is defined as returning the same value as Date.prototype.toISOString.
I.e.
date.toJSON() === date.toISOString()
by design.

Related

How to manipulate date time using vanilla javascript

I want to manipulate date which come from the api.
When I use: console.log(dataAPI.dateStation)
I see 2023-01-24T06:00:00.000Z
Is there way to change the date time in this format 2023-01-24 06:00:00
Just I want to remove T character between date and time and remove .000Z at the end.
The simplest way to do it is probably:
new Date(dataAPI.dateStation).toLocaleString()
If what you want is to display it somewhere, it'll automatically adapt the ISO date you have into a localized and readable date (based on timezone and language).
To know more about it and the options, here is the doc: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString
If you want to print the date in ISO 8601 format, you can use the 'sv' (Sweden) locale and Date.toLocaleString().
You can also specify whichever IANA timezone you wish to use, I'm using UTC in this case.
const d = '2023-01-24T06:00:00.000Z'
let timestamp = new Date(d).toLocaleString('sv', { timeZone: 'UTC' });
console.log('Timestamp:', timestamp);
Use the javascript date class with toLocaleString
new Date(dataAPI.dateStation).toLocaleString('en-US');
Without installing some third-party library, your best bet is probably to use the string you have (which is the format returned by toISOString() ),and modify it as desired. If it's already a string in the format you gave, you can just call replace on it:
dataAPI.dateStation.replace('T',' ').replace('.00Z','')
If it's a Date object, first call toISOString() to get a string:
dataAPI.dateStation.toISOString().replace('T',' ').replace('.00Z','')
If it's a string in a possibly-different format, call new Date() to get a Date object, then call toISOString() on that, and finally call replace on the result:
new Date(dataAPI.dateStation).toISOString().replace('T',' ').replace('.00Z','')
You can use regular expressions to remove the parts you don't want:
let s = "2023-01-24T06:00:00.000Z"
s = s.replace(/T/, ' ')
s = s.replace(/\.\d{3}Z$/, '')
console.log(s)

Why does parsing a locale date string result in an invalid date?

Can someone explain why the following snippets result in an invalid date object?
new Date(new Date().toLocaleString())
// or
Date.parse(new Date().toLocaleString())
This is expressly permitted by the ES5 specification's definition of Date.parse (emphasis mine):
...all of the following expressions should produce the same numeric value in that implementation, if all the properties referenced have their initial values:
x.valueOf()
Date.parse(x.toString())
Date.parse(x.toUTCString())
Date.parse(x.toISOString())
However, the expression
Date.parse(x.toLocaleString())
is not required to produce the same Number value as the preceding three expressions and, in general, the value produced by Date.parse is implementation-dependent when given any String value that does not conform to the Date Time String Format (15.9.1.15) and that could not be produced in that implementation by the toString or toUTCString method.
Since toLocaleString is not required to produce a string conformant to the Date Time String Format YYYY-MM-DDTHH:mm:ss.sssZ, it is allowable for its output not to be parsed correctly by Date.parse.
new Date().toLocaleString() returns the current date in a format new Date() can't parse, resulting in unexpected dates.

new Date(milliseconds) returns Invalid date

I am trying to convert milliseconds to a date using the javascript using:
new Date(Milliseconds);
constructor, but when I give it a milliseconds value of say 1372439683000 it returns invalid date. If I go to a site that converts milliseconds to date it returns the correct date.
Any ideas why?
You're not using a number, you're using a string that looks like a number. According to MDN, when you pass a string into Date, it expects
a format recognized by the parse method (IETF-compliant RFC 2822 timestamps).
An example of such a string is "December 17, 1995 03:24:00", but you're passing in a string that looks like "1372439683000", which is not able to be parsed.
Convert Milliseconds to a number using parseInt, or a unary +:
new Date(+Milliseconds);
new Date(parseInt(Milliseconds,10));
The Date function is case-sensitive:
new Date(Milliseconds);
instead of this
new date(Milliseconds);
use this
new Date(Milliseconds);
your statement will give you date is not defined error
Is important to note that the timestamp parameter MUST be a number, it cannot be a string.
new Date(1631793000000).toLocaleString('en-GB', { timeZone: 'America/Argentina/Buenos_Aires' });
// Returns: '16/09/2021, 08:50:00'
new Date("1631793000000").toLocaleString('en-GB', { timeZone: 'America/Argentina/Buenos_Aires' });
// Returns: 'Invalid Date'
In case you're receiving the timestamp as string, you can simply wrap it around parseInt(): parseInt(your_ts_string)
I was getting this error due to a different reason.
I read a key from redis whose value is a json.
client.get(someid, function(error, somevalue){});
Now i was trying to access the fields inside somevalue (which is a string), like somevalue.start_time, without parsing to JSON object.
This was returning "undefined" which if passed to Date constructor, new Date(somevalue.start_time) returns "Invalid date".
So first using JSON.parse(somevalue) to get JSON object before accessing fields inside the json solved the problem.

How to deserialize JSON text into a date type using Windows 8 JSON.parse?

I'm building a Windows 8 Metro app (aka "Modern UI Style" or "Windows Store app") in HTML5/JavaScript consuming JSON Web Services and I'm bumping into the following issue: in which format should my JSON Web Services serialize dates for the Windows 8 Metro JSON.parse method to deserialize those in a date type?
I tried:
sending dates using the ISO-8601 format, (JSON.parse returns a string),
sending dates such as "/Date(1198908717056)/" as explained here (same result).
I'm starting to doubt that Windows 8's JSON.parse method supports dates as even when parsing the output of its own JSON.stringify method does not return a date type.
Example:
var d = new Date(); // => a new date
var str = JSON.stringify(d); // str is a string => "\"2012-07-10T14:44:00.000Z\""
var date2 = JSON.parse(str); // date2 is a string => "2012-07-10T14:44:00.000Z"
Here's how I got this working in a generic way (though it I'd rather find a format supported out-of-the-box by Windows 8's JSON.parse method):
On the server, I'm serializing my strings using:
date1.ToString("s");
This uses the ISO 8601 date format which is always the same, regardless of the culture used or the format provider supplied (see here for more information).
On the client-side, I specified a "reviver" callback to JSON.parse which looks for dates using a regexp and converts them into a date object automatically.
In the end, the deserialized object will contain actual JavaScript date types and not strings.
Here's a code sample:
var responseResult = JSON.parse(request.responseText, function dateReviver(key, value) {
if (typeof value === 'string') {
var re = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)$/
var result = re.exec(value);
if (result) {
return new Date(Date.UTC(+result[1], +result[2] - 1, +result[3], +result[4],+result[5], +result[6]));
}
});
Hope this helps,
Carl
This is not something that's unique to Windows 8's JSON.parse – it's the by-design behavior of the ECMA standard JSON parser. Therefore, there is (and can be) no "out-of-the-box support" for dates.
Per spec, JSON values can only be a String, Number, Boolean, Array, Object, or null. Dates are not supported. (IMO, this is an oversight on the part of the spec, but it's what we have to live with.)
Since there is no date type, your app has to work out how to handle dates on its own. The best way to handle this is to send dates as ISO 8601 strings (yyyy-MM-dd'T'HH:mm:ss'Z') or as milliseconds since the epoch (Jan 1 1970 00:00:00 UTC). The important part here is to make sure time is in UTC.
If performance is important, I would not use a reviver callback with JSON.parse. I did a lot of testing, and the overhead involved with invoking a function for every single property in your object cuts performance in half.
On the other hand, I was honestly surprised with how well testing a regex against every string value stood up against only parsing known property names. Just make sure you define the regex once, outside the loop!
Obviously, the absolute fastest ways to turn JSON values into Dates is if you know exactly what properties need to be parsed for dates. However, given the surprisingly good performance of the regex-based search methods, I don't think it's worth the extra complexity unless you really need the extra performance.
A note on using ISO strings vs milliseconds since epoch: tested independently, milliseconds wins. In IE, there's no difference, but Firefox really seems to struggle with ISO strings. Also note that the Date constructor takes milliseconds in all browsers. It also takes a the ISO string, but not in IE ≤ 8.

How can I parse this date string consistently across browsers?

I'm using Javascript's Date object to parse a string into a milliseconds timestamp. I'm using Date.parse(), and the strings I'm parsing are of the following format: "2012-07-06 12:59:36-0600"
Date.parse performs nicely in Chrome, parsing into the correct timestamp I'd anticipate. However, every other browser returns "NaN" when I run the string through Date.parse().
I know that the Date object implementation is browser-specific, but I'd like to find a javascript solution that's capable of parsing strings of this type for any browser. Any suggestions on what else I could use in Javascript to achieve this?
Convert the input to valid ISO 8601:
Date.parse("2012-07-06 12:59:36-0600".replace(' ', 'T'));
This was tested (and works) in Firefox.
Note:
Note that while time zone specifiers are used during date string
parsing to properly interpret the argument, they do not affect the
value returned, which is always the number of milliseconds between
January 1, 1970 00:00:00 UTC and the point in time represented by the
argument.
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/parse
Have you tried DateJS? Maybe you don't want to add another library, but it will solve your crossbrowser problem.
If the format is consistent, you can parse it yourself:
var date = "2012-07-06 12:59:36-0600";
function parseDatetime(input) {
var match = input.match(/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})([-+]\d{4})/);
match.shift(); // discard the "full match" index
match[2]--;
match[4] += parseInt(match[6],10);
return new Date(match[0],match[1],match[2],match[3],match[4],match[5]);
}

Categories

Resources