function IsLeap(Y, G) {
  var leap = true;

  if (G === false) {
    if (Y % 4 === 0) {
      leap = true;
    } else {
      leap = false;
    }
  } else {
    leap = false;

    if (Y % 4 === 0) {
      leap = true;
    } ;

    if ((Y % 100 === 0) && (Y % 400 > 0)) {
      leap = false;
    } ;

    if (Y % 4000 === 0) {
      leap = false;
    }
  } ;

  return leap;
}

;

function FindMonth(N, yr, cal) {
  try {
    var K = 0;
    var G = cal;

    if (typeof (G) != "boolean") {
      throw new TypeError("FindMonth. Bad input of calendar type.");
    } ;

    if (IsLeap(yr, G)) {
      K = 1;
    } else {
      K = 2;
    } ;

    var month = Math.floor(((9 * (K + N)) / 275) + 0.98);

    if (N < 32) {
      month = 1;
    }

    return month;
  }
  catch (e) {
    if (e instanceof Error) {
      alert(e.name + ": " + e.message);
    }
  }
}

function FindDay(N, yr, cal) {
  try {
    var K = 0;
    var G = cal;

    if (typeof (G) != "boolean") {
      throw new TypeError("Bad input of calendar type.");
    }

    if (IsLeap(yr, cal)) {
      K = 1;
    } else {
      K = 2;
    }

    var M = FindMonth(N, yr, G);
    var day = N - Math.floor((275 * M) / 9) + K * Math.floor((M + 9) / 12) + 30;
    return day;
  }
  catch (e) {
    if (e instanceof Error) {
      alert(e.name + ": " + e.message);
    }
  }
}

function FindLast(year, month, weekday) {
  try {
    var Y = parseInt(year);

    if (isNaN(Y) || (Y > 9999)) {
      throw new Error("FindLast. Bad year input");
    }

    var M = parseInt(month);

    if (isNaN(M) || (M < 0) || (M > 11)) {
      throw new Error("FindLast. Bad month input");
    }

    var WD = parseInt(weekday);

    if (isNaN(WD) || (WD < 0) || (WD > 6)) {
      throw new Error("FindLast. Bad weekday input");
    }

    var Mlengths = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

    if (IsLeap(Y, true)) {
      Mlengths[1] = 29;
    }

    var D = Mlengths[M];
    var MonthOfDays = new Date(Y, M);
    MonthOfDays.setDate(D);

    while (MonthOfDays.getDay() != WD) {
      D = D - 1;
      MonthOfDays.setDate(D);
    }

    return D;
  }
  catch (e) {
    if (e instanceof Error) {
      alert(e.name + ": " + e.message);
    }
  }
}

function FindFirst(year, month, weekday) {
  try {
    var Y = parseInt(year);

    if (isNaN(Y) || (Y > 9999)) {
      throw new Error("FindFirst. Bad year input");
    }

    var M = parseInt(month);

    if (isNaN(M) || (M < 0) || (M > 11)) {
      throw new Error("FirstLast. Bad month input");
    }

    var WD = parseInt(weekday);

    if (isNaN(WD) || (WD < 0) || (WD > 6)) {
      throw new Error("FirstLast. Bad weekday input");
    }

    var D = 1;
    var MonthOfDays = new Date(Y, M);
    MonthOfDays.setDate(1);

    while (MonthOfDays.getDay() != WD) {
      D = D + 1;
      MonthOfDays.setDate(D);
    }

    if (D > 8) {
      throw new Error("FindFirst. Output too large.");
    }

    return D;
  }
  catch (e) {
    if (e instanceof Error) {
      alert(e.name + ": " + e.message);
    }
  }
}

