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

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! )

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.

Unexpected Javascript Date object implicit conversion

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.

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.

Javascript date addition

I'm trying to do computations on Javascript dates, and the following thing happens:
var date = new Date()
undefined
date * 2
2815580408292
date - 10000
1407790194146
date / 6
234631700691
date + 10000
'Mon Aug 11 2014 13:50:04 GMT-0700 (PDT)10000'
It was going so well until I got to the +, where it turned from performing the operation on the milliseconds to concatenating strings. I need + to perform addition on milliseconds, not string concatenation. I'm doing this weird code-generation thing, so I can't do stuff like date.setTime(date.getTime() + 10000) without extraordinary effort and sullying the codebase. Is there some way of hacking Javascript so that + will add the milliseconds instead of concatenating as strings, or is there some date library that I can use + on its date objects and have it do addition rather than concatenation? I tried date.js but it concatenated too.
You mean like this?
date.getTime()+1000

What's wrong with this javascript date parsing? Why does js hate the number 8?

I've got an object containing dates in the format YYYY-MM-DD.
I'm extracting the various year, month and day integers so I can send them to a different API.
Here's an example of my method, using substr()
Demo: http://jsfiddle.net/AppSynergy/tELsw/
OK, it works. OH NO! - it doesn't - not quite.. What's wrong with the 3rd element, where the "08" in 8th April decides to be 0 instead?
If I change "08" to another integer e.g. "03", it's fine. But "08" causes issues..
This one is driving me crazy -- what's wrong?
If you can spot it, you deserve ice-cream.
08 is considered as an (invalid) octal literal by default.
You have to explicitly specify the radix in your call to parseInt() in order for this token to be considered as a decimal (base 10) number:
$("#debug").append(parseInt(date.substr(5, 2), 10) + " / ");
You need to use parseInt with radix/base of 10 since preceding 0 converts your number in octal notation.
parseInt(yourNum, 10);
Because of that reason, it turns out that you should ALWAYS specify base when using parseInt unless you are not working on base 10 numbers.
If string begins with "0", javascript will think the radix is eight (octal).
You need to tell javascript to parse the string by base of 10.
$.each(testData, function(i, val) {
// sort out the date format
var date = val.trim();
$('#debug').append(date+' ==><br />');
$('#debug').append(parseInt(date.substr(0, 4), 10)+' / ');
$('#debug').append(parseInt(date.substr(5, 2), 10)+' / ');
$('#debug').append(parseInt(date.substr(8, 2), 10)+'<br /><br />');
});

Categories