
function CaptionZ() {
  //    JAVASCRIPT INCLUDE FILE - (c) J R Stockton  >= 2008-11-11
  //            http://www.merlyn.demon.co.uk/zell-inc.js
  // DoWkTest and EasterTest are called by zel-188(2,3,5,6).htm
  // CodeLinks is called by those and zeller-c.htm
  // Gpro188x are used by zeller-c.htm ; are reduced Cvt188x
  // ZEG188x also used by zeller-c.htm ; zel-188x.htm use all 188x
  }

var ZincT=0

function CodeLinks(X) { document.writeln('<p>',
    '<a href="view-source:'+this.location+'">View Source<\/a>, ',
    '<a href="view-source:http://www.merlyn.demon.co.uk/',
    'zell-inc.js">View Include File<\/a> (contains functions), ',
    '<a href="js-nclds.htm#Zinc">',
    'Include File Page<\/a> (shows functions)')
  if (X) document.writeln('<p>Automated Gregorian tests',
    ' are at <a href="zeller-c.htm#ToI">zeller-c.htm<\/a>.<\/p>' ) }

// function LZ(x) { return (x<0||x>=10?"":"0") + x }

function DoMtoISOdate(MarDay) { var Mth = 3, Day = MarDay
  if (Day>31) { Mth = 4 ; Day -= 31 }
  return 'Year-0' + Mth + '-' + LZ(Day) }


function AllDays(F, ZY, C) { CvtYYYY = window["Cvt"+ZY]
  var Y, M, D, dow, pro, Ers = 0, Cal = ["Julian   ", "Gregorian"],
    YY = F.Rnge.value.split(/\D+/), Y0 = +YY[0], Y1 = +YY[1],
    Yrs0 = [], Yrs1 = [], Job = Cal[C] + " :\tZeller " + ZY,
    Arr = ["Value?\n" + Job], YMD
  for (Y=Y0 ; Y<=Y1 ; Y++) for (M=1 ; M<=12 ; M++)
  for (D=1 ; D<=31 ; D++) {

    YY = (new Date(Y, M-1, D).getDay()+1) % 7
    CvtYYYY(Y, M, D)
    if (C) {dow = Gdow ; pro = Gpro} else {dow = Jdow ; pro = Jpro}
    if (YY!= pro) { Ers++
      YMD = LZZ(Y)+"-"+LZ(M)+"-"+LZ(D)
      if (!Yrs0[Y]) Yrs0[Y] = YMD ; Yrs1[Y] = YMD
      Arr.push(YMD + "\t " + YY + "  " + pro) }

    }
  Arr.push("Error Days in " + Y0 + "-" + Y1 + " : " + Ers)
  if (Ers) { Arr.splice(1, 0, "Error days\tTRU pro")
    Arr.push("First and last error day in each year : ")
    for (Y=Y0 ; Y<=Y1 ; Y++)
      if (Yrs0[Y]) Arr.push(Yrs0[Y] + "\t" + Yrs1[Y]) }
  FreshPage(Job, "<pre>"+Arr.join("<br>")+"<\/pre>") }




function Bad7Days(F, ZY, C) { CvtYYYY = window["Cvt"+ZY]
  var Y, M, D, dow, pro, Ers = 0, Cal = ["Julian   ", "Gregorian"],
    YY = F.Rnge.value.split(/\D+/), Y0 = +YY[0], Y1 = +YY[1],
    Yrs0 = [], Yrs1 = [], Job = Cal[C] + " :\tZeller " + ZY,
    Arr = ["Mod 7?\n" + Job], YMD
  for (Y=Y0 ; Y<=Y1 ; Y++) for (M=1 ; M<=12 ; M++)
  for (D=1 ; D<=31 ; D++) { CvtYYYY(Y, M, D)
    if (C) {dow = Gdow ; pro = Gpro} else {dow = Jdow ; pro = Jpro}
    if (dow != pro) { Ers++
      YMD = LZZ(Y)+"-"+LZ(M)+"-"+LZ(D)
      if (!Yrs0[Y]) Yrs0[Y] = YMD ; Yrs1[Y] = YMD
      Arr.push(YMD + "\t" + dow + "  " + pro) } }
  Arr.push("Error Days in " + Y0 + "-" + Y1 + " : " + Ers)
  if (Ers) { Arr.splice(1, 0, "Error days\tdow pro")
    Arr.push("First and last error day in each year : ")
    for (Y=Y0 ; Y<=Y1 ; Y++)
      if (Yrs0[Y]) Arr.push(Yrs0[Y] + "\t" + Yrs1[Y]) }
  FreshPage(Job, "<pre>"+Arr.join("<br>")+"<\/pre>") }




