L
Lasse Reichstein Nielsen
Mick White said:It would validate "dateOK(2000,2000,2000)", would it not?
Try (and see that it doesn't).
/L
Mick White said:It would validate "dateOK(2000,2000,2000)", would it not?
<snip>function DateOK2(Y, M, D) {
var ML = __months[M];
return D>0 && ML && (D<=ML ||
D==29 && Y%4==0 && (Y%100!=0 || Y%400==0) ) }
!( ayear & 3 || !( ayear & 15 ) && ayear % 25 )
Hmmm, that's very interesting. My first inclination was to say that
swapping those last two arguments was going to lead the last one being
evaluated (almost) all the time (since it's checking for divisibility by
400,
only true 1/400 of the time) but that's not correct since the 25 is doing
much of the work. That being the case, the situation becomes murkier
and depends much more on the efficiency of the various operations.
In particular, the last operation (the presumed expensive Mod 25)
is only going to be done 1/16th of the time as opposed to the 1/4 on
the top line. Now I'm real curious as to which wins out on time, if either.
<snip>The RmEv button, used above, gives much shorter times that the Eval
button - so thanks to Richard, who can possibly explain why!
Lasse Reichstein Nielsen wrote:
function DateOK2(Y, M, D) {
var ML = __months[M];
return D>0 && ML && (D<=ML ||
D==29 && Y%4==0 && (Y%100!=0 || Y%400==0) ) }
<snip>
The comparison operation on - ML - reminded me that a - <= - comparison
of an object with a number will call the object's - valueOf - method,
and so the possibility of putting an object with an overridden -
valueOf - method into index 2 of the months length array and have that
method return 28 or 29 based on the year:-
var DateOK3 = (function(){
var _y;
var __months = [
NaN,31,
{valueOf:function(){
return (((_y&3)||((_y&15)&&(!(_y%25))))?28:29);
}},
31,30,31,30,31,31,30,31,30,31
];
return (function(Y, M, D){
_y = Y;
return (D > 0) && (D <= __months[M]);
});
})();
Which takes advantage of undefined values from - __months[M] - type
converting to NaN for the comparison and so returns false from - (D <=
__months[M]) - when - M - is out of the appropriate range and has the
merit of always returning a boolean value.
Dr John Stockton said:Richard Cornford posted:Lasse Reichstein Nielsen wrote:
function DateOK2(Y, M, D) {
var ML = __months[M];
return D>0 && ML && (D<=ML ||
D==29 && Y%4==0 && (Y%100!=0 || Y%400==0) ) }
To avoid getting a result which is neither true nor false (but is
equivalent to false), I put !! before ML.
The comparison operation on - ML - reminded me that a - <= -
comparison of an object with a number will call the object's
- valueOf - method, and so the possibility of putting an object
with an overridden - valueOf - method into index 2 of the months
length array and have that method return 28 or 29 based on the
year:-
var DateOK3 = (function(){
var _y;
var __months = [
NaN,31,
{valueOf:function(){
return (((_y&3)||((_y&15)&&(!(_y%25))))?28:29);
}},
31,30,31,30,31,31,30,31,30,31
];
return (function(Y, M, D){
_y = Y;
return (D > 0) && (D <= __months[M]);
});
})();
Which takes advantage of undefined values from - __months[M] - type
converting to NaN for the comparison and so returns false from -
(D <= __months[M]) - when - M - is out of the appropriate range
and has the merit of always returning a boolean value.
Remarkable code. But it appears to work (though seems, tested with
2002-02-29, *marginally* slower than the best of the others). It's
testable in <URL:http://www.merlyn.demon.co.uk/js-dates4.htm#DVal>.
<snip>Alas, unless I wrap the above in a "normal" function, it's not
amenable to my usual code display technique.
news:comp.lang.javascript said:I make it 6-10% faster than Lasse's original (with !!ML). The version I
was using for testing was:-
var DateOK2b = (function(){
var __months = [NaN,31,28,31,30,31,30,31,31,30,31,30,31]
return (function(Y, M, D){
return (D <= __months[M])? (D > 0) :
(D==29) &&
(M==2) &&
!( ((Y&3)||((Y&15)&&(!(Y%25)))) );
});
})();
Dr said:Richard Cornford posted:I make it 6-10% faster than Lasse's original (with !!ML). The version
I was using for testing was:-
var DateOK2b = (function(){
var __months = [NaN,31,28,31,30,31,30,31,31,30,31,30,31]
return (function(Y, M, D){
return (D <= __months[M])? (D > 0) :
(D==29) &&
(M==2) &&
!( ((Y&3)||((Y&15)&&(!(Y%25)))) );
});
})();
OK. But && M==2 seems superfluous.
Should NaN (instead of
blank) be faster?
It's not obvious how best to speed-test - one should cover all 1461
good dates in 4 years, or 146097 in 400, but how many & which bad
ones?
I wonder why the using Date Object is so slow; possibly in order to
accommodate out-of-range fields.
I've been re-looking at Zeller's Concordance (and have been in
communication with one of his great-grandsons). In converting Y M D
to day-of-week, Zeller separated out the century, which seems simpler
for manual arithmetic; but, at least on a computer, ISTM better not
to :- <URL:http://www.merlyn.demon.co.uk/zeller-c.htm#DDCC>
boxes 1 & 3
Box 3 gives a much faster way of converting Y M D to a day count than
using a Date Object (at least, in my system).
That function is repeated at
<URL:http://www.merlyn.demon.co.uk/dayscale.htm#CDD> Box 1
and Box 2 gives an inverse. ISTM unlikely that one can do much better
for the forward function; but the inverse might be improvable ....
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.