Unexpected Javascript Date object implicit conversion - javascript

Why Javascript's Date object returns different value for implicit conversions?
Number conversion:
+new Date()
// returns 1456293356618 as expected
String conversion:
''+new Date()
// returns "Wed Feb 24 2016 09:26:28 GMT+0" but "1456293356618" as a string was expected
Where can I find the documentation on ECMAScript and the implementation on v8's source?
Edit: I'm not looking for the solution for the expected result. I want to find the documentation in the specs.

The + operator is overloaded. In:
+new Date()
it is treated as the unary + operator and coerces the value to Number. In:
'' + new Date() // note one value is a string
it is treated as the string concatenation operator and coerces the values to String. In:
5 + 6 // note both values are number
it is treated as the addition operator. Since the values are numbers, no coercion is necessary.
Note that whether + does addition or concatenation depends on the values and is described in ECMAScript 2015 §12.7.3.1 step 11.

I think you are refering to this Overview of Date Objects and Definitions of Abstract Operators, specifically Section 20.3.1.1
A Date object contains a Number indicating a particular instant in time to within a millisecond. Such a Number is called a time value. A time value may also be NaN, indicating that the Date object does not represent a specific instant of time.
This means that using math operations on a Date object will extract its Number value to work. That's why statements like +new Date() and Math.floor(new Date()) returns a Number.
As for '' + new Date(), the Date object returns its String value perhaps using its toString() function.

Related

Date comparison with primitive value. When it is bigger than primitive?

new Date('Sep 23, 2019') > 0 ----> true
new Date('Sep 23, 2019') > 's' ----> false
When date compared with primitive is greater or lower than primitive?
F.ex. I need to compare any date with a primitive which is lower than the date.
When Date is compared to Number, using one of the <, <=, > or >= operators, the Date is converted to milliseconds (as if .getTime() is invoked on it).
When Date is compared to String like "1569177000000", the string is converted to the number too.
When Date is compared to String like "s" that cannot be converted to a number, there is no ordering: you will always get false (any comparison to NaN is false).
See MDN:
For relational abstract comparisons (e.g., <=), the operands are first converted to primitives, then to the same type, before comparison.
Specifically, for >, see here in the specification, where LeftFirst is false.
It's pretty complicated, but both sides are converted to a primitive (preferably a number) if they aren't already. When this is done with a Date, it returns the date's Unix timestamp.
Because both sides are then numbers, it's straightforward after that - the interpreter just checks which number is larger.
You can use the valueOf function on date
// Convert date into primitive
new Date('Sep 23, 2019').valueOf() //1569177000000
you can use getTime() or date functions to convert date into primitive value and then use a comparison operator.

valid date is coming as output from invalida date Javascript [duplicate]

This question already has answers here:
JavaScript Detecting Valid Dates
(5 answers)
Why does Date.parse give incorrect results?
(11 answers)
Closed 6 years ago.
I am unable to understand why javascript is giving valid date equals to 1 dec date when giving invalid date? Is this behaviour incorporated in language for specific reason? because it must be invalid date for my use case
new Date("11/31/2017")
First of all, the Date constructor is not designed to validate input, or even to be picky. On the contrary, it's explicitly designed to create an instance at any cost, with creative rules like this:
Where Date is called as a constructor with more than one argument, if
values are greater than their logical range (e.g. 13 is provided as
the month value or 70 for the minute value), the adjacent value will
be adjusted. E.g. new Date(2013, 13, 1) is equivalent to new
Date(2014, 1, 1)
So if you really need to validate dates you need to look somewhere else.
As about 11/31/2017, the constructor expects this:
String value representing a date. The string should be in a format
recognized by the Date.parse() method (IETF-compliant RFC 2822
timestamps and also a version of ISO8601).
... which looks good. But this follows (emphasis mine):
parsing of date strings with the Date constructor (and Date.parse,
they are equivalent) is strongly discouraged due to browser
differences and inconsistencies.
And if we dig into Date.parse() docs we finally read this:
The ECMAScript specification states: If the String does not conform to
the standard format the function may fall back to any
implementation–specific heuristics or implementation–specific parsing
algorithm. Unrecognizable strings or dates containing illegal element
values in ISO formatted strings shall cause Date.parse() to return
NaN.
However, invalid values in date strings not recognized as ISO format
as defined by ECMA-262 may or may not result in NaN, depending on the
browser and values provided, e.g.:
// Non-ISO string with invalid date values
new Date('23/25/2014');
will be treated as a local date of 25 November, 2015 in Firefox 30 and
an invalid date in Safari 7
This fallback case is the one your date fell into.