function twelve24(twelve, hour, minute) {
  try {
    if (typeof (twelve) != "boolean") {
      throw new TypeError("twelve24. Bad input of 12/24 type.");
    }

    var H = parseInt(hour);

    if (isNaN(H)) {
      throw new TypeError("twelve24. Bad hour input, type.");
    }

    if ((H > 24) || (H < 0)) {
      throw new RangeError("twelve24. Bad hour input, range.");
    }

    var M = parseInt(minute);

    if (isNaN(M)) {
      throw new TypeError("twelve24. Bad minute input.");
    }

    if ((M > 59) || (M < 0)) {
      throw new RangeError("twelve24. Bad minute input.");
    }

    theString = "";

    if (M < 10) {
      M = "0" + M;
    }

    if (twelve === true) {
      if (H == 12) {
        theString = " " + H + ":" + M + " pm";
      } else if (H > 12) {
        H = H - 12;
        theString = " " + H + ":" + M + " pm";
      } else {
        theString = " " + H + ":" + M + " am";
      }
    } else {
      theString = " " + H + ":" + M;
    }

    return theString;
  }
  catch (e) {
    if (e instanceof Error) {
      alert(e + ": " + e.message);
    }
  }
}

function GregOrJul2Islamic(dy, mn, yr, cal) {
  var dayString = "";
  var dateString = "";
  var monthString = "";
  var X = parseInt(yr);

  if (isNaN(X)) {
    throw new Error("Bad year input.");
  }

  var M = parseInt(mn);

  if (isNaN(M)) {
    throw new Error("Bad month input.");
  }

  var D = parseInt(dy);

  if (isNaN(D)) {
    throw new Error("Bad day input.");
  }

  var G = cal;

  if (typeof (G) != "boolean") {
    throw new TypeError("Bad input of calendar type.");
  }

  var W = 0;
  var IsMns = new Array("Muharram", "Safar",    "Rabi\'al-Awwal", "Rabi\'ath-Thani", "Jumada l-Ula", "Jumada t-Tania",
                        "Rajab",    "Sha\'ban", "Ramadan",        "Shawwal",         "Dhu l-Qa\'da", "Dhu l-Hijja");

  try {
    if ((yr < 622) || ((yr == 622) && (mn < 6)) || ((yr == 622) && (mn == 6) && (dy <= 16))) {
      throw new RangeError("Before Hegirae.");
    }

    if (G === true) {
      if (M < 3) {
        X = X - 1;
        M = M + 12;
      }

      var alpha = Math.floor(X / 100);
      var beta = 2 - alpha + Math.floor(alpha / 4);
      var b = Math.floor(365.25 * X) + Math.floor(30.6001 * (M + 1)) + parseInt(D) + parseInt(1722519) + beta;
      var c = Math.floor((b - 122.1) / 365.25);
      var d = Math.floor(365.25 * c);
      var e = Math.floor((b - d) / 30.6001);
      D = b - d - Math.floor(30.6001 * e);

      if (e < 14) {
        M = e - 1;
      } else if (e > 13) {
        M = e - 13;
      }

      if (M > 2) {
        X = c - 4716;
      } else if (M < 3) {
        X = c - 4715;
      }
    }

    if ((X % 4) === 0) {
      W = 1;
    } else {
      W = 2;
    }

    var N = Math.floor((275 * M) / 9) - W * Math.floor((M + 9) / 12) + D - 30;
    var A = X - 623;
    var B = Math.floor(A / 4);
    var C = A % 4;
    var C1 = 365.2501 * C;
    var C2 = Math.floor(C1);

    if ((C1 - C2) > 0.5) {
      C2 = C2 + 1;
    }

    var Dpr = (1461 * B) + 170 + C2;
    var Q = Math.floor(Dpr / 10631);
    var R = Dpr % 10631;
    var J = Math.floor(R / 354);
    var O = Math.floor(((11 * J) + 14) / 30);
    var H = 30 * Q + J + 1;
    var JJ = (R % 354) - O + N - 1;

    if (JJ > 354) {
      var DL = (11 * (H % 30)) % 30;

      if (DL < 19) {
        JJ = JJ - 354;
        H = H + 1;
      } else if (DL > 18) {
        JJ = JJ - 355;
        H = H + 1;
      }
    }

    if (JJ == 355) {
      dateString = "30 Dhu l-Hijja A.H. " + toString(H);
    } else {
      S = Math.floor((JJ - 1) / 29.5);
      monthString = IsMns[S];
      dayString = Math.floor(JJ - (29.5 * S));
      dateString = monthString + " " +dayString+ ", " + H+".";
    }

    return dateString;
  }
  catch (e) {
    if (e instanceof Error) {
      alert(e.name + ": " + e.message);
    }
  }
}

