// JavaScript Document
  var dr;
  dr=Math.atan(1)/45

  // Validate the year, calculate, and set results in form.
  function chny(form) {
    begVal="beg"
    now = new Date;
    then = new Date;

    var year = form.year.value;
    if (year >= 1644 && year <= 4099) {
      result = chNYCalc(year);
      if (result.month == 1)
            form.cnym.value = "1";
      else
            form.cnym.value = "2";
      form.cnyd.value = result.day;

} else {
      form.year.value = "";
      form.month.value = "";
      form.day.value = "";
    }
  }



  function clrTxt(form){
     form.day.value = "";
     form.month.value = "";
     form.animal.value = "";
     form.animalPrev.value = "";
  }

  // Truncate an integer.
  function trunc(num) {
    if (num > 0)
      return Math.floor(num);
    else
      return Math.ceil(num);
  }

  // Normalize a degree measure
  function fnnm(x) {
   return (x - 360 * Math.floor(x/360));
  }

  // trig functions in degrees
   function fnsn(x) {
     return Math.sin(x*dr)}

   function fncs(x) {
     return Math.cos(x*dr)}


  // Chinese New Year CALCULATION
  function chNYCalc(y) {
    /*
     * y is a 4 digit year
     * d returns the day of the month of Chinese New Year
     * m returns the month of Chinese New Year
     *
     */

   var chTZ;            // Chinese Time Zone -- hours
   var s1, s2;            // preceding and contained winter solstice jd
   var solT1, solT2;   // solar terms 1 and 2 - begin and end Aquarius
   var m1, m2, m3, m12;     // new moons
   var NY; // Proposed JD of new year
   var m,d,y;
   var cw0, cw1, cw2, cw3;
   var c;     // animal number
    a = new Array (
     "Rat",  "Ox", "Tiger", "Rabbit(Hare)",
   "Dragon", "Snake", "Horse", "Sheep(Goat)",
   "Monkey", "Rooster", "Dog", "Boar(Pig)")
   var animal,animalPrev;

    if (y < 1928)
      chTZ = -(465+40/60)/60;
    else
      chTZ = -8;

    s1 = wSolst(y-1,chTZ);
    s2 = wSolst(1*y,chTZ);
    solT1 = solTerm(y, chTZ, 300);
    solT2 = solTerm(y, chTZ, 330);
    m1 = nextNewMoon(s1, chTZ);
    m2 = nextNewMoon(m1, chTZ);
    m3 = nextNewMoon(m2, chTZ);
    m12 = nextNewMoon(s2, chTZ);

    NY = m2
    if (Math.floor((m12 - m1)/ 29.530588 + .5) == 13)
      if (solT1 >= m2 || solT2 >= m3) {
         NY = m3;
     /*  alert("delay")  */
         }

    if (NY > 2299160)
      {cw0= Math.floor((NY - 1867216.25)/36524.25);
       cw0= NY + 1 + cw0 - Math.floor(cw0/4);
      } else
      {cw0= NY};

    cw0 += 1524;
    cw1 = Math.floor((cw0 - 122.1)/365.25);
    cw2 = Math.floor(365.25*cw1);
    cw3 = Math.floor((cw0 - cw2)/30.6001);
    d = cw0 - cw2 - Math.floor(30.61*cw3);
    y = cw1 - 4716;
    m = cw3 - 1;
    if (m > 12)
      {m -= 12; y += 1;}

    c = (y-4) % 12; cPrev= (y-5) % 12;
    animal = a[c]; animalPrev = a[cPrev];

    return {month: m, day: d, animal: animal,
      animalPrev: animalPrev}; // object containing the results
  }

