/******************************************************************************
  Date enhancement Library © 2004 by roenving -- beta 0.99
  This library adds 5 methods to the standard javascript Date-object:
    .toDays()        returns daycount from UNIX-time start (works in UTC-time)
    .getWeek()       returns weeknumber of this year (or preceding or next year if applicable -- currently Danish/European: ISO-8601 !-)
    .age()           returns datedifference in age-style-array, e.g. array of years, months, days, hours, minutes, seconds and milliseconds since provided Date or a formatted text-string.
    .dateDiff()      returns either a timecount till now, a new date according to parameter differencies or an age-array
    .format()        returns a formatted Date-string according to the provided format-string

  For further information and a reference look in the accompanying text-file: roenvingDate.txt

  Last update: 2004-10-26
  Contact me if you experience unexpected trouble: 
  roenving [at] hot mail [dot] com

  Free to use if you retain this text-block
******************************************************************************/

function rD_argsFailure(a){
  alert('Argument(s) not supported'+(rD_argsFailure.arguments.length>0?"\nFailure on: "+a:""));
  return null;
}
function rD_twoDigits(num){
  return (10>num)?"0"+num:""+num;
}

Date.prototype.toDays = function(){return Math.floor(this.getTime()/(1000*60*60*24));}

Date.prototype.getWeek = function(){
  var firstDay = new Date(this.getFullYear(),0,1,this.getHours(),this.getMinutes(),this.getSeconds(),this.getMilliseconds());
  var fDay = firstDay.getDay();
  var fWeek = (fDay>0&&5>fDay)?1:0;
  var yearDayDiff = this.toDays()-firstDay.toDays();
  var thisWeek = fWeek+Math.floor(yearDayDiff/7)+((fDay>this.getDay()&&this.getDay()>0)?1:0);
  thisWeek = (thisWeek==53&&this.getDate()-this.getDay()>27)?1:(thisWeek!=0)?thisWeek:new Date(this.getFullYear()-1,11,31,this.getHours(),this.getMinutes(),this.getSeconds(),this.getMilliseconds()).getWeek();
  return thisWeek;
}
Date.prototype.age = function(d,ignoreTime,numFormat){
  args = this.age.arguments;
  if(args.length==0||args.length>=3&&typeof d != 'object')d = new Date();
  if(typeof d != 'object' || !d.getTime){
    return rD_argsFailure(typeof d);
  }
  if(d.getTime()>this.getTime()){
    var f = d;
    d = this;
  }else
    var f = this;
  ignoreTime = (args.length==1||!args[1])?false:true;
  var c = [1000,60,60,24];
  var t = new Array();
  t[t.length] = f.getFullYear() - d.getFullYear();
  t[t.length] = f.getMonth() - d.getMonth();
  t[t.length] = f.getDate() - d.getDate();
  t[t.length] = f.getHours() - d.getHours();
  t[t.length] = f.getMinutes() - d.getMinutes();
  t[t.length] = f.getSeconds() - d.getSeconds();
  t[t.length] = f.getMilliseconds() - d.getMilliseconds();
  for(i=6;i>2;i--){
    if(ignoreTime){
      t[i] = 0;
    }else if(0>t[i]){
      t[i] += c[6-i];
      t[i-1]--;
    }
  }
  if(0>t[2]){
    t[2] += new Date(f.getFullYear(),f.getMonth(),0).getDate();
    t[1]--;
  }
  if(0>t[1]){
    t[1] += 12;
    t[0]--;
  }
  if(3>args.length || typeof args[2] != 'number' || 1 > args[2])
    return [t[0],t[1],t[2],t[3],t[4],t[5],t[6]];
  var ftxt,ret="",started=false;
  if(typeof roenvingDate_text!='undefined'&&roenvingDate_text[5]!='undefined'){
    ftxt = roenvingDate_text[5];
  }else{
    ftxt = ['år','år','måned','måneder','dag','dage','time','timer','minut','minutter','sekund','sekunder','millisekund','millisekunder'];
  }
  for(i=0;args[2]>i;i++){
    if(!args[3]||t[i]!=0||started){
      started = true;
      ret += ", " + t[i] + " " + ((t[i]==1)?ftxt[i*2]:ftxt[i*2+1]);
    }
  }
  return (ret=="")?'0 '+ftxt[i*2-1]:ret.substring(2);
}