// Day of Week Form :

var Jdow, Gdow, Jpro, Gpro // global
  DName = ['Sat', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri'] // non-std.

function DoWkTest(ZPYr) {
  with (new Date()) var TryD = getFullYear() +
    " " + LZ(getMonth()+1) + " " + LZ(getDate())
 document.writeln(
  '<form name=FD', ZPYr, ' action="#">',
  '<div class=TRY style="margin: 0 auto 0 auto; width: 68ex;">',
  '<div class=CEN>',
  '<b>JavaScript Day-of-Week Tests - ', ZPYr, '<\/b><\/div><hr>',
  'Y M D : <input type=text name=inp size=12 value="', TryD, '"> ',
  ' &nbsp; <input type=button name=Conv value="Convert" onClick= ',
  ' "var X = CvtYYYY(', ZPYr, ', inp.value) ;',
  ' Un.value = X[0] ; Pr.value = X[1] ; Dy.value = X[2] ">',
  '&nbsp; The input date is not numerically validated.<br>',
  '<input type=text name=Un size=40 readonly> &nbsp; As published',
  '<br><input type=text name=Pr size=40 readonly>',
  ' &nbsp; Protected against <i>MOD 7<\/i> error<br> Gregorian,',
  ' by JavaScript : <input type=text name=Dy size=6 readonly>',

  '<hr>Check all days in ',
  '<input type=text name=Rnge value="1995-2025" size=10>',
  ' (opens a new window or tab)',

  '<br>for <tt>Gpro<\/tt> value : ',
//  '<input type=button value="Juln" onClick="AllDays(this.form, ', ZPYr, ', 0)"> ',
  '<input type=button value="Greg" onClick="AllDays(this.form, ', ZPYr, ', 1)"> ',

  ' &nbsp; &nbsp; for <i>MOD 7<\/i> : ',
  '<input type=button value="Juln" onClick="Bad7Days(this.form, ', ZPYr, ', 0)"> ',
  '<input type=button value="Greg" onClick="Bad7Days(this.form, ', ZPYr, ', 1)"> ',

  '<\/div><\/form>' ) /* Writes form which calls Cvt188x  & */ }


function ZDoWk(S, v) { return '  ' + S + ': ' + v + ' ' + DName[v] }

function CvtYYYY(YYYY, SS) { var B, y, m, q, Ansr = ['?', '?']
  B = /^(\d+)\D+(\d+)\D+(\d+)$/.test(SS)
  if (B) with (RegExp) { y = +$1 ; m = +$2 ; q = +$3 // date
    with (new Date(0)) {
      setFullYear(y, m-1, q) ; var JavDay = (getDay()+1)%7 }
    window["Cvt"+YYYY](y, m, q) // sets globals
    Ansr = [
      [$1,$2,$3] + ';' + ZDoWk('Jdow', Jdow) + ZDoWk('Gdow', Gdow),
      [$1,$2,$3] + ';' + ZDoWk('Jpro', Jpro) + ZDoWk('Gpro', Gpro),
      JavDay + ' ' + DName[JavDay] ] }
  return Ansr }



// Easter Form :

function EasterTest(ZPYr) { var TryY = (new Date()).getFullYear()
 document.writeln('<form name=FE', ZPYr, ' action="#">',
  '<div class=TRY style="margin: 0 auto 0 auto; width: 29ex;">',
  '<div class=CEN>',
  '<b>JavaScript Easter Test - ', ZPYr, '<\/b><\/div><hr>',
  'Year &nbsp;',
  '<input type=text name=Inp size=8 value="', TryY, '"> &nbsp; ',
  '<input type=button name=Conv value=" Go " onClick= ',
  ' " Ju.value = DoMtoISOdate(ZEJ', ZPYr, '(+Inp.value)) ;',
  '   Gr.value = DoMtoISOdate(ZEG', ZPYr, '(+Inp.value)) ;',
  '   CF.value = YMDobjToISO(EGREaster(+Inp.value)) "><br>',
  '<input type=text name=Ju size=13 readonly> &nbsp; Julian<br>',
  '<input type=text name=Gr size=13 readonly> &nbsp; Gregorian<br>',
  '<input type=text name=CF size=13 readonly> &nbsp;',
  ' Good Greg.',
  '<\/div><\/form>') /* Writes form to call ZEJ188x & ZEG188x */ }



// Test Forms for Each Paper

function ZellerUserTest(ZY) { // e.g. ZY=1886
  document.writeln("<p>Test form for any of four Papers :-<\/p>")
  DoWkTest(ZY) ; EasterTest(ZY)
  PopBtn(window["Cvt"+ZY], window["Gpro"+ZY])
  PopBtn(window["ZEJ"+ZY], window["ZEG"+ZY])
  PopBtn(AllDays, Bad7Days)
  CodeLinks(1) }


// Tests for Zeller's Examples

function EasterExample(Cal, EFn, Year) {
  document.writeln("Easter ", Year,
    " = ", DoMtoISOdate(EFn(Year)), " ", Cal) }


function DoWeekExample(Cal, CvtN, Y, M, D) { CvtN(Y, M, D)
  var X = Cal.charAt(0)=="J" ? Jpro : Gpro
  document.writeln("Day-of-Week ", Y, "-", LZ(M), "-",
    LZ(D), " = ", X, " ", DName[X], " ", Cal) }


// 1882 paper :

function Cvt1882(y, m, q) { var J, e, k, A
  if (m<3) { m = m+12 ; y = y-1 }
  J = Math.floor(y/100) ; k = y%100 ; e = J%4 ; A = k+4
  Gdow =
    (q + Math.floor((m+1)*26/10) + k + Math.floor(k/4) - 2*e) % 7
  Gpro =
    (q + Math.floor((m+1)*26/10) + k + Math.floor(k/4) + 5*e) % 7
  Jdow =
    (q + Math.floor((m+1)*26/10) + A + Math.floor(A/4) -  J ) % 7
  Jpro =
    (q + Math.floor((m+1)*26/10) + A + Math.floor(A/4) + 6*J) % 7 }

function Gpro1882(y, m, q) { var J, e, k
  if (m<3) { m = m+12 ; y = y-1 }
  J = Math.floor(y/100) ; k = y%100 ; e = J%4
  Gpro =
    (q + Math.floor((m+1)*26/10) + k + Math.floor(k/4) + 5*e) % 7
  return Gpro }

function ZEJ1882(Yr) { var a, b, d,   k = Yr%100, J = (Yr-k)/100,
    ko4 = Math.floor(k/4)
  a = (k + 5*J) % 19
  b = ( 19*a+15 ) % 30
  d = (b + k + ko4 - J) % 7 ; if (d<0) d+=7 // correction 20070515
  return 28 + b - d }

function ZEG1882(Yr) { var a, b, d, h, k = Yr%100, J = (Yr-k)/100,
    ko4 = Math.floor(k/4), Jo4 = Math.floor(J/4), e = J%4
  a = (k + 5*J) % 19
  h = J - Jo4 - Math.floor( (8*J+13)/25 )
  b = ( 19*a+15 + h ) % 30
//  d = (b + k + ko4 + 2 - 2*e) % 7  // can the arg be neg? yes
  d = (b + k + ko4 + 2 + 5*e) % 7
  if (d==0) { if ((b==29) || ( b==28 && a>10)) d = 7 }
  return 28 + b - d }



// 1883 paper :

function Cvt1883(y, m, q) { var I, e, k
  if (m<3) { m = m+12 ; y = y-1 }
  I = Math.floor(y/100) ; e = I%4 ; k = y%100 ;
  Jdow =
    (q + Math.floor((m+1)*26/10) + k + Math.floor(k/4) - (I+2))%7
  Jpro =
    (q + Math.floor((m+1)*26/10) + k + Math.floor(k/4) +6*I-2 )%7
  Gdow =
    (q + Math.floor((m+1)*26/10) + k + Math.floor(k/4) - 2*e) % 7
  Gpro =
    (q + Math.floor((m+1)*26/10) + k + Math.floor(k/4) + 5*e) % 7 }

function Gpro1883(y, m, q) { var I, e, k
  if (m<3) { m = m+12 ; y = y-1 }
  I = Math.floor(y/100) ; e = I%4 ; k = y%100 ;
  Gpro =
    (q + Math.floor((m+1)*26/10) + k + Math.floor(k/4) + 5*e) % 7
  return Gpro }

function ZEJ1883(Yr) { var a, b, d,   k = Yr%100, I = (Yr-k)/100,
    ko4 = Math.floor(k/4)
  a = (k + 5*I) % 19
  b = ( 19*a+15 ) % 30
  d = (b + k + ko4 - I) % 7 ; if (d<0) d+=7 // correction 20070515
  return 28 + b - d }

function ZEG1883(Yr) { var a, b, d, h, k = Yr%100, I = (Yr-k)/100,
    ko4 = Math.floor(k/4), Io4 = Math.floor(I/4), e = I%4
  a = (k + 5*I) % 19
  h = I - Io4 - Math.floor( (8*I+13)/25 )
  b = ( 19*a+15 + h ) % 30
//  d = (b + k + ko4 + 2 - 2*e) % 7  // can arg be neg? yes // +2
  d = (b + k + ko4 + 2 + 5*e) % 7  // +2
  if (d==0) { if ((b==29) || ( b==28 && a>10)) d = 7 }
  return 28 + b - d }


// 1885 paper :

function Cvt1885(y, m, q) { var J, e, K
  if (m<3) { m = m+12 ; y = y-1 }
  J = Math.floor(y/100) ; e = J%4 ; K = y%100 ;
  Gdow =
    (q + Math.floor((m+1)*26/10) + K + Math.floor(K/4) - 2*e) % 7
  Gpro =
    (q + Math.floor((m+1)*26/10) + K + Math.floor(K/4) + 5*e) % 7
  Jdow =
    (q + Math.floor((m+1)*26/10) + K + Math.floor(K/4) - (J+2))%7
  Jpro =
    (q + Math.floor((m+1)*26/10) + K + Math.floor(K/4) + 6*J+5 )%7 }

function Gpro1885(y, m, q) { var I, e, K
  if (m<3) { m = m+12 ; y = y-1 }
  I = Math.floor(y/100) ; e = I%4 ; K = y%100 ;
  Gpro =
    (q + Math.floor((m+1)*26/10) + K + Math.floor(K/4) + 5*e) % 7
  return Gpro }

function ZEJ1885(Yr) { var a, b, d,   K = Yr%100, J = (Yr-K)/100,
    Ko4 = Math.floor(K/4)
  a = Yr % 19
  b = ( 19*a+15 ) % 30
  d = (b + K + Ko4 - J) % 7 ; if (d<0) d+=7 // correction 20070515
  return 28 + b - d }

function ZEG1885(Yr) { var a, b, d, g, K = Yr%100, J = (Yr-K)/100,
    Ko4 = Math.floor(K/4), Jo4 = Math.floor(J/4), e = J%4
  a = (K + 5*J) % 19
  g = J - Jo4 - Math.floor( (8*J+13)/25 )
  b = ( 19*a+15 + g ) % 30
//  d = (b + K + Ko4 + 2 - 2*e) % 7  // can the arg be neg? // +2
  d = (b + K + Ko4 + 2 + 5*e) % 7  // can the arg be neg? // +2
  if (d==0) { if ((b==29) || ( b==28 && a>10)) d = 7 }
  return 28 + b - d }


// 1886 paper :

function Cvt1886(y, m, q) { var J, e, K
  if (m<3) { m = m+12 ; y = y-1 }
  J = Math.floor(y/100) ; e = J%4 ; K = y%100 ;
  Jdow = (q + Math.floor((m+1)*26/10) +
              K + Math.floor(K/4) + 5 - J) % 7
  Jpro = (q + Math.floor((m+1)*26/10) +
              K + Math.floor(K/4) + 5 + 6*J) % 7
  Gdow = (q + Math.floor((m+1)*26/10) +
              K + Math.floor(K/4) + Math.floor(J/4) - 2*J) % 7
  Gpro = (q + Math.floor((m+1)*26/10) +
              K + Math.floor(K/4) + Math.floor(J/4) + 5*J) % 7 }

function Gpro1886(y, m, q) { var J, e, K
  if (m<3) { m = m+12 ; y = y-1 }
  J = Math.floor(y/100) ; e = J%4 ; K = y%100 ;
//  Gpro = (q + Math.floor((m+1)*2.6) +
//            K + Math.floor(K/4) + 5*e) % 7
  Gpro = (q + Math.floor((m+1)*26/10) +
            K + Math.floor(K/4) + Math.floor(J/4) + 5*J) % 7
  return Gpro }

function ZEJ1886(Yr) { var a, b, d,   K = Yr%100, J = (Yr-K)/100,
    Ko4 = Math.floor(K/4)
  a = Yr % 19
  b = ( 19*a+15 ) % 30
  d = (b + K + Ko4 - J) % 7 ; if (d<0) d+=7 // correction 20070515
  return 28 + b - d }

function ZEG1886(Yr) { var a, b, d, g, K = Yr%100, J = (Yr-K)/100,
    Ko4 = Math.floor(K/4), Jo4 = Math.floor(J/4), e = J%4
  a = (5*J + K) % 19
  g = J - Jo4 - Math.floor((8*J+13)/25)
  b = ( 19*a+15 + g ) % 30
  d = (b + K + Ko4 + Jo4 + 2 + 5*J) % 7  // arg be neg? // +2 +5*
  if (d==0) { if ((b==29) || ( b==28 && a>10)) d = 7 }
  return 28 + b - d }



function RunD(y1, y2, Orl, ZZ, EX) {
  if ((y2-y1)>[10,1][+Orl])
    if (!confirm('This may take some time - OK?')) return
  ZZ.value = '-' ; EX.value = ' Working'
  setTimeout("RunDates("+y1+", "+y2+", "+Orl+")", 10) }

function RunDates(y1, y2, Orl) { var D = new Date(0), T='    '
  var A, X0, X2, X3, X5, X6, J, JS, Errs = 0, Err, S, y, m, q
  with (document.forms['Frm1']) {
    EX.value = '   Date     Good 1882 1883 1885 1886 Err?'
    for ( J=y1 ; J<=y2 ; J++ ) { window.status = J
      for ( D.setFullYear(J, 0, 1) ;
            D.getFullYear()==J ; D.setDate(D.getDate()+1) ) {
        with (D) { X0 = (D.getDay() + 1)%7
          y = getFullYear() ; m = getMonth()+1 ; q = getDate() }
        X2 = Gpro1882(y, m, q)
        X3 = Gpro1883(y, m, q)
        X5 = Gpro1885(y, m, q)
        X6 = Gpro1886(y, m, q)
        Err = (X2!=X0) || (X3!=X0) || (X5!=X0) || (X6!=X0)
        if (Err) { Errs++ }
        if (Orl || Err ) { S = '\n' + D.ISOlocaldateStr() +
            T + X0 + T + X2 + T + X3 + T + X5 + T + X6
          EX.value += S + (Err ? '  ****' : '' ) } } }
    ZZ.value = ' Years '+y1+'-'+y2+' done, errors '+ Errs } }


function RunE(y1, y2, Orl, F) {
  if ((y2-y1)>[500,250][+Orl])
    if (!confirm('This may take some time - OK?')) return
  with (F) { ZZ.value = '-' ; EX.value = ' Working' }
  setTimeout("RunEaster("+y1+", "+y2+", "+Orl+")", 10) }

function RunEaster(y1, y2, Orl) { var Errs = 0, Err, S,
    X0, X2, X3, X5, X6, J, JS, T='    '
  with (document.forms['Frm2']) {
    EX.value = ' Year  EGRP  1882  1883  1885  1886  Err?'
    for ( J=y1 ; J<=y2 ; J++ ) { window.status = J
      X0 = YMDobjToDoM(EGREaster(J))
      X2 = ZEG1882(J)
      X3 = ZEG1883(J)
      X5 = ZEG1885(J)
      X6 = ZEG1886(J)
      Err = (X2!=X0) || (X3!=X0) || (X5!=X0) || (X6!=X0)
      if (Err) { Errs++ }
      if (Orl || Err ) {
        JS = J + '' ; while (JS.length<5) JS = ' ' + JS
        S = '\n' + JS + T + X0 + T + X2 + T + X3 + T + X5 + T + X6
        EX.value += S + (Err ? '  ****' : '' ) } }
    ZZ.value = ' Years '+y1+'-'+y2+' done, errors '+ Errs } }


var ZincB=0 // end.

