MomentJS max and min return wrong values - javascript

I've encountered a strange result when comparing two MomentJS objects using max and min methods. They appear to return the wrong value.
For example, this code returns today rather than tomorrow:
moment().max(moment().add(1, 'd'))
http://jsfiddle.net/cGtbY/
Can anyone explain this behavior?

You misinterpret the meaning of min and max.
From the test suite (https://github.com/moment/moment/blob/develop/test/moment/min_max.js#L51):
equalMoment(test, now.max(future), now, "Now with the maximum of the future should be now");
The way to understand the meaning is: a.max(b) <= b (at latest, the result can be the second date).
The documentation has a clear quote:
Sometimes, server clocks are not quite in sync with client clocks. This ends up displaying humanized strings such as "in a few seconds" rather than "a few seconds ago". You can prevent that with moment#max()
The .max function is therefore the numerical minimum (selecting the earlier moment)

After looking in the source code of MomentJS 2.2.1, here's the source code of max():
max: function ( other ) {
other = moment.apply( null, arguments );
return other > this ? this : other;
},
Seems like they are returning this when other is later.. Weird..

Related

Exponential growth one-liner function fails on one test but not others?

Can anyone debug this for me? I've been staring at it and testing things for hours but can't seem to get it working. I'm starting to wonder whether the coding challenge web app is wrong and I'm right!
The task is this:
Find the number of generations it would take for a population p0 to surpass a max population p given that the population increases by percent% plus aug every generation
My one-liner is as follows:
nbYear = (p0, percent, aug, p) => {
return Array(999).fill().filter((_,i)=>Array(i+1).fill().map((_,j)=>j==0?p0:0).reduce((y,_)=>Math.round(y*percent/100+y+aug))<=p).length;
}
The code I've written passes on 100 tests but fails on one in particular (they don't disclose the input paramters on which it failed). All it says is that the function gave the output: 51 when it should have been 50
I've concluded that the one test for which it failed must have been for a value over 999.

Javascript Date/Time Parsing, UTC to Local Time Broke

I have a strange timezone/date formatting issue that recently came up with some new code, and what makes it more strange is that it only affects two months - August and September.
The code takes a date string with UTC time formatted like this:
10-06-2017 09:29:15
And converts it to a new string with the same format but with local time. The zeroPad function ensures that the format remains the same.
We implemented it in March and everything worked fine. It's within Classic ASP on IIS9/Server 2012.
As soon as we got to August, it broke. 08-10-2017 09:33:06 becomes 12-09-2016 20:33:06.
Can anyone see what I've done wrong?
function jsConvert(dateString) {
var patterns = dateString.split(/[\-\s:]/g);
var date = new Date(parseInt(patterns[2]),
parseInt(patterns[0]) - 1,
parseInt(patterns[1]),
parseInt(patterns[3]),
parseInt(patterns[4]),
parseInt(patterns[5]));
date.setTime(date.getTime() - getTimezoneOffset() * 60 * 1000);
var result = zeroPad(date.getMonth() + 1);
result += '-' + zeroPad(date.getDate());
result += '-' + date.getFullYear();
result += ' ' + zeroPad(date.getHours());
result += ':' + zeroPad(date.getMinutes());
result += ':' + zeroPad(date.getSeconds());
return result;
}
function zeroPad(number) {
return (number < 10) ? '0' + number : number;
}
What are the units of time in your getTimezoneOffset() function?
Your code is written as though the getTimezoneOffset() function returns a number of minutes, since you are multiplying by 60 and then 1000, to get millseconds.
But if your getTimezoneOffset is returning seconds, you will be over-doing the multiplication and therefore jumping back too far in time.
I think it would have to be milliseconds, to jump back the distance you are getting. #CBroe above mentions that perhaps you mean the builtin getTimezoneOffset function, which is indeed in minutes. Perhaps you have a separate getTimezoneOffset function defined in your code elsewhere, that returns an answer in milliseconds? In which case CBroe's answer fixes it.
My next suggestion would be to add lines of debugging code
For example, could you add the following?
At the beginning, add console.log("A",dateString).
After var patterns = dateString.split(/[\-\s:]/g); add a line console.log("B",patterns);.
After var date = ...(patterns[5])); add a line console.log("C",date);.
After date.setTime...1000); add a line console.log("D",date); console.log("E",getTimezoneOffset());.
If you show us the output of these lines, we should be able to pinpoint the problem easily. I have included item E because I am just wondering if there is yet another getTimezoneOffset() function in your system, which we are not aware of, or something. Seeing its value will help reassure everyone.
Meanwhile can you confirm the time zone you are running the code in? I am guessing it is in the USA rather than Europe, from your preference for putting month before the day?
So as it turns out this is a known, albeit obscure issue. It has to do with the fact that parseInt assumes that numbers with leading zeros are NOT base 10, but instead radix. It's well documented here: Javascript parseInt() with leading zeros
Once I made the change to:
parseInt(patterns[2]**, 10**);
All was good.
Thanks for the input.