function nextNewMoon (j1, chTZ) {
  var d,j1,t,k,m,mp,F,jdNo
    d = j1 - 2415020; t = d / 36525
    k = (j1 - 2415020.759) / 29.53058868; k = Math.floor(k) - 1
    jdNo = 0
    while (jdNo <= j1){
     m = fnnm(359.22 + 29.10535608 * k)
     mp = fnnm(306.03 + 385.8169181 * k + .01073 * t * t + .00001236 * t * t * t)
     F = fnnm(21.2964 + 390.67050646 * k - .0016528 * t * t)

     jdNo = 2415020.75933 + 29.53058868 * k + .0001178 * t * t
     jdNo = jdNo + .1734 * fnsn(m)
     jdNo = jdNo + .0021 * fnsn(2 * m)
     jdNo = jdNo - .4068 * fnsn(mp)
     jdNo = jdNo + .0161 * fnsn(2 * mp)
     jdNo = jdNo + .0104 * fnsn(2 * F)
     jdNo = jdNo - .0051 * fnsn(m + mp)
     jdNo = jdNo - .0074 * fnsn(m - mp)
     jdNo = jdNo + .001 * fnsn(2 * F - mp)

     jdNo = jdNo - (.41 + 1.2053 * t + .4992 * t * t) / 1440
     jdNo = jdNo - chTZ / 24
     jdNo = Math.floor(jdNo + .5)

     k = k + 1
    } // LOOP UNTIL jdNo > j1
    return jdNo
}

function solTerm (y, chTZ, LO) {
   var ys,t,PE,L,DT,m,chJD;
    if (LO >= 270)
       ys = y - 1;
     else
       ys = 1*y;
    t = (365.2422 * (ys + LO / 360) - 693878.7) / 36525
    PE = .00134 * fncs(22518.7541 * t + 153)
    PE = PE + .00154 * fncs(45037.5082 * t + 217) + .002 * fncs(32964.3577 * t + 313) + .00178 * fnsn(20.2 * t + 231)
    DT = 1
    while (Math.abs(DT * 36525) > .001) {
      L = 279.6967 + 36000.76892 * t + .0003025 * t * t
      m = 358.476 + 35999.04975 * t - .00015 * t * t - .0000033 * t * t * t
      L = L + (1.91946 - .004789 * t - .000014 * t * t) * fnsn(m) + (.020094 - .0001 * t) * fnsn(2 * m) + .000293 * fnsn(3 * m)
      L = L - .00479 * fnsn(fnnm(259.18 - 1934.142 * t)) - .00569 + PE + .00179 * fnsn(351 + 445267.1142 * t - .00144 * t * t)
      L = fnnm(L)
      DT = (fnnm(LO - L + 180) - 180) / 36525
      t = t + DT;
    } // LOOP WHILE ABS(DT * 36525) > .001
    chJD = t * 36525 + 2415020 - (.41 + 1.2053 * t + .4992 * t * t) / 1440 - chTZ / 24
    return Math.floor(chJD + .5)
}

function wSolst (ys, chTZ)  { //chTZ in hours; + = west
    var LO,t,PE,L,DT,chJD
    LO = 270
    t = (365.2422 * (1*ys + LO / 360) - 693878.7) / 36525
    PE = .00134 * fncs(22518.7541 * t + 153)
    PE = PE + .00154 * fncs(45037.5082 * t + 217) + .002 * fncs(32964.3577 * t + 313) + .00178 * fnsn(20.2 * t + 231)
    DT = 1
    while (Math.abs(DT * 36525) > .001) {
      L = 279.6967 + 36000.76892 * t + .0003025 * t * t
      m = 358.476 + 35999.04975 * t - .00015 * t * t - .0000033 * t * t * t
      L = L + (1.91946 - .004789 * t - .000014 * t * t) * fnsn(m) + (.020094 - .0001 * t) * fnsn(2 * m) + .000293 * fnsn(3 * m)
      L = L - .00479 * fnsn(fnnm(259.18 - 1934.142 * t)) - .00569 + PE + .00179 * fnsn(351 + 445267.1142 * t - .00144 * t * t)
      L = fnnm(L)
      DT = (fnnm(LO - L + 180) - 180) / 36525
      t = t + DT;
    } // LOOP WHILE ABS(DT * 36525) > .001
    chJD = t * 36525 + 2415020 - (.41 + 1.2053 * t + .4992 * t * t) / 1440 - chTZ / 24
    return Math.floor(chJD + .5)
}