How does Date's constructor overload the unary +?

I was reading this answer to Hidden Features of JavaScript? and was perplexed by this behaviour:
> new Date
< Fri Feb 26 2016 21:15:43 GMT-0500 (EST)
> +new Date
< 1456539382581
< 0 + new Date + 0
"0Fri Feb 26 2016 21:17:39 GMT-0500 (EST)0"
So, the Date constructor returns an object which, when converted to a number via unary (but not via addition) returns a number representing the Unix Epoch.
How is this possible? Reading about the topic, it seems like JS has no support for operator overloading, or only a small amount if overloading non-operator functions (add, toString, whatever) counts.
JS doesn't seem to have any such function for unary + specifically (or number coersion at all, it seems), so how is this done?
Unary operator + converts its operand to a number if it isn't already.
So +new Date is similar to Number(new Date).
new Date() // Fri Feb 26 2016 21:45:32 GMT-0500 (EST)
Number(new Date()) // 1456541132899
+new Date() // 1456541132899
Update:
What's special about the Date object that makes calling Number on it return the Unix time?
Date objects are based on a time value that is the number of milliseconds since 1 January, 1970 UTC (From MDN). So, it makes sense when we ask it to convert it to a number, it returns us milliseconds.
Automatic type conversion of Dates.
The primitive numeric value of a Date object, returned by Date.prototype.getValue() is a Unix time stamp, the number of milliseconds since 1 January, 1970 UTC and is the value of a Date object converted to a number.
When converting an object to number following a unary + operator, the javascript engine explicitly asks the object to return a number, by calling the objects internal toPrimitive method with a hint value of "number" as described in section 7.1.1 of the ES6 standard. This mechanism converts Date objects to milliseconds after a unary + sign in fairly standard fashion.
So how to explain how Date objects become converted to a string when used as the operand of a non unary plus?. It would seem that for the non-unary case, type conversion requests an object's primitive value without supplying a result type hint and . . . Date provides an exotic toPrimitive function which converts dates to string by default instead of to number. Date and Symbol are special in this regard and differ from most other objects.
Here is a little description about unary plus from MDN:
The unary plus operator precedes its operand and evaluates to its operand but attempts to converts it into a number, if it isn't already.
If the operator cannot parse a string/value, it returns NaN.

understanding javascript typeof date behaviour

Here's the code :
var d = new Date();
console.log(typeof(d+1)); //string
console.log(typeof(d-1)); // number
why does it produce different results?
(date + 1) returns a string, because of string concatenation
(date - 1) returns a number because of type conversion
Basically, a string plus a number returns a string with a number appended to the end. This is because the + operator is used to concatenate strings.
On the other hand, when you subtract a number from a string, JavaScript performs automatic type conversion.
Form more information, look here
http://www.w3schools.com/js/js_type_conversion.asp

Why does 'new Date() * 1' produce a Javascript timestamp?

I have the following methods of obtaining a timestamp:
new Date().valueOf()
new Date().getTime()
Date.parse(new Date())
new Date() * 1
But I'm confused: why am I able to get a timestamp using the last method?
This is because the Date() object can be converted directly to a number (the timestamp), and when applying mathematical operators to it JavaScript converts this for us.
An even quicker way to get the timestamp is to use the Unary Plus:
+new Date();
The unary plus operator precedes its operand and evaluates to its operand but attempts to converts it into a number, if it isn't already. Although unary negation (-) also can convert non-numbers, unary plus is the fastest and preferred way of converting something into a number, because it does not perform any other operations on the number.
– MDN's Unary Plus documentation.
The same applies with strings "1" * 1 equals 1 because JavaScript automatically converts "1" to a number because of the presence of the multiplication operator (*).
One of the weird things about JavaScript is that if you try and perform an operation between two variables, it will try to convert them to a type where it can perform this operation. But this can happen in different ways, so for example "2" * 2 === 4 is true, but so is "2" + 2 === "22" because it goes to the string version of the + operator first.
When you take a Date and try to do multiply or divide it, JavaScript will understand that as converting the Date to it's numerical timestamp value. Consequently the surprising outcome you see above.
However:
new Date() + 1
Results in "Tue Jul 07 2015 15:20:17 GMT+0100 (GMT Daylight Time)1" because the date can also be treated as a string.
This is one of the many quirks of JavaScript that will be helpful to understand when you run into that weird bug, but you would be well advised to avoid using in your code if you want to be able to understand it at a glance later ( spoiler warning: You do! )

Categories