Multiple datepicker

D

Dr John Stockton

JRS: In article <[email protected]>, dated Fri, 30
Jul 2004 01:14:14, seen in Richard Cornford
the Date object is not without its limitations.
There are, for example, implementations with a 32 bit milliseconds
representation so they are range limited to between some time in 1901
and 2039 (as I recall).

Signed 32-bit seconds from 1970-01-01 00:00:00 GMT = 0 has a range of
1901-12-13 20:45:52 GMT to 2038-01-19 03:14:07 GMT inclusive.

The half-way point was 2004-01-10 13:37:04 GMT; failures were reported
in Risks Digest (
It would be worth noting such non-ECMA262 implementations; with some
mortgage look-aheads being 30 years, problems may appear by early 2008.
 
R

rh

:

I don't see why not.

Because part of the fun here was to see the whole thing succinctly and
efficiently accomplished with bit munging and (short-cut) logic (but
you may get your fun in other ways).
If the trade of between the less efficient tertiary
conditional and not having to do so many NOT operations were more
significant then it would be a good idea. In this context reducing the
number of NOT operations doesn't provide enough benefit to decide the
matter one way or the other.

And I agree that primarily is the determinant. Also to be considered
is, if there is an efficiency return, what is the trade-off in
complexity cost, and is it worth it?

This is a case where you're agreeing the tertiary conditional benefit
was not seen to be significant (before even getting to the complexity
question).
One of the reasons I was using the tertiary conditional, or one of my
other two proposals:-

(y & 3)||((y & 15 && !(y % 25))||!y)

(y & 3)||(((y & 15)||!y)&&!(y % 25))

- was to move the - !y - operation to the right of - (y & 3) - so that
in addition to only being done for one month in 12 it would then only be
done for one year in 4 (less, once it is to the right of - (y & 15) -).

Fully understood and appreciated.
My test still suggest that my version is (very fractionally) faster than
your latest, but I had to loop through 90,000 years to get a difference
of < 1% and a minority of tests came out the other way around so I
expect the influence of background tasks is too great to call this one
way or the other.

My point wasn't to say I can produce a faster version. It was that
your tertiary conditional gambit, in my view, couldn't be shown to pay
off, particularly given considerations I've stated above.

Regards,

../rh
 
L

Lasse Reichstein Nielsen

Here's another version that executes as fast, or marginally faster,
than LastOfMonth2 in IE, Netscape, Mozilla and Opera, and gives the
same results over a similar (wider) range in my tests:
function LastOfMonth3(y, m) { // m = 0..11
return 29 + !m + (m*2.58 | 0) - (--m*2.58 | 0)
- ( !!m || 2 + !y
+ ( !!( (y & 3) || y & 15 && !(y % 25) )) ) ; // ~ CGjrs
}

It looks almost ok, although it seems to claim that year 0 wasn't
a leap year. That's the only year I can see a difference for.

I though of another version, that used bit operations instead
of arithmetics (if I can't have an array, I can still code one
into an integer :)
---
function LastOfMonthBitArray(y,m) {
return 28 + (((0xeefbb3>>(m<<1))&3) ||
!((y&3)||((y&15)&&!(y%25))) );
}
---
How efficient it is varies between browsers. In IE, it's slower than
the one above, in Opera, it's faster, and in MozFF the fastest method
I have. In IE and Opera, this one is still fastest (even by a lot in
IE - for all months in all years between 0 and 5000, the following
function is almost four times as fast as the above!).
 
R

rh

Lasse said:
It looks almost ok, although it seems to claim that year 0 wasn't
a leap year. That's the only year I can see a difference for.

OK, I think I see where we went wrong. Richard used MonthLength to
test, and concluded that the year 0 had 28 days. However, that is
incorrect because MonthLength is really giving a value for 1900, not
the year 0 (as pointed out at the start of this thread, because of the
weird Date object behaviour for year parameters in the range 0-99 :().

So the whole effort to adjust for year 0 was misguided, and
LastOfMonth3 should really read:

function LastOfMonth3(y, m) { // m = 0..11
return 29 + !m + (m*2.58 | 0) - (--m*2.58 | 0)
- ( !!m || 2
+ ( !!( (y & 3) || y & 15 && !(y % 25) )) ) ; // ~ CGjrs
}

I though of another version, that used bit operations instead
of arithmetics (if I can't have an array, I can still code one
into an integer :)
---
function LastOfMonthBitArray(y,m) {
return 28 + (((0xeefbb3>>(m<<1))&3) ||
!((y&3)||((y&15)&&!(y%25))) );
}
---
Neat!!

How efficient it is varies between browsers. In IE, it's slower than
the one above, in Opera, it's faster, and in MozFF the fastest method
I have. In IE and Opera, this one is still fastest (even by a lot in
IE - for all months in all years between 0 and 5000, the following
function is almost four times as fast as the above!).

---
var arr = [31,,31,30,31,30,31,31,30,31,30,31];
function LastOfMonthExternalArray(y,m) {
return arr[m] || 28+!((y&3)||((y&15)&&!(y%25)));
}
--

My timing results (Win98) over all months in years -10,000 to 10,000
seem to be quite different from what you found:

LastOfMonthBitArray LastOfMonthExternalArray LastOfMonth3

IE 1150 1270 1480
NS 1310 1210 3740
Moz 1540 1590 3680
Op 3070 3090 6100

../rh
 
R

rh

Lasse said:
I though of another version, that used bit operations instead
of arithmetics (if I can't have an array, I can still code one
into an integer :)
---
function LastOfMonthBitArray(y,m) {
return 28 + (((0xeefbb3>>(m<<1))&3) ||
!((y&3)||((y&15)&&!(y%25))) );
}
---

And with yet another slightly different approach, and beating this
thing to death :), there's also:

function LastOfMonth4(y, m) {
return 31 + (m&8&&m&1||!(m&8||m&1)||!(m-7))
-(!!--m||2+(!!((y&3)||y&15&&!(y%25))));
}

and:

function LastOfMonth5(y, m) {
return 28 + (m&8&&m&1||!(m&8||m&1)||!(m-7))
+ (!!--m<<1||!((y&3)||((y&15)&&!(y%25))));


Not too surprisingly, both are slower than the integer bit-shift
lookup above. While the first of these seems to perform fine across
browsers, the latter is particulaly slow on Netscape/Mozilla.

../rh
 
R

rh

Lasse said:
I though of another version, that used bit operations instead
of arithmetics (if I can't have an array, I can still code one
into an integer :)
---
function LastOfMonthBitArray(y,m) {
return 28 + (((0xeefbb3>>(m<<1))&3) ||
!((y&3)||((y&15)&&!(y%25))) );
}
---

Not to be so easily outdone, and after mulling it a bit (yes, of
course that's a pun), I submit the following alternative bit-masher's
dream:

function LastOfMonth6(y, m) {
return 29 +(m!=1||-!!(y&3||y&15&&!(y%25)))+(++m>>3^m&1);
}
How efficient it is varies between browsers.

Similarly, although it appears that LastOfMonthBitArray still edges
out LastOfMonth6, but not by much.

By the way, I did find in doing timings that Opera perfomance degrades
as execution proceeds in a triple test sequence, where the other
broswers don't, and therefore the last in the sequence in Opera always
compares very poorly (as per my earlier performance table).

Regards,

../rh
 
R

Richard Cornford

rh wrote:
function LastOfMonth6(y, m) {
return 29 +(m!=1||-!!(y&3||y&15&&!(y%25)))+(++m>>3^m&1);
}
<snip>

I like the - (((++mm>>3)^m)&1) - logic. I observe that the number 30 is
binary - 11110 -, so - 30|((++m>>3)^m) - will be correct for all months
except February. Avoiding the - &1 - to mask out all but the low bit, as
the 4 set bits in 30 will negate the higher bits in - m -. Possibly:-

function LastOfMonth6b(y, m) {
return ((m!=1)&&(30|((++m>>3)^m)))||( 28+!((y&3)||((y&15)&&!(y%25))));
}

- not speed tested.

Richard.
 
R

rh

:

I like the - (((++mm>>3)^m)&1) - logic. I observe that the number 30 is
binary - 11110 -, so - 30|((++m>>3)^m) - will be correct for all months
except February. Avoiding the - &1 - to mask out all but the low bit, as
the 4 set bits in 30 will negate the higher bits in - m -. Possibly:-

function LastOfMonth6b(y, m) {
return ((m!=1)&&(30|((++m>>3)^m)))||( 28+!((y&3)||((y&15)&&!(y%25))));
}

And I like the innovation. By virtue of the same, it could also be
written as:

function LastOfMonth6c(y, m) {
return 28|(((m!=1)&&(2|((++m>>3)^m)))||((!((y&3)||((y&15)&&!(y%25))))));
}

While it's consistent, it undoes some of your added advantage on the
speed side. So I tested LastOfMonth6b and:

function LastOfMonth6d(y, m) {
return ((m!=1)&&(++m>>3^m|30))||(!((y&3)||((y&15)&&!(y%25))))|28;
}

which I found to be faster than LastOfMonth6b in all but IE.

Alas, that wascally Lasse still has it in all but Netscape, but thanks
to your help I find it's by a barely perceptible amount now in the
others. :)

../rh
 

Ask a Question

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.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top