function Islamic2GregOrJul(dy, mn, yr, cal) {
  var JulMns = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September",
                         "October", "November", "December");
  var datestring = "";

  try {
    var H = parseInt(yr);

    if (isNaN(H)) {
      throw new Error("Bad year input.");
    }

    var M = parseInt(mn);

    if (isNaN(M)) {
      throw new Error("Bad month input.");
    }

    var D = parseInt(dy);

    if (isNaN(D)) {
      throw new Error("Bad day input.");
    }

    var Gregorian = cal;

    if (typeof (Gregorian) != "boolean") {
      throw new Error("Bad type of calendar input.");
    }

    var N = D + Math.floor((29.5001 * (M - 1)) + 0.99);
    var Q = Math.floor(H / 30);
    var R = H % 30;
    var A = Math.floor(((11 * R) + 3) / 30);
    var W = (404 * Q) + (354 * R) + 208 + A;
    var Q1 = Math.floor(W / 1461);
    var Q2 = W % 1461;
    var G = 621 + 4 * Math.floor((7 * Q) + Q1);
    var K = Math.floor(Q2 / 365.2422);
    var E = Math.floor(365.2422 * K);
    var J = Q2 - E + N - 1;
    var X = G + K;

    if ((J > 366) && (X % 4 === 0)) {
      J = J - 366;
      X = X + 1;
    }

    if ((J > 365) && (X % 4 > 0)) {
      J = J - 365;
      X = X + 1;
    }

    var JD = Math.floor(365.25 * (X - 1)) + 1721423 + J;
    var alpha = Math.floor((JD - 1867216.25) / 36524.25);
    var beta = 0;
    var b = 0;
    var c = 0;
    var d = 0;
    var e = 0;
    var m = 0;
    var day = 0;
    var month = 0;
    year = 0;

    if (! Gregorian) {
      beta = JD;
      b = beta + 1524;
      c = Math.floor((b - 122.1) / 365.25);
      d = Math.floor(365.25 * c);
      e = Math.floor((b - d) / 30.6001);
      day = b - d - Math.floor(30.6001 * e);

      if (e < 14) {
        m = e - 1;
        month = JulMns[m - 1];
      } else if (e > 13) {
        m = e - 13;
        month = JulMns[m - 1];
      }

      if (m > 2) {
        year = c - 4716;
      } else if (m < 3) {
        year = c - 4715;
      }

      dateString = day + " " + month + " " + year;
      return dateString;
    } else {
      beta = JD + 1 + alpha - Math.floor(alpha / 4);

      if (JD < 2299161) {
        beta = JD;
        alert("You have entered a date that is earlier than the introduction of the Gregorian calendar.\n Such dates are conventionally expressed in the Julian calendar.");
        document.Icalc.GorJ[1].checked = true;
      }

      b = beta + 1524;
      c = Math.floor((b - 122.1) / 365.25);
      d = Math.floor(365.25 * c);
      e = Math.floor((b - d) / 30.6001);
      day = b - d - Math.floor(30.6001 * e);

      if (e < 14) {
        m = e - 1;
        month = JulMns[m - 1];
      } else if (e > 13) {
        m = e - 13;
        month = JulMns[m - 1];
      }

      if (m > 2) {
        year = c - 4716;
      } else if (m < 3) {
        year = c - 4715;
      }

      dateString = "       "+day + " " + month + " " + year;
      return dateString;
    }
  }
  catch (ex) {
    if (e instanceof Error) {
      alert(e.name + ": " + e.message);
    }
  }
}

