Multiple datepicker

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Simon Templar

    Multiple datepicker

    Hi,

    I am trying to introduce a multiple datepicker into a webpage and the
    problem arises with the second picker. I tried to copy and adapt the code I
    employed for the first one, renaming the variables but it is simply unable
    to output any date to the database. The code for the first picker (which
    works fine) is as follows:



    <html>
    <head>
    <script type="text/javascript">

    var numDays = {
    '1': 31, '2': 28, '3': 31, '4': 30, '5': 31, '6': 30,
    '7': 31, '8': 31, '9': 30, '10': 31, '11': 30, '12': 31
    };

    function setDays(oMonthS el, oDaysSel, oYearSel)
    {
    var nDays, oDaysSelLgth, opt, i = 1;
    nDays = numDays[oMonthSel[oMonthSel.selec tedIndex].value];
    if (nDays == 28 && oYearSel[oYearSel.select edIndex].value % 4 == 0)
    ++nDays;
    oDaysSelLgth = oDaysSel.length ;
    if (nDays != oDaysSelLgth)
    {
    if (nDays < oDaysSelLgth)
    oDaysSel.length = nDays;
    else for (i; i < nDays - oDaysSelLgth + 1; i++)
    {
    opt = new Option(oDaysSel Lgth + i, oDaysSelLgth + i);
    oDaysSel.option s[oDaysSel.length] = opt;
    }
    }
    var oForm = oMonthSel.form;
    var month = oMonthSel.optio ns[oMonthSel.selec tedIndex].value;
    var day = oDaysSel.option s[oDaysSel.select edIndex].value;
    var year = oYearSel.option s[oYearSel.select edIndex].value;
    oForm.f_despara .value = month + '/' + day + '/' + year;
    }
    </head>
    <body>
    <form>
    <table>
    <tr>
    <td>
    <select name="day" class="buscar" id="day"
    onChange="setDa ys(month,this,y ear)">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
    <option value="5">5</option>
    <option value="6">6</option>
    <option value="7">7</option>
    <option value="8">8</option>
    <option value="9">9</option>
    <option value="10">10</option>
    <option value="11">11</option>
    <option value="12">12</option>
    <option value="13">13</option>
    <option value="14">14</option>
    <option value="15">15</option>
    <option value="16">16</option>
    <option value="17">17</option>
    <option value="18">18</option>
    <option value="19">19</option>
    <option value="20">20</option>
    <option value="21">21</option>
    <option value="22">22</option>
    <option value="23">23</option>
    <option value="24">24</option>
    <option value="25">25</option>
    <option value="26">26</option>
    <option value="27">27</option>
    <option value="28">28</option>
    <option value="29">29</option>
    <option value="30">30</option>
    <option value="31">31</option>
    <option selected>D&iacu te;a</option>
    </select></td>
    <td><select name="month" class="buscar" id="month"
    onchange="setDa ys(this,day,yea r)">
    <option value="1">Enero </option>
    <option value="2">Febre ro</option>
    <option value="3">Marzo </option>
    <option value="4">Abril </option>
    <option value="5">Mayo</option>
    <option value="6">Junio </option>
    <option value="7">Julio </option>
    <option value="8">Agost o</option>
    <option value="9">Septi embre</option>
    <option value="10">Octu bre</option>
    <option value="11">Novi embre</option>
    <option value="12">Dici embre</option>
    <option selected>Mes</option>
    </select></td>
    <td><select name="year" class="buscar" id="year"
    onchange="setDa ys(month,day,th is)">
    <option value="1995">19 95</option>
    <option value="1996">19 96</option>
    <option value="1997">19 97</option>
    <option value="1998">19 98</option>
    <option value="1999">19 99</option>
    <option value="2000">20 00</option>
    <option value="2001">20 01</option>
    <option value="2002">20 02</option>
    <option value="2003">20 03</option>
    <option value="2004">20 04</option>
    <option selected>A&ntil de;o</option>
    </select>
    <input type="hidden" name="f_despara " value="" />
    </td>
    </tr>
    </table>
    </form>
    </body>
    </html>




    Then I tried to add a second date picker and never worked. I tried this way:
    I added another function to the script:



    function setDays2(oMonth 2Sel, oDays2Sel, oYear2Sel)
    {
    var nDays2, oDays2SelLgth, opt2, i2 = 1;
    nDays2 = numDays[oMonth2Sel[oMonth2Sel.sele ctedIndex].value];
    if (nDays2 == 28 && oYear2Sel[oYear2Sel.selec tedIndex].value % 4 == 0)
    ++nDays2;
    oDays2SelLgth = oDays2Sel.lengt h;
    if (nDays2 != oDays2SelLgth)
    {
    if (nDays2 < oDays2SelLgth)
    oDays2Sel.lengt h = nDays2;
    else for (i2; i2 < nDays2 - oDays2SelLgth + 1; i2++)
    {
    opt = new Option(oDays2Se lLgth + i2, oDays2SelLgth + i2);
    oDays2Sel.optio ns[oDays2Sel.lengt h] = opt2;
    }
    }
    var oForm2 = oMonth2Sel.form ;
    var month2 = oMonth2Sel.opti ons[oMonth2Sel.sele ctedIndex].value;
    var day2 = oDays2Sel.optio ns[oDays2Sel.selec tedIndex].value;
    var year2 = oYear2Sel.optio ns[oYear2Sel.selec tedIndex].value;
    oForm.f_vac1.va lue = month2 + '/' + day2 + '/' + year2;
    }



    and then added the date picker fields to the form:



    <tr>
    <td><select name="day2" class="buscar" id="day2"
    onChange="setDa ys2(month2,this ,year2)">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
    <option value="5">5</option>
    <option value="6">6</option>
    <option value="7">7</option>
    <option value="8">8</option>
    <option value="9">9</option>
    <option value="10">10</option>
    <option value="11">11</option>
    <option value="12">12</option>
    <option value="13">13</option>
    <option value="14">14</option>
    <option value="15">15</option>
    <option value="16">16</option>
    <option value="17">17</option>
    <option value="18">18</option>
    <option value="19">19</option>
    <option value="20">20</option>
    <option value="21">21</option>
    <option value="22">22</option>
    <option value="23">23</option>
    <option value="24">24</option>
    <option value="25">25</option>
    <option value="26">26</option>
    <option value="27">27</option>
    <option value="28">28</option>
    <option value="29">29</option>
    <option value="30">30</option>
    <option value="31">31</option>
    <option selected>D&iacu te;a</option>
    </select></td>
    <td><select name="month2" class="buscar" id="month2"
    onchange="setDa ys2(this,day2,y ear2)">
    <option value="1">Enero </option>
    <option value="2">Febre ro</option>
    <option value="3">Marzo </option>
    <option value="4">Abril </option>
    <option value="5">Mayo</option>
    <option value="6">Junio </option>
    <option value="7">Julio </option>
    <option value="8">Agost o</option>
    <option value="9">Septi embre</option>
    <option value="10">Octu bre</option>
    <option value="11">Novi embre</option>
    <option value="12">Dici embre</option>
    <option selected>Mes</option>
    </select></td>
    <td><select name="year2" class="buscar" id="year2"
    onchange="setDa ys2(month2,day2 ,this)">
    <option value="1995">19 95</option>
    <option value="1996">19 96</option>
    <option value="1997">19 97</option>
    <option value="1998">19 98</option>
    <option value="1999">19 99</option>
    <option value="2000">20 00</option>
    <option value="2001">20 01</option>
    <option value="2002">20 02</option>
    <option value="2003">20 03</option>
    <option value="2004">20 04</option>
    <option selected>A&ntil de;o</option>
    </select>
    <input type="hidden" name="f_vac1" value="" />
    </td>
    </tr>



    The script works well avoiding invalid date on the form but never passes the
    value to the database.

    Could someone help me?

    Thanks in advance,

    Gustavo


  • Thomas 'PointedEars' Lahn

    #2
    Re: Multiple datepicker

    Simon Templar wrote:[color=blue]
    > <html>[/color]

    This is not Valid HTML. <http://validator.w3.or g/>
    [color=blue]
    > <head>
    > <script type="text/javascript">
    >
    > var numDays = {
    > '1': 31, '2': 28,[/color]

    In leap years, February has 29 days.

    '3': 31, '4': 30, '5': 31, '6': 30,[color=blue]
    > '7': 31, '8': 31, '9': 30, '10': 31, '11': 30, '12': 31
    > };[/color]

    The number of days a month has can be determined reliably (including
    leap years) using Date objects:

    /**
    * Returns the number of days of a month.
    *
    * @author
    * (C) 2004 Thomas Lahn <date.js@Pointe dEars.de>
    * @partof
    * <http://pointedears.de/scripts/date.js>
    * @argument Date d
    * Date object to hold the month.
    * @return type number
    * The number of the days of the month,
    * -1 if no Date object has been passed.
    */
    function getDaysOfMonth( d)
    {
    if (d && d.constructor == Date)
    {
    // make a "copy" of the passed Date object so that it does not change
    var y;
    if (d.getFullYear)
    {
    y = d.getFullYear() ;
    }
    else
    {
    y = d.getYear();
    if (y < 1900)
    {
    y += 1900;
    }
    }

    var d2 = new Date(y, d.getMonth() + 1, d.getDate());

    // the day before the first day of the next month
    // is the last day of the current month
    d2.setDate(0);

    return d2.getDate();
    }

    return -1;
    }


    For the rest of your source code, I suggest you put a testcase in a Valid
    HTML document (if it contains server-side scripting, put the source code
    of that in an unparsed HTML document [.phps and the like] or a text file)
    instead of dumping more than 200 uncommented (and some even unnecessary)
    lines of it to a public newsgroup.


    PointedEars

    Comment

    • Lasse Reichstein Nielsen

      #3
      Re: Multiple datepicker

      Thomas 'PointedEars' Lahn <PointedEars@we b.de> writes:
      [color=blue]
      > function getDaysOfMonth( d)[/color]

      Might as well pass the year and month number alone, no need for a full
      date.
      [color=blue]
      > if (d.getFullYear)[/color]

      While getFullYear is convenient, you are no better off if it turns
      out to be missing. Just do:
      ---
      function getDaysOfMonth( year, month) { // month==1 is January
      if (year >= 0 && year < 100) {
      year += 100;
      month -= 1200;
      }
      return new Date(year, month, 0).getDate();
      }
      ---
      The correction for year/month seems to be necessary, otherwise the
      function will fail for the year 0, as it (and everything else between
      0 and 99) will have 1900 added to the year. However, the year 0 was a
      leap year (according to the Javascript the Date object), while 1900
      wasn't.

      /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

      • Dr John Stockton

        #4
        Re: Multiple datepicker

        JRS: In article <41048887.10809 03@PointedEars. de>, dated Mon, 26 Jul
        2004 06:28:55, seen in news:comp.lang. javascript, Thomas 'PointedEars'
        Lahn <PointedEars@we b.de> posted :[color=blue]
        >Simon Templar wrote:[/color]
        [color=blue][color=green]
        >> var numDays = {
        >> '1': 31, '2': 28,[/color]
        >
        >In leap years, February has 29 days.[/color]

        If you had troubled to read the Sainted one's code before responding,
        you would have seen that he is aware of that; his code fully complies
        with the Julian Calendar, AFAICS.

        [color=blue]
        >
        >'3': 31, '4': 30, '5': 31, '6': 30,[color=green]
        >> '7': 31, '8': 31, '9': 30, '10': 31, '11': 30, '12': 31
        >> };[/color]
        >
        >The number of days a month has can be determined reliably (including
        >leap years) using Date objects:
        >
        > /**
        > * Returns the number of days of a month.[/color]

        Only for fully-Gregorian months, of course.

        [color=blue]
        > *
        > * @author
        > * (C) 2004 Thomas Lahn <date.js@Pointe dEars.de>[/color]

        YCKI.

        [color=blue]
        > y = d.getYear();
        > if (y < 1900)
        > {
        > y += 1900;
        > }
        > }[/color]

        Incorrect in some systems. I have recently posted, and no-one has
        refuted, a brief and reliable means of getting the full year from any
        plausible getYear().

        [color=blue]
        > d2.setDate(0);[/color]

        Possible failure in Mac NS 4.




        Recent discussion in this group should have indicated to you a
        considerably quicker, and shorter, method.


        Simon : see FAQ; it leads indirectly to
        <URL:http://www.merlyn.demo n.co.uk/js-date4.htm#MaYl> which has

        function TailOfMonth(y, m) {
        if (m==1) return 28 + (y%4 == 0) // 1901-2099
        return [31,0,31,30,31,3 0, 31,31,30,31,30, 31][m] }

        which is rather like what you already have. On my system, it is about 5
        times faster than the best I know using a Date Object, and that is
        nearly twice as fast as one like what TL gave.

        Modification for all Gregorian years should not slow it much.

        BOTF.

        --
        © John Stockton, Surrey, UK. ?@merlyn.demon. co.uk Turnpike v4.00 IE 4 ©
        <URL:http://jibbering.com/faq/> JL / RC : FAQ for news:comp.lang. javascript
        <URL:http://www.merlyn.demo n.co.uk/js-index.htm> jscr maths, dates, sources.
        <URL:http://www.merlyn.demo n.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.

        Comment

        • Mick White

          #5
          Re: Multiple datepicker

          Dr John Stockton wrote:
          [color=blue]
          > JRS: In article <41048887.10809 03@PointedEars. de>, dated Mon, 26 Jul
          > 2004 06:28:55, seen in news:comp.lang. javascript, Thomas 'PointedEars'
          > Lahn <PointedEars@we b.de> posted :
          >[color=green]
          >>Simon Templar wrote:[/color]
          >
          >[color=green][color=darkred]
          >>>var numDays = {
          >>>'1': 31, '2': 28,[/color]
          >>
          >>In leap years, February has 29 days.[/color]
          >
          >
          > If you had troubled to read the Sainted one's code before responding,
          > you would have seen that he is aware of that; his code fully complies
          > with the Julian Calendar, AFAICS.
          >
          >
          >[color=green]
          >>'3': 31, '4': 30, '5': 31, '6': 30,
          >>[color=darkred]
          >>>'7': 31, '8': 31, '9': 30, '10': 31, '11': 30, '12': 31
          >>>};[/color]
          >>
          >>The number of days a month has can be determined reliably (including
          >>leap years) using Date objects:
          >>
          >> /**
          >> * Returns the number of days of a month.[/color]
          >
          >
          > Only for fully-Gregorian months, of course.
          >
          >
          >[color=green]
          >> *
          >> * @author
          >> * (C) 2004 Thomas Lahn <date.js@Pointe dEars.de>[/color]
          >
          >
          > YCKI.
          >
          >
          >[color=green]
          >> y = d.getYear();
          >> if (y < 1900)
          >> {
          >> y += 1900;
          >> }
          >> }[/color]
          >
          >
          > Incorrect in some systems. I have recently posted, and no-one has
          > refuted, a brief and reliable means of getting the full year from any
          > plausible getYear().
          >
          >
          >[color=green]
          >> d2.setDate(0);[/color]
          >
          >
          > Possible failure in Mac NS 4.
          >
          >
          >
          >
          > Recent discussion in this group should have indicated to you a
          > considerably quicker, and shorter, method.
          >
          >
          > Simon : see FAQ; it leads indirectly to
          > <URL:http://www.merlyn.demo n.co.uk/js-date4.htm#MaYl> which has
          >
          > function TailOfMonth(y, m) {
          > if (m==1) return 28 + (y%4 == 0) // 1901-2099
          > return [31,0,31,30,31,3 0, 31,31,30,31,30, 31][m] }[/color]


          function TailOfMonth(y, m) {
          return [31,y%4 == 0?29:28,31,30,3 1,30, 31,31,30,31,30, 31][m] }

          Mick
          [color=blue]
          >
          > which is rather like what you already have. On my system, it is about 5
          > times faster than the best I know using a Date Object, and that is
          > nearly twice as fast as one like what TL gave.
          >
          > Modification for all Gregorian years should not slow it much.
          >
          > BOTF.
          >[/color]

          Comment

          • Lasse Reichstein Nielsen

            #6
            Re: Multiple datepicker

            Dr John Stockton <spam@merlyn.de mon.co.uk> writes:
            [color=blue]
            > function TailOfMonth(y, m) {
            > if (m==1) return 28 + (y%4 == 0) // 1901-2099
            > return [31,0,31,30,31,3 0, 31,31,30,31,30, 31][m] }
            >
            > which is rather like what you already have. On my system, it is about 5
            > times faster than the best I know using a Date Object, and that is
            > nearly twice as fast as one like what TL gave.[/color]

            In my versions of IE, Opera, that versions is about as
            fast as the Date based version I suggested (not entirely sure for
            Mozilla, because it asked me if I wanted to stop the script because it
            had run too long .. but it seems the Date object is *very* slow).

            If speed is of the essence, not creating an array for each call is a
            great saving in both Mozilla and Opera (and is marginally faster in IE
            as well). This version:

            var months = [31,,31,30,31,30 ,31,31,30,31,30 ,31];
            function lengthOfMonth(y ,m) { // m==0 is January
            return arr[m] || ((!(y%4) && (!!(y%25) || !(y%400)))+28);
            }

            is very fast in both Opera and Mozilla (in a loop, it takes almost no
            time over a no-op function), and it isn't slower in IE.

            /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

            • Dr John Stockton

              #7
              Re: Multiple datepicker

              JRS: In article <smbeya5v.fsf@h otpop.com>, dated Mon, 26 Jul 2004
              19:02:04, seen in news:comp.lang. javascript, Lasse Reichstein Nielsen
              <lrn@hotpop.com > posted :[color=blue]
              >Thomas 'PointedEars' Lahn <PointedEars@we b.de> writes:
              >[color=green]
              >> function getDaysOfMonth( d)[/color]
              >
              >Might as well pass the year and month number alone, no need for a full
              >date.
              >[color=green]
              >> if (d.getFullYear)[/color]
              >
              >While getFullYear is convenient, you are no better off if it turns
              >out to be missing. Just do:
              >---
              > function getDaysOfMonth( year, month) { // month==1 is January
              > if (year >= 0 && year < 100) {
              > year += 100;
              > month -= 1200;
              > }
              > return new Date(year, month, 0).getDate();
              > }
              >---
              >The correction for year/month seems to be necessary, otherwise the
              >function will fail for the year 0, as it (and everything else between
              >0 and 99) will have 1900 added to the year. However, the year 0 was a
              >leap year (according to the Javascript the Date object), while 1900
              >wasn't.[/color]

              The correction is over-complex, since for this purpose it is only
              necessary to add 400 years (and only for February; and only for Year 0,
              I think). The year only needs to be correct modulo 400.

              Or add a multiple thereof; so, since there is probably little interest
              in month-lengths before BC 10000 or after AD 250000, the best is just to
              add 10000 years unconditionally - assuming that new Date is sensibly
              written.

              Year 0 (BC 1) was a leap year on the Gregorian & Julian calendars; but
              not in actuality, since the Romans had been bad at counting up to 4.


              For y >= 0, full Gregorian,

              function LastOfMonth(y, m) { // m = 0..11 // new, undertested.
              if (m==1) return 29 - ( y & 3 || y & 15 && !(y % 25) ) // ~ CGjrs
              return [31,0,31,30,31,3 0, 31,31,30,31,30, 31][m] }

              --
              © 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

              • Lasse Reichstein Nielsen

                #8
                Re: Multiple datepicker

                Dr John Stockton <spam@merlyn.de mon.co.uk> writes:
                [color=blue]
                > The correction is over-complex,[/color]

                Absolutely.
                [color=blue]
                > since for this purpose it is only necessary to add 400 years (and
                > only for February; and only for Year 0, I think). The year only
                > needs to be correct modulo 400.[/color]

                Indeed. Only the year 0 fails, because only years between 0 and 99
                are affected by the year-rewriting, and of those, only 0 differst
                from the year + 1900.

                The reason (well, excuse) for doing it this way was to not need to
                know how the month lengths are calculated. That is left entirely
                up to the Date object. The only rewriting was to avoid the problem
                with years 0-99 as arguments to the constructor.
                [color=blue]
                > For y >= 0, full Gregorian,
                >
                > function LastOfMonth(y, m) { // m = 0..11 // new, undertested.
                > if (m==1) return 29 - ( y & 3 || y & 15 && !(y % 25) ) // ~ CGjrs
                > return [31,0,31,30,31,3 0, 31,31,30,31,30, 31][m] }[/color]

                Except
                LastOfMonth(200 2,1) == 27
                and
                LastOfMonth(200 3,1) == 26
                since (y&3) becomes 2 and 3 in those years. If you change it to:

                function LastOfMonth(y, m) { // m = 0..11 // new, undertested.
                if (m==1) return 29 - ( !!(y & 3) || y & 15 && !(y % 25) ) // ~ CGjrs
                return [31,0,31,30,31,3 0, 31,31,30,31,30, 31][m] }

                then it seems to work (the bit-fiddling is impressive :).

                For efficiency, you only need to do the extra calculation for m == 1.

                /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

                • Dr John Stockton

                  #9
                  Re: Multiple datepicker

                  JRS: In article <bri2xtiy.fsf@h otpop.com>, dated Tue, 27 Jul 2004
                  01:01:25, seen in news:comp.lang. javascript, Lasse Reichstein Nielsen
                  <lrn@hotpop.com > posted :[color=blue]
                  >Dr John Stockton <spam@merlyn.de mon.co.uk> writes:
                  >[color=green]
                  >> The correction is over-complex,[/color]
                  >
                  >Absolutely.
                  >[color=green]
                  >> since for this purpose it is only necessary to add 400 years (and
                  >> only for February; and only for Year 0, I think). The year only
                  >> needs to be correct modulo 400.[/color]
                  >
                  >Indeed. Only the year 0 fails, because only years between 0 and 99
                  >are affected by the year-rewriting, and of those, only 0 differst
                  >from the year + 1900.
                  >
                  >The reason (well, excuse) for doing it this way was to not need to
                  >know how the month lengths are calculated. That is left entirely
                  >up to the Date object. The only rewriting was to avoid the problem
                  >with years 0-99 as arguments to the constructor.
                  >[color=green]
                  >> For y >= 0, full Gregorian,
                  >>
                  >> function LastOfMonth(y, m) { // m = 0..11 // new, undertested.
                  >> if (m==1) return 29 - ( y & 3 || y & 15 && !(y % 25) ) // ~ CGjrs
                  >> return [31,0,31,30,31,3 0, 31,31,30,31,30, 31][m] }[/color]
                  >
                  >Except
                  > LastOfMonth(200 2,1) == 27
                  >and
                  > LastOfMonth(200 3,1) == 26
                  >since (y&3) becomes 2 and 3 in those years. If you change it to:
                  >
                  > function LastOfMonth(y, m) { // m = 0..11 // new, undertested.
                  > if (m==1) return 29 - ( !!(y & 3) || y & 15 && !(y % 25) ) // ~ CGjrs
                  > return [31,0,31,30,31,3 0, 31,31,30,31,30, 31][m] }
                  >
                  >then it seems to work (the bit-fiddling is impressive :).[/color]


                  Yes, the tests that were exhaustive enough for the older methods proved
                  inadequate. I now test every month in 400 years, for safety.

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

                  looks nicer to me, and tests OK in js-dates4.htm. Thanks.


                  JRS: In article <iscay22i.fsf@h otpop.com>, dated Mon, 26 Jul 2004
                  21:56:53, seen in news:comp.lang. javascript, Lasse Reichstein Nielsen
                  <lrn@hotpop.com > posted :
                  [color=blue]
                  >If speed is of the essence, not creating an array for each call is a
                  >great saving in both Mozilla and Opera (and is marginally faster in IE
                  >as well).[/color]

                  That will take a while to put neatly into page 4; I have several very
                  similar arrays, and only the unnecessary differences can be ignored in
                  merging them.

                  --
                  © John Stockton, Surrey, UK. ?@merlyn.demon. co.uk Turnpike v4.00 IE 4 ©
                  <URL:http://jibbering.com/faq/> JL / RC : FAQ for news:comp.lang. javascript
                  <URL:http://www.merlyn.demo n.co.uk/js-index.htm> jscr maths, dates, sources.
                  <URL:http://www.merlyn.demo n.co.uk/> TP/BP/Delphi/jscr/&c, FAQ items, links.

                  Comment

                  • rh

                    #10
                    Re: Multiple datepicker

                    Dr John Stockton <spam@merlyn.de mon.co.uk> wrote:
                    [color=blue]
                    > JRS: In article <iscay22i.fsf@h otpop.com>, dated Mon, 26 Jul 2004
                    > 21:56:53, seen in news:comp.lang. javascript, Lasse Reichstein Nielsen
                    > <lrn@hotpop.com > posted :
                    >[color=green]
                    > >If speed is of the essence, not creating an array for each call is a
                    > >great saving in both Mozilla and Opera (and is marginally faster in IE
                    > >as well).[/color]
                    >[/color]

                    You may also wish to consider something along the lines of:

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

                    which cadges from Zeller (at the very least, makes use of a function I
                    came across a couple of years ago in an implementation of Zeller's
                    congruence). It's considerably more efficient than creating the lookup
                    array within the js function, but will be slower (although perhaps
                    still not all that much slower) than your table lookup with the array
                    created outside.

                    ../rh

                    Comment

                    • Dr John Stockton

                      #11
                      Re: Multiple datepicker

                      JRS: In article <290e65a0.04072 71842.699220bd@ posting.google. com>,
                      dated Tue, 27 Jul 2004 19:42:56, seen in news:comp.lang. javascript, rh
                      <codeHanger@yah oo.ca> posted :
                      [color=blue]
                      >You may also wish to consider something along the lines of:
                      >
                      > function LastOfMonth(y, m) { // m = 0..11
                      > return 29 + (m*31/12 | 0) - ((m-1)*31/12 | 0) + !m
                      > - ( !! (m-1) || 2
                      > + ( !!((y & 3) || y & 15 && !(y % 25) )) ) ; // ~ CGjrs }
                      >
                      >which cadges from Zeller (at the very least, makes use of a function I
                      >came across a couple of years ago in an implementation of Zeller's
                      >congruence). It's considerably more efficient than creating the lookup
                      >array within the js function, but will be slower (although perhaps
                      >still not all that much slower) than your table lookup with the array
                      >created outside.[/color]

                      Moving the final } to before the comment mark helps. Then, assuming the
                      tests in js-date4.htm are now adequate, it is correct over a full cycle
                      of 400 years Gregorian and in IE4 is 2-3 times faster than the best of
                      the others there.

                      It does not, at first sight, though, look much like Zeller's Congruence.
                      though it has in common the idea of using arithmetic instead of table
                      lookup. Have you seen my Zeller pages, via <URL:http://www.merlyn.demon
                      ..co.uk/zeller-c.htm> etc. ?


                      function MonthLength(y, m) { // m = 0..11
                      return new Date(y, m+1, 1, -9).getDate() }

                      is the best I've found for a function which can immediately be seen to
                      be correct, though; ten times slower.

                      --
                      © 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

                        #12
                        Re: Multiple datepicker

                        Dr John Stockton wrote:
                        [color=blue]
                        > Moving the final } to before the comment mark helps.[/color]

                        Thats well and good. It seems that a newline got dropped in the
                        posting.
                        [color=blue]
                        > Then, assuming the
                        > tests in js-date4.htm are now adequate, it is correct over a full cycle
                        > of 400 years Gregorian and in IE4 is 2-3 times faster than the best of
                        > the others there.
                        >
                        > It does not, at first sight, though, look much like Zeller's Congruence.
                        > though it has in common the idea of using arithmetic instead of table
                        > lookup. Have you seen my Zeller pages, via <URL:http://www.merlyn.demon
                        > .co.uk/zeller-c.htm> etc. ?[/color]

                        I have, and noted there was no direct comparable, which was in part
                        the reason for some minor, but perhaps not enough, caution in the
                        wording of the post. The first difference calculation I used is
                        equivalent to that found at:

                        <URL: http://users.aol.com/s6sj7gt/mikecal.htm>

                        which also makes reference to similarity "in spirit" with Zeller's
                        congruence.

                        While on the topic of js date calculations, a relatively
                        straightforward 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.

                        Aside from the commendable mathematical finesse and compactness of the
                        code, it provides an interesting look at use of the comma operator
                        (jslint notwithstanding , of course) -- a construct that seems to be
                        extremely rare (non-existent? :)) in demonstration js code posts.

                        ../rh

                        Comment

                        • Richard Cornford

                          #13
                          Re: Multiple datepicker

                          Dr John Stockton wrote:[color=blue]
                          > rh wrote:[color=green]
                          >>You may also wish to consider something along the lines of:
                          >>
                          >> function LastOfMonth(y, m) { // m = 0..11
                          >> return 29 + (m*31/12 | 0) - ((m-1)*31/12 | 0) + !m
                          >> - ( !! (m-1) || 2
                          >> + ( !!((y & 3) || y & 15 && !(y % 25) )) ) ; // ~ CGjrs
                          >> }[/color][/color]
                          <snip>[color=blue]
                          >
                          > ... , assuming the tests in js-date4.htm are now adequate,
                          > it is correct over a full cycle of 400 years Gregorian and
                          > in IE4 is 2-3 times faster than the best of the others there.[/color]
                          <snip>[color=blue]
                          > function MonthLength(y, m) { // m = 0..11
                          > return new Date(y, m+1, 1, -9).getDate() }
                          >
                          > is the best I've found for a function which can immediately be seen to
                          > be correct, though; ten times slower.[/color]

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

                          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) )) ) ;
                          }

                          However, for February in the year zero - MonthLength - returns 28 days,
                          while - LastOfMonth - returns 29. The expression - (!!(m-1)|| ... ) -
                          only moves into the OR clause in February, so a final additional
                          adjustment by - !y - (only 1 in the year zero, zero otherwise) would
                          correct the discrepancy at a minimal cost in processing time, producing
                          (in my version):-

                          function LastOfMonth3(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
                          /* or maybe:-
                          ((y & 15)||!y)&&
                          !(y % 25)
                          or:-
                          ((y & 15)?!(y % 25):!y)
                          */
                          )
                          ))
                          );
                          }

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

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

                          Richard.


                          Comment

                          • Grant Wagner

                            #14
                            Re: Multiple datepicker

                            Richard Cornford wrote:
                            [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.
                            >
                            > 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 -.
                            >
                            > Richard.[/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. But in this case, I'd most
                            likely use some variation of the Date() object solution presented by Thomas.

                            Why would I use a clunky Date() object driven solution when I have a much
                            faster algorithm? Because a Date object solution is incredibly clear. If I
                            need to go back later and modify the code (although I can't imagine why I
                            would need to unless calendars spontaneously produce a 13th month), code
                            using a Date object is self-documenting. Even if I can't find the original
                            code, I could probably re-write it in about 2 minutes.

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

                            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.

                            My solution produces the same results as yours for all months 0..11 for all
                            years 1000..3199. Now for the fun part. For all months 0..11 for all years
                            1000..3199 (times in ms);

                            LastOfMonth -2- -3-
                            IE: 282 4172
                            NS4: 12719 30970
                            FF0.9: 391 25516 (two "slow script" warnings)
                            O7.53: 531 5094
                            M1.7.1: 500 25908 (two "slow script" warnings)

                            Okay, I take it all back. Given these performance figures I'd use Richard's
                            solution :D.

                            --
                            Grant Wagner <gwagner@agrico reunited.com>
                            comp.lang.javas cript FAQ - http://jibbering.com/faq

                            Comment

                            • Grant Wagner

                              #15
                              Re: Multiple datepicker

                              Richard Cornford wrote:
                              [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.
                              >
                              > 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 -.
                              >
                              > Richard.[/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. But in this case, I'd most likely use
                              some variation of the Date() object solution presented by Thomas.

                              Why would I use a clunky Date() object driven solution when I
                              have a much faster algorithm? Because a Date object solution is
                              incredibly clear. If I need to go back later and modify the code
                              (although I can't imagine why I would need to unless calendars
                              spontaneously produce a 13th month), code using a Date object is
                              self-documenting. Even if I can't find the original code, I could
                              probably re-write it in about 2 minutes.

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

                              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.

                              My solution produces the same results as yours for all months
                              0..11 for all years 1000..3199. Now for the fun part. For all
                              months 0..11 for all years 1000..3199 (times in ms);

                              LastOfMonth -2- -3-
                              IE: 282 4172
                              NS4: 12719 30970
                              FF0.9: 391 25516 (two "slow script" warnings)
                              O7.53: 531 5094
                              M1.7.1: 500 25908 (two "slow script" warnings)

                              Okay, I take it all back. Given these performance figures I'd use
                              Richard's solution :D.

                              --
                              Grant Wagner <gwagner@agrico reunited.com>
                              comp.lang.javas cript FAQ - http://jibbering.com/faq

                              Comment

                              Working...