Is there a built-in way to match ranges of values against ranges of values in JavaScript?

Let's say I have a value somewhere in a list items, whose value is a range from 3-10.
Then let's say I search using a range from say 5-15.
Since the lower end of the search range (5) falls within the range of the entry in the list (3-10), then it should match.
To do this I have to check if either range value in the search falls between the range values of the entry, and vice-verse.
While I have a working function for this, I was wondering if there is a common pattern or built-in way to do this kind of "range matrix" filtering in JavaScript. I don't even know if there is some actual nomenclature for this sort of thing.
Expected behavior: https://repl.it/Jz6c/0
Perhaps this is more of a Code Review question than a Stack Overflow question, but since we're here...
Based on your repl.it demo, it looks like you are asking if there is a simpler way to write this code:
var matchesRange = function(min, max, value) {
return value >= min && value <= max;
};
var matchesRangeMatrix = function(searchRange, targetRange) {
return matchesRange(searchRange.min, searchRange.max, targetRange.min) ||
matchesRange(searchRange.min, searchRange.max, targetRange.max) ||
matchesRange(targetRange.min, targetRange.max, searchRange.min) ||
matchesRange(targetRange.min, targetRange.max, searchRange.max);
};
where you call matchesRangeMatrix() with two object arguments, each of which has a min and max property.
This code makes a total of eight comparisons (four calls to matchesRange with two comparisons each).
You can do the whole thing with only two comparisons. Let's take out the matrix nomenclature, since that seems to make it sound more complicated than it is. Instead, how about a function called rangesOverlap():
function rangesOverlap( one, two ) {
return one.min < two.max && two.min < one.max;
}
That's all you need! Try this updated version of your repl.it and compare the results with your original.
If you're wondering how something so simple could work, I invite you to read this Hacker News discussion where I and a few other people debated this very topic. (I'm "Stratoscope" over there, but in particular look for a comment by "barrkel" about a third of the way down the page that lists a truth table for this problem.)
The context of that discussion was whether two appointments conflict or not. For example, appointments from 1-2pm and 2-3pm would not conflict even though the first one ends at the same time the second one begins. If your definition of overlapping ranges is different, so 1-2 and 2-3 would be considered to overlap, you should be able to do this by using <= instead of <:
function rangesOverlap( one, two ) {
return one.min <= two.max && two.min <= one.max;
}
But fair warning, I have not tested this version of the code.
Note that this isn't anything specific to JavaScript. The same question and the same solutions would apply to pretty much any programming language.

Pattern for treating zero as truthy

