Multiple datepicker

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Richard Cornford

    #16
    Re: Multiple datepicker

    Grant Wagner wrote:[color=blue]
    > Richard Cornford wrote:[/color]
    <snip>[color=blue][color=green]
    >> ... is still very fractionally faster than
    >> the original - LastOfMonth -.[/color]
    >
    > And any execution time you might have gained was time lost
    > figuring all that out. The users' time waiting for the number
    > of days in a month is effectively "free" (since it is so short
    > on a per instance basis) and your time is not. I get it though,
    > producing the optimal algorithm for a given problem can be fun,
    > I do it myself sometimes.[/color]
    <snip>

    There is the (not everyone's idea of) fun aspect of optimum algorithms,
    but I find that activity useful anyway because recognising an efficient
    formulation in one context may make its applicability more obvious in
    another (where it may be more significant).

    In most respects the speed of date calculations in form validation is
    not significant, but 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). Not a problem in most current (and especially
    commercial) contexts but for something like a DHTML animation relating
    star positions to date a combination of a large (and known) date range
    and fast execution might be useful.

    <snip>[color=blue]
    > Again, don't get me wrong, I'm not criticizing at all. I'm just
    > contributing something to the discussion (I hope), but pointing
    > out that sometimes the "optimal" solution isn't necessarily the
    > "best" solution (especially if someone else is paying for the
    > "optimal" solution).[/color]
    <snip>

    I wouldn't argue with that.

    Richard.


    Comment

    • rh

      #17
      Re: Multiple datepicker

      "Richard Cornford" wrote:[color=blue]
      > Looking at the - LastOfMonth - function I observer that the
      > calculation - 31/12 - is done twice. The result must be the same each
      > time, and could be pre-calculated. Given that the result is truncated by
      > the OR zero operation and the range of - m - is limited, an
      > approximation of - 31/12 - should be sufficient, and - 2.58 - (or its
      > internal IEEE double representation) seems to be close enough to give
      > identical results for m == [0 to 11].[/color]

      I think I was hoping there would be a "compile-time" constant
      expression optimization, but I don't know whether such occurs in js
      implementations . Probably not.
      [color=blue]
      >
      > Next, - (m-1) - is calculated twice. If - +!m - were moved forward the
      > first occurrence of - (m-1) - could be replaced with - (--m) - and the
      > second replaced with just - m -, producing:-
      >
      > function LastOfMonth2(y, m) { // m = 0..11
      > return 29 + (m*2.58 | 0) + !m - ((--m)*2.58 | 0)
      > - ( !!(m) || 2
      > + ( !!((y & 3) || y & 15 && !(y % 25) )) ) ;
      > }
      >[/color]

      That's a good change.

      <..>
      [color=blue]
      > - and flipping some of the logic in the final expression produced:-
      >
      > function LastOfMonth2(y, m) { // m = 0..11
      > return 29 + (m*2.58 | 0) + !m - ((--m)*2.58 | 0)
      > - ( !!(m) || 2
      > + (!( !(y & 3)&&((y & 15)?(y % 25):y) )));
      > }
      >
      > - losing some of the logical NOT operations along the way.
      >[/color]

      Hey, tertiary conditionals aren't allowed!! :)
      [color=blue]
      > Those gives me identical results to - MonthLength - for all months in
      > years from -1000 to +3200 and is still very fractionally faster than
      > the original - LastOfMonth -.
      >[/color]

      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
      }


      ../rh

      Comment

      • Richard Cornford

        #18
        Re: Multiple datepicker

        rh wrote:[color=blue]
        > "Richard Cornford" wrote:[color=green]
        >> Looking at the - LastOfMonth - function I observer
        >> that the calculation - 31/12 - is done twice. ...[/color][/color]
        <snip>[color=blue]
        > I think I was hoping there would be a "compile-time" constant
        > expression optimization, but I don't know whether such occurs
        > in js implementations . Probably not.[/color]

        That is certainly a possible optimisation, but not something that I
        would necessarily expect from a JS implementation.

        <snip>[color=blue][color=green]
        >> - and flipping some of the logic in the final expression
        >> produced:-
        >> function LastOfMonth2(y, m) { // m = 0..11
        >> return 29 + (m*2.58 | 0) + !m - ((--m)*2.58 | 0)
        >> - ( !!(m) || 2
        >> + (!( !(y & 3)&&((y & 15)?(y % 25):y) )));
        >> }
        >>
        >> - losing some of the logical NOT operations along the way.[/color]
        >
        > Hey, tertiary conditionals aren't allowed!! :)[/color]

        I don't see why not. 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.

        <snip>[color=blue]
        > 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
        > }[/color]

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

        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.

        Richard.


        Comment

        • Dr John Stockton

          #19
          Re: Multiple datepicker

          JRS: In article <290e65a0.04072 82041.92560ad@p osting.google.c om>, dated
          Wed, 28 Jul 2004 21:41:15, seen in news:comp.lang. javascript, rh
          <codeHanger@yah oo.ca> posted :
          [color=blue]
          > The first difference calculation I used is
          >equivalent to that found at:
          >
          > <URL: http://users.aol.com/s6sj7gt/mikecal.htm>[/color]

          Interesting.
          [color=blue]
          >which also makes reference to similarity "in spirit" with Zeller's
          >congruence.
          >
          >While on the topic of js date calculations, a relatively
          >straightforwar d conversion of the C code to JavaScript found there
          >gives:
          >
          > function DayOfWeek(d,m,y ) { // d = 1..31; m = 1..12
          > return (d+=m<3? y--:y-2, d+4+ Math.floor(23*m/9)+ Math.floor(y/4)
          > - Math.floor(y/100)+Math.floor (y/400))%7;
          > }
          >
          >which (under very limited testing) appears to give the expected result
          >in IE.[/color]

          Now in the foot of zeller-c.htm; unless my testing has blundered, it is
          OK for all months in 401 years, and for at least some days in the months
          (the dependence on d is obviously correct).

          It could be shortened a bit, but not by a line, by using |0 instead of
          Math.floor.

          --
          © John Stockton, Surrey, UK. ?@merlyn.demon. co.uk Turnpike v4.00 MIME. ©
          Web <URL:http://www.merlyn.demo n.co.uk/> - FAQqish topics, acronyms & links;
          some Astro stuff via astro.htm, gravity0.htm; quotes.htm; pascal.htm; &c, &c.
          No Encoding. Quotes before replies. Snip well. Write clearly. Don't Mail News.

          Comment

          • Dr John Stockton

            #20
            Re: Multiple datepicker

            JRS: In article <41095FE1.EB1AE 92C@agricoreuni ted.com>, dated Thu, 29
            Jul 2004 20:36:12, seen in news:comp.lang. javascript, Grant Wagner
            <gwagner@agrico reunited.com> posted :
            [color=blue]
            >In fact, given the parameter choices (year and month), here is my
            >solution:
            >
            >function LastOfMonth3(y, m) { // m = 0..11
            > var d = new Date(y, (m + 1), 1);
            > if (d && d.constructor == Date) {
            > d.setDate(0);
            > return d.getDate();
            > } else {
            > return -1;
            > }
            >}
            >
            >Note that Netscape 4.78 does not properly handle constructing a
            >date with a day of 0, as a result, it is necessary to construct
            >the date for the first of the next month, then set it to zero.[/color]

            Does it handle new Date(y, m+1, 1, -9) ?

            (optimisation : 9 is the digit nearest to the - key)

            [color=blue]
            >Okay, I take it all back. Given these performance figures I'd use
            >Richard's solution :D.[/color]

            The real benefit is not in the result-code, but in what is learned in
            getting the that code.

            --
            © John Stockton, Surrey, UK. ?@merlyn.demon. co.uk Turnpike v4.00 MIME. ©
            Web <URL:http://www.merlyn.demo n.co.uk/> - FAQqish topics, acronyms & links;
            some Astro stuff via astro.htm, gravity0.htm; quotes.htm; pascal.htm; &c, &c.
            No Encoding. Quotes before replies. Snip well. Write clearly. Don't Mail News.

            Comment

            • Dr John Stockton

              #21
              Re: Multiple datepicker

              JRS: In article <cec3so$ien$1$8 300dec7@news.de mon.co.uk>, dated Fri, 30
              Jul 2004 01:14:14, seen in news:comp.lang. javascript, Richard Cornford
              <Richard@litote s.demon.co.uk> posted :
              [color=blue]
              > the Date object is not without its limitations.
              >There are, for example, implementations with a 32 bit milliseconds
              >representati on so they are range limited to between some time in 1901
              >and 2039 (as I recall).[/color]

              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 (news:comp.risk s).

              It would be worth noting such non-ECMA262 implementations ; with some
              mortgage look-aheads being 30 years, problems may appear by early 2008.

              --
              © John Stockton, Surrey, UK. ?@merlyn.demon. co.uk Turnpike v4.00 MIME. ©
              Web <URL:http://www.merlyn.demo n.co.uk/> - w. FAQish topics, links, acronyms
              PAS EXE etc : <URL:http://www.merlyn.demo n.co.uk/programs/> - see 00index.htm
              Dates - miscdate.htm moredate.htm js-dates.htm pas-time.htm critdate.htm etc.

              Comment

              • rh

                #22
                Re: Multiple datepicker

                "Richard Cornford" wrote:

                <..>
                [color=blue]
                > rh wrote:[color=green]
                > > Hey, tertiary conditionals aren't allowed!! :)[/color]
                >
                > I don't see why not.[/color]

                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).
                [color=blue]
                >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.
                >[/color]

                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).
                [color=blue]
                > <snip>[color=green]
                > > 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
                > > }[/color]
                >
                > 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) -).
                >[/color]

                Fully understood and appreciated.
                [color=blue]
                > 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.
                >[/color]

                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

                Comment

                • Lasse Reichstein Nielsen

                  #23
                  Re: Multiple datepicker

                  codeHanger@yaho o.ca (rh) writes:
                  [color=blue]
                  > 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:[/color]
                  [color=blue]
                  > 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
                  > }[/color]

                  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 LastOfMonthBitA rray(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!).

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

                  /L
                  --
                  Lasse Reichstein Nielsen - lrn@hotpop.com
                  DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleD OM.html>
                  'Faith without judgement merely degrades the spirit divine.'

                  Comment

                  • rh

                    #24
                    Re: Multiple datepicker

                    Lasse Reichstein Nielsen wrote:
                    [color=blue]
                    > codeHanger@yaho o.ca (rh) writes:
                    >[color=green]
                    > > 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:[/color]
                    >[color=green]
                    > > 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
                    > > }[/color]
                    >
                    > 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.
                    >[/color]

                    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
                    }

                    [color=blue]
                    > 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 LastOfMonthBitA rray(y,m) {
                    > return 28 + (((0xeefbb3>>(m <<1))&3) ||
                    > !((y&3)||((y&15 )&&!(y%25))) );
                    > }
                    > ---[/color]

                    Neat!!
                    [color=blue]
                    > 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 LastOfMonthExte rnalArray(y,m) {
                    > return arr[m] || 28+!((y&3)||((y &15)&&!(y%25))) ;
                    > }
                    > --[/color]

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

                    LastOfMonthBitA rray LastOfMonthExte rnalArray LastOfMonth3

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

                    ../rh

                    Comment

                    • rh

                      #25
                      Re: Multiple datepicker

                      Lasse Reichstein Nielsen wrote:
                      [color=blue]
                      > 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 LastOfMonthBitA rray(y,m) {
                      > return 28 + (((0xeefbb3>>(m <<1))&3) ||
                      > !((y&3)||((y&15 )&&!(y%25))) );
                      > }
                      > ---[/color]

                      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

                      Comment

                      • rh

                        #26
                        Re: Multiple datepicker

                        Lasse Reichstein Nielsen wrote:[color=blue]
                        > 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 LastOfMonthBitA rray(y,m) {
                        > return 28 + (((0xeefbb3>>(m <<1))&3) ||
                        > !((y&3)||((y&15 )&&!(y%25))) );
                        > }
                        > ---[/color]

                        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);
                        }
                        [color=blue]
                        > How efficient it is varies between browsers.[/color]

                        Similarly, although it appears that LastOfMonthBitA rray 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

                        Comment

                        • Richard Cornford

                          #27
                          Re: Multiple datepicker

                          rh wrote:
                          <snip>[color=blue]
                          > function LastOfMonth6(y, m) {
                          > return 29 +(m!=1||-!!(y&3||y&15&&! (y%25)))+(++m>> 3^m&1);
                          > }
                          >[color=green]
                          >> How efficient it is varies between browsers.[/color][/color]
                          <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.


                          Comment

                          • rh

                            #28
                            Re: Multiple datepicker

                            "Richard Cornford" wrote:

                            <..>
                            [color=blue]
                            > 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))) );
                            > }
                            >[/color]

                            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

                            Comment

                            Working...