Date.prototype.dateDiff = function(){
  var args = this.dateDiff.arguments;
  if(args.length==0||args.length==1&&args[0]=='age'){
    return this.age();
  }
  if(args.length==1){
    if(args[0]=='set')return new Date(this.getTime());
    if(args[0]=='now'){
      var now = new Date();
      return now.getTime()-this.getTime();
    }
    return rD_argsFailure(args[0]);
  }
  switch(args[0]){
    case 'set':
      for(i=1;args.length>i;i++){
        if(typeof args[i] != 'number')
          return rD_argsFailure(typeof args[i]);
        else
          args[i] = parseInt(args[i]);
      }
      for(i=args.length;8>i;i++){
        args[i] = 0;
      }
      return new Date(this.getFullYear()+args[1],this.getMonth()+args[2],this.getDate()+args[3],this.getHours()+args[4],this.getMinutes()+args[5],this.getSeconds()+args[6],this.getMilliseconds()+args[7]);
    case 'age':
      if(typeof args[1] == 'object'){
        return (!args[1].getTime)?rD_argsFailure(typeof args[1]):this.age(args[1]);
      }
      if(4>args.length)return rD_argsFailure('Too few arguments to create a date');
      for(i=1;args.length>i;i++){
        if(typeof args[i] != 'number' || 0>args[i])
          return rD_argsFailure(typeof args[i]);
        else
          args[i] = parseInt(args[i]);
      }
      for(i=args.length;8>i;i++){
        args[i] = 0;
      }
      return this.age(new Date(args[1],args[2],args[3],args[4],args[5],args[6],args[7]));
    default:
      return rD_argsFailure(args[0]);
  }
  return args[0];
}
Date.prototype.format = function(fstring){
  if(this.format.arguments.length>0&&typeof fstring != 'string')return rD_argsFailure(fstring);
  fstring = (this.format.arguments.length==0)?"":fstring;
  var ftxt = new Array(),result="",str="";
  if(typeof roenvingDate_text!='undefined'){
    ftxt[0] = roenvingDate_text[0];
    ftxt[1] = roenvingDate_text[1];
    ftxt[2] = roenvingDate_text[2];
    ftxt[3] = roenvingDate_text[3];
  }else{
    ftxt[0] = ['januar','februar','marts','april','maj','juni','juli','august','september','oktober','november','december'];
    ftxt[1] = ['jan','feb','mar','apr','maj','jun','jul','aug','sep','okt','nov','dec'];
    ftxt[2] = ['søndag','mandag','tirsdag','onsdag','torsdag','fredag','lørdag'];
    ftxt[3] = ['søn','man','tir','ons','tor','fre','lør'];
  }
  var f = fstring.split("");
  var r = new Array(), esc = false, wsp = true, prev = "", acc = "";
  for(i=0;f.length>i;i++){
    if(esc){
      esc=false;
      acc += "\\"+f[i];
    }else if(f[i] == "\\"){
      if(prev != ""){
        r[r.length] = acc;
        prev = "";
        acc = "";
      }
      esc=true;
      continue;
    }else if(/[ymdhusw]/i.test(f[i])){
      if(wsp || f[i].toLowerCase() == prev.toLowerCase()){
        wsp = false;
      }else{
        r[r.length] = acc;
        acc = "";
      }
      prev = f[i];
      acc += f[i];
    }else{
      if(prev != ""){
        prev = "";
        r[r.length] = acc;
        acc = "";
      }
      if(/[\s\,\.\-\/\:]/.test(f[i])){
        r[r.length] = acc+f[i];
        wsp = true;
        acc = "";
      }else{
        wsp = false;
        acc += f[i];
      }
    }
  }
  if(acc != "")r[r.length] = acc;
  for(i=0;r.length>i;i++){
    if(!/^[ymdhusw]+$/i.test(r[i])){
      result += r[i].replace(/\\/g,"");
    }else{
      switch(r[i].charAt(0).toLowerCase()){
        case 'y':
          switch(r[i].length){
            case 2:
              result += (""+this.getFullYear()).substring(2);
              break;
            case 4:
              result += this.getFullYear();
              break;
            default:
              result += r[i];
          }
          break;
        case 'm':
          switch(r[i].length){
            case 1:
              result += (this.getMonth()+1);
              break;
            case 2:
              result += rD_twoDigits(this.getMonth()+1);
              break;
            case 3:
              str = ftxt[1][this.getMonth()];
              if(/^MM/.test(r[i])){
                str = str.toUpperCase();
              }else if(/^Mm/.test(r[i])){
                str = str.charAt(0).toUpperCase()+str.substring(1);
              }
              result += str;
              break;
            case 4:
              str = ftxt[0][this.getMonth()];
              if(/^MM/.test(r[i])){
                str = str.toUpperCase();
              }else if(/^Mm/.test(r[i])){
                str = str.charAt(0).toUpperCase()+str.substring(1);
              }
              result += str;
              break;
            default:
              result += r[i];
          }
          break;
        case 'd':
          switch(r[i].length){
            case 1:
              result += this.getDate();
              break;
            case 2:
              result += rD_twoDigits(this.getDate());
              break;
            case 3:
              str = ftxt[3][this.getDay()];
              if(/^DD/.test(r[i])){
                str = str.toUpperCase();
              }else if(/^Dd/.test(r[i])){
                str = str.charAt(0).toUpperCase()+str.substring(1);
              }
              result += str;
              break;
            case 4:
              str = ftxt[2][this.getDay()];
              if(/^DD/.test(r[i])){
                str = str.toUpperCase();
              }else if(/^Dd/.test(r[i])){
                str = str.charAt(0).toUpperCase()+str.substring(1);
              }
              result += str;
              break;
            default:
              result += r[i]
          }
          break;
        case 'h':
          switch(r[i].length){
            case 1:
              result += this.getHours();
              break;
            case 2:
              result += rD_twoDigits(this.getHours());
              break;
            default:
              result += r[i]
          }
          break;
        case 'u':
          switch(r[i].length){
            case 1:
              result += this.getMinutes();
              break;
            case 2:
              result += rD_twoDigits(this.getMinutes());
              break;
            default:
              result += r[i]
          }
          break;
        case 's':
          switch(r[i].length){
            case 1:
              result += this.getSeconds();
              break;
            case 2:
              result += rD_twoDigits(this.getSeconds());
              break;
            default:
              result += r[i]
          }
          break;
        case 'w':
          switch(r[i].length){
            case 1:
              result += this.getWeek();
              break;
            case 2:
              result += rD_twoDigits(this.getWeek());
              break;
            case 3:
              var WY = this.getFullYear();
              var WW = this.getWeek();
              WY += (WW==1&&this.getMonth()==11)?1:(WW>51&&this.getMonth()==0)?-1:0;
              result += WY + "W" + rD_twoDigits(WW);
              break;
            case 4:
              var WY = this.getFullYear();
              var WW = this.getWeek();
              WY += (WW==1&&this.getMonth()==11)?1:(WW>51&&this.getMonth()==0)?-1:0;
              result += WY + "W" + rD_twoDigits(WW) + ((this.getDay()==0)?7:this.getDay());
              break;
            default:
              result += r[i]
          }
      }
    }
  }
  return (result=="")?this.toLocaleString():result;
}