I often do stuff like this:
delay = delay || 24; // default delay of 24 hours
But I actually want to permit 0, and 0 || 24 === 24, instead of 0.
I'm wondering what the best pattern is to take user input from command line, or input from wherever, and do the same logic, only treat zero as truthy. I think the best pattern I've found is to do exactly that:
delay = (delay === 0 ? delay : (delay || 24));
Firstly, it permits things like 'abc', which is really wrong. But if I put in an early + it lets null slide through, which is also wrong. Secondly, very ugly, because it's clearly working around a language deficiency rather than doing something elegant with the language tools available. And not terribly readable. I'm doing something that is one line of thought and I'd like to do it in one actual line of code (not one line on technicality, like this is). But most other ideas I have had get even uglier:
delay = typeof delay === 'number' ? delay : 24; // but typeof NaN === 'number', so
delay = (!isNaN(delay) && typeof delay === 'number') ? delay : 24;
Note that this actually would work with string - if i were interested in accepting "", then
str = typeof str === 'string' ? str : 'default';
Since there is no NaN hole, and this is intelligently readable: if we have a string use that, otherwise use defaut.
Or this route:
delay = !isNaN(+delay) ? delay : 24; // fails on null
delay = !Number.isNaN(+delay) ? delay : 24; // still fails on null
// same thing with null check, now way uglier than we started
So I still like my hacky ternary and boolean logic better. Yes, I am looking for a condensed, one-line solution, since JS is rife with patterns and what would be clever in many other languages is well-recognized and readable and clear in JS. But I'm novice and trying to learn good patterns, hence, this question.
To be more explicit on the requirements:
0 needs to go to 0.
undefined needs to go to 24.
All actual numbers under typeof need to go to themselves, except NaN.
I strongly feel null should go to 24 because I very rarely use JS code that treats null and undefined differently on purpose. I feel it's better to keep it that way.
I slightly feel NaN should go to 24 because this more closely follows the || pattern. Falsy things should go to default.
'abc' should go to 24 - in my real application this is user input, and the user should not mistakenly type, say an email.
'123abc' should ideally go to 24, which conversion to Number catches but parseInt does not. I believe emails can start with numbers, so this drives the point home that this is something that ought to be caught.
Underscore or lodash answers are acceptable, in particular, to those of you who have lectured me on trying to be "clever" instead of writing a 2-3 line function. Those libraries exist precisely because there are many simple 2-3 line functions accomplishing the same thing in many places in many code bases all over the world, and it's far more readable and maintainable and robust to have those isolated as something like, say, _.readNumber. If no such method exists and I am able to come up with general enough requirements, I will submit a poll request myself and post that as answer to this question. This is something I like about JS - it has good ecosystem in that it's very possible to not have to write these utility methods. Since I'm particularly dealing with user input it may be better for me to write a slightly more specialized function and submit to commander.js, which is where I keep needing this.
Nowhere is int a requirement mentioned, so assuming you want any number, otherwise defaulting to 24, you could use this:
delay = isFinite(delay) ? delay : 24;
Or the safer:
delay = isFinite(parseFloat(delay)) ? delay : 24;
Or the Robert Lemon special:
delay = isFinite(parseFloat(delay))|0||24;
Of course having someone else understand the statement at a glance is more important than syntactic sugar. You're writing code to be understood by man and machine, not to ward off industrial spies.
The cleanest solution, by far:
delay = numberOrDefault(delay, 24);
// i = i || 24 doesn't work with i = 0, so this small func takes care of this.
function numberOrDefault(input, default) {
// a few lines handling your case
}
Don't try to abuse the language. Don't try to be clever. Don't try to obfuscate your code. It will serve noone but your ego, and will hurt the maintainability and readability of your code.
Functions are there and can have names. They're done exactly for the purpose you're looking for: give names to some bunch of instructions. Use them.
Assuming user input as some comments are saying, then it begins as any possible string so may as well test it.
delay = /^(\d+)$/.exec( delay ) ? Number( RegExp.$1 ) : 24;
Note this also protects against negative integers, which although not given as a requirement is nonsensical as a delay of time.
How about:
delay = isNaN(parseInt(delay, 10)) ? 24 : delay
(Edit: I now see this suggestion in the comments. That happened while I was working this out in a console, honest. :D)
If you absolutely require that strings with leading numbers not be valid, you're going to have to typecheck it:
delay = typeof(delay) === "number" && isNaN(parseInt(delay, 10)) ? 24 : delay
For example, if I use your idiom:
delay = (delay === 0 ? delay : (delay || 24));
And "delay" is `"123abc", your method will result in delay still being "123abc", since it is a truthy value.
Per Shmiddty's comment, if you aren't going to do the explicit type check, you need to use parseInt to ensure that you're actually setting delay to an integer type; even if 0 were truthy, doing delay = delay || 24 would set delay to a string value if one were passed without any kind of coercion or type check. Coercing to a number before doing the isNaN check ensures that anything that isn't a valid number (as parsed by parseInt; strings with leading numbers will still slip by) ensures that when you check isNaN, the result will mean "this is a valid number" or "this is not a valid number", rather than "this is NaN" or "this is anything except NaN".
If you're doing the type check, you don't strictly need the parseInt, but I'd argue that it's still a good idea from a semantics perspective, since it indicates that you expect and require an integer for that value.
don't do this, even though it can literally do exactly what you want:
Number.prototype.valueOf=function(){return this||"0";}
alert( 0 || 24 )// shows: 24
i think it would break other scripts, but it would be nice if we could do stuff like this at a block level in javascript...

Is it possible that Javascript keep same expression value?

I was wondering if javascript calculate (again) same expressions as it encounters them :
for example :
alert(new Date().getTime()+1-1+1-1+1-1+1-1+1-1+1-1+1-1+1-1+1-1+1-1-new Date().getTime())
output : 0
it's hard to test it like it but I thought that all the +/-1 will take it some time ( a tick) so I could see a difference.
But the answer is 0.
So ,
Is it zero because its just too fast or because JS treats the first new Date() as the same as the later one ?
GetTime() returns the number of milliseconds since the Unix epoch. Given that in theory an addition takes just one FLOP on a modern processor (which runs in the billions of FLOPS), I would say that it is extremely likely that the processor simply executes the entire statement in less than one millisecond.
Of course the way to really test this would be to run this billions of times in a loop and let the law of large numbers sort out the rest. To make things even easier, you could also try using alternating multiplication and division by an arbitrarily large number to make the execution take longer.
At any rate, keep in mind that in general, languages don't tend to optimise a function unless it always, or almost always makes sense to do so. In your specific case, how could the program reasonably assume that you aren't trying to measure how long the arithmetic takes? And what if you decomposed the single-line statement into several smaller statements? You would be doing the exact same thing... would it be reasonable in this case for the date/time function to act differently?
In short, I can think of many cases in which caching the date/time would cause serious problems in program execution. I can't imagine that the infinitesimally small performance boost provided by the caching would make up for them.
Yes, 10 + operations and 10 - operations are probably not going to take a millisecond. You can test it like this:
var c = (new Date().getTime() + calc() - new Date().getTime());
function calc() {
for (var i = 0; i < 100000000; i++) {}
return 0;
}
console.log(c);
And you really are going to get an output that doesn't equal zero.
To answer the crux of your question, which the other answers seem to be missing; no, it's not possible that the two calls to new Date() are optimized into the same thing. These two separate calls return distinct objects and for the engine to simply optimize the two distinct calls into one call would be completely invalid.
Consider, for example, if you had done this with a different method that returned a new Date object but this method included a 20 second delay in it (or an incremented return value each call) - the two getTime results should be thousands of ticks apart but your proposed "optimization" would cause them to return the same value.
What if the Date() function returned a random integer between 1 and 10,000?
There would be no way for the engine to know that the two calls should return the same value (which, incidentally, they shouldn't) without knowing what the returned values should be and, in order to know this, it would have to execute both methods anyway.
So, yes, it's because the calls are completed less than a millisecond apart.
That will depend on the JavaScript engine. If the code is being pre-compiled, your +/- 1 calculation might be optimized away.

Categories