function EU(delta) {
  try {
    var offset = delta;
    var now = new Date();
    var H = 0;
    var Yr = now.getUTCFullYear();
    var startDST = new Date();
    startDST.setUTCMonth(2, FindLast(Yr, 2, 0));
    startDST.setUTCHours(1);
    var stopDST = new Date();
    stopDST.setUTCMonth(9, FindLast(Yr, 9, 0));
    stopDST.setUTCHours(1);

    if ((now.getTime() > startDST.getTime()) && (now.getTime() < stopDST.getTime())) {
      H = now.getUTCHours() + offset + 1;

      if (H > 23) {
        H = H - 24;
      }
    } else {
      H = now.getUTCHours() + offset;

      if (H > 23) {
        H = H - 24;
      }
    }

    var minutes = now.getUTCMinutes();
    var timeString = H + ":" + minutes;
    return timeString;
  }
  catch (e) {
    if (e instanceof Error) {
      alert(e.name + ": " + e.message);
    }
  }
}

function US(myDate, delta) {
  try {
    var offset = delta;
    var timeNow = new Date(myDate.getTime());
    var H = 0;
    var Yr = timeNow.getUTCFullYear();
    var startDST = new Date();
    startDST.setUTCMonth(3, FindFirst(Yr, 3, 0));
    startDST.setUTCHours(2 + offset);
    var stopDST = new Date();
    stopDST.setUTCMonth(9, FindLast(Yr, 9, 0));
    stopDST.setUTCHours(2 + offset - 1);

    if ((timeNow.getTime() > startDST.getTime()) && (timeNow.getTime() < stopDST.getTime())) {
      H = timeNow.getUTCHours() + offset + 1;

      if (H < 0) {
        H = 24 + H;
      }
    } else {
      H = timeNow.getUTCHours() + offset;

      if (H < 0) {
        H = 24 + H;
      }
    }

    var minutes = timeNow.getUTCMinutes();
    var timeString = " " + H + ":" + minutes;
    return timeString;
  }
  catch (e) {
    if (e instanceof Error) {
      alert(e.name + ": " + e.message);
    }
  }
}

function USisDay(myDate, delta) {
  try {
    var offset = delta;
    var timeNow = new Date(myDate.getTime());
    var Yr = timeNow.getUTCFullYear();
    var startDST = new Date();
    startDST.setUTCDate(FindFirst(Yr, 3, 0));
    startDST.setUTCHours(2 + offset);
    var stopDST = new Date();
    stopDST.setUTCDate(FindLast(Yr, 9, 0));
    stopDST.setUTCHours(2 + offset - 1);

    if ((timeNow.getTime() > startDST.getTime()) && (timeNow.getTime() < stopDST.getTime())) {
      return true;
    }
  }
  catch (e) {
    if (e instanceof Error) {
      alert(e.name + ": " + e.message);
    }
  }
}

function RF(myDate, delta) {
  try {
    var offset = delta;
    var now = new Date(myDate.getTime());
    var Yr = now.getUTCFullYear();
    var startDST = new Date();
    startDST.setUTCMonth(2, FindLast(Yr, 2, 0));
    startDST.setUTCHours(2 + offset);
    var stopDST = new Date();
    stopDST.setUTCMonth(9, FindLast(Yr, 9, 0));
    stopDST.setUTCHours(2 + offset);

    if ((now.getTime() > startDST.getTime()) && (now.getTime() < stopDST.getTime())) {
      now.setUTCHours(now.getUTCHours() + offset + 1);
    } else {
      now.setUTCHours(now.getUTCHours() + offset);
    }

    var hours = now.getUTCHours();
    var minutes = now.getUTCMinutes();
    var timeString = hours + ":" + minutes;
    return timeString;
  }
  catch (e) {
    if (e instanceof Error) {
      alert(e.name + ": " + e.message);
    }
  }
}