<!--
////////////////////////////////////////////////////////
// Copyright 2003, Timothy James Forsythe, all rights reserved.
// Permission granted to use, copy, modify, and distribute so long as
// the above copyright and this permission statement are retained in all
// copies.  THERE IS NO WARRANTY - USE AT YOUR OWN RISK.
//
// based on the algorithms of Rick McCarty
////////////////////////////////////////////////////////////////////////
//
//    Algorithm for Converting Gregorian Dates to ISO 8601 Week Date
//                            (Y2K  Compliant)
//                           Rick McCarty, 1999
//
//                     From: Gregorian Year-Month-Day
//                 To: ISO YearNumber-WeekNumber-Weekday 
//
//ISO 8601 specifies that Week 01 of the year is the week containing
//the first Thursday; Monday is Weekday 1, Sunday is Weekday 7;
//WeekNumber requires two digits (W01, W02, etc.; "W" is optional)
//
//Algorithm Conventions:
//   "/" = integer division, discard remainder  (5/2 = 2)
//   "%" = modulus, keep only remainder    (5%2 = 1)
//   "&" = concatenation   ("W" & 12 = "W12")
//   "!=" = unequal   (7 != 8  is true)
//   "+=" = add right value to left variable,
//             if F = 3, then (F += 4) yields F = 7
//   "-=" = subtract right value from left variable
//
//1. Convert input to Y M D
//   Y = Year     (full specification; input 98 = year 0098)
//   M = Month    (1 through 12)
//   D = Day      (1 through 31)
//2. Find if Y is LeapYear
//   if (Y % 4 = 0  and  Y % 100 != 0) or Y % 400 = 0
//      then
//         Y is LeapYear
//      else
//         Y is not LeapYear
//3. Find if Y-1 is LeapYear
//4. Find the DayOfYearNumber for Y M D
//   Mnth[1] = 0    Mnth[4] = 90    Mnth[7] = 181   Mnth[10] = 273
//   Mnth[2] = 31   Mnth[5] = 120   Mnth[8] = 212   Mnth[11] = 304
//   Mnth[3] = 59   Mnth[6] = 151   Mnth[9] = 243   Mnth[12] = 334
//   DayOfYearNumber = D + Mnth[M]
//   if Y is LeapYear and M > 2
//      then
//         DayOfYearNumber += 1
//5. Find the Jan1Weekday for Y (Monday=1, Sunday=7)
//   YY = (Y-1) % 100
//   C = (Y-1) - YY
//   G = YY + YY/4
//   Jan1Weekday = 1 + (((((C / 100) % 4) x 5) + G) % 7)
//6. Find the Weekday for Y M D
//   H = DayOfYearNumber + (Jan1Weekday - 1)
//   Weekday = 1 + ((H -1) % 7)
//7. Find if Y M D falls in YearNumber Y-1, WeekNumber 52 or 53
//   if DayOfYearNumber <= (8-Jan1Weekday) and Jan1Weekday > 4
//      then
//         YearNumber = Y - 1 
//         if Jan1Weekday = 5 or (Jan1Weekday = 6 and Y-1 is LeapYear)
//            then
//               WeekNumber = 53
//            else 
//               WeekNumber = 52
//      else 
//         YearNumber = Y
//8. Find if Y M D falls in YearNumber Y+1, WeekNumber 1
//   if YearNumber = Y
//      then
//         if Y is LeapYear
//            then 
//               I = 366
//               else
//               I = 365
//         if (I - DayOfYearNumber) < (4 - Weekday)
//            then
//               YearNumber = Y + 1
//               WeekNumber = 1
//9. Find if Y M D falls in YearNumber Y, WeekNumber 1 through 53
//   if YearNumber = Y
//      then
//         J = DayOfYearNumber + (7 - Weekday) + (Jan1Weekday -1)
//         WeekNumber = J / 7
//         if Jan1Weekday > 4
//               WeekNumber -= 1
//10. Output ISO Week Date:
//   if WeekNumber < 10
//      then
//         WeekNumber = "0" & WeekNumber  (WeekNumber requires 2 digits)
//   YearNumber - WeekNumber - Weekday    (Optional: "W" & WeekNumber)
//
////////////////////////////////////////////////////////////////////////

function ISODate()
{
  this.d    = "";
  this.wstr = "";
  this.w    = "";
  this.y    = "";
}

function GregorianToIso8601(d,m,year)
{
  var GR_MO_LEN = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

  var date = new ISODate();
  
  if (year > 0)
  {
    var i;
  
    m=m-1;

    // 2.
    var leapYear = false;
    if (   (   ((year % 4) == 0)
            && ((year % 100) != 0)
           )
        || ((year % 400) == 0)
       )
    {
      leapYear = true;
      GR_MO_LEN[1] = 29;
    }
  
    // 4.
    var doy = 0;
    for (i=0; i<m; ++i)
    {
      doy += GR_MO_LEN[i];
    }
    doy += d;
  
    // 5.
    var temp1 = (year - 1) % 100;
    var temp2 = (year - 1) - temp1;
    var temp3 = temp1 + Math.floor(temp1 / 4);
    var startDay = 1 + ((((Math.floor(temp2 / 100) % 4) * 5) + temp3) % 7);

    // 6.
    date.d = 1 + ((doy + (startDay - 1) - 1) % 7);  
  
    // 7.
    var lastYearLY = false;
    if (   (   (((year-1) % 4) == 0)
            && (((year-1) % 100) != 0)
           )
        || (((year-1) % 400) == 0)
       )
    {
      lastYearLY = true;
    }

    if ((doy <= (8-startDay)) && (startDay > 4))
    {
      date.y = year - 1;
      if (   (startDay == 5) 
          || ((startDay == 6) && lastYearLY)
         )
      {
        date.w = 52;
      }
      else
      {
        date.w = 53;
      }
    }
    else
    {
      date.y = year;
    }
 
    // 8.
    if (date.y == year)
    {
      if (leapYear)
      {
        temp1 = 366;
      }
      else
      {
        temp1 = 365;
      }
     
      if ((temp1 - doy) < (4 - date.d))
      {
        date.y = year + 1;
        date.w = 1;
      }
    }

    // 9.
    if (date.y == year)
    {
      temp1 = doy + (7 - date.d) + (startDay - 1);
      date.w = Math.floor(temp1 / 7);
      if (startDay > 4)
      {
        date.w = date.w - 1;
      }
    }
 
    if (date.w < 10) 
    { 
      date.wstr = "W0" + date.w;
    }
    else
    {
      date.wstr = "W" + date.w;
    }  
  }  

  return date;
}

//-->
