/*  ******************************************************************
 **  Soubor  :  /ariadne/javascript/date.js
 **
 **  Modul   :  Práce s datem/časem
 **  Verze   :  0.1.0
 **
 **  Autor   :  Michal Hromádko      michal.hromadko@lifeweb.cz
 **  Revize  :  Martin Jonáš         martin.jonas@lifeweb.cz
 **
 **  Popis   :  Funkce pro vypsání a zpětné rozparsování data/času
 **             ve zvoleném formátu
 ** ***************************************************************** */

/**
 * Funkce přidává počáteční nulu ke dvoumístným hodnotám
 * @param x Zadaná hodnota
 * @return Vrací řetězec upravený na délku 2 znaků
 */
function LZ(x) {
  return (((x < 0) || (x > 9)) ? "" : "0") + x;
}

/**
 * Funkce zkontroluje zda zadané datum odpovídá zadanému formátu
 * @param val  Kontrolované datum
 * @param format Požadovaný formát data
 * @return Vrací true při správnosti data, jinak false
 */
function isDateInFormat(val, format) {
  var date = getDateFromFormat(val, format);
  return (date != 0);
}

/**
 * Funkce formátuje datum dle zadaného formátu
 * @param date Zadané datum
 * @param format Požadovaný formát data
 * @return Vrací řetězec se sformátovaným datem
 */
function formatDate(date, format) {

  /**
   * Pomocná funkce která upravuje požadovaný formát data
   */
  function rep(re, str) {
    format = format.replace(re, str);
  };

  format = format + "";

  // Standartní výpis data
  rep(/%D/, "%m/%d/%y");
  // Standartní výpis času
  rep(/%T/, "%H:%M:%S");


  var result = "";
  var i_format = 0;
  var c = "";
  var token = "";

  var dat = date.getDate(); //Returns the day of the month from a Date object (from 1-31)
  var day = date.getDay(); //Returns the day of the week from a Date object (from 0-6)
  var month = date.getMonth(); //Returns the month from a Date object (from 0-11)
  var year = date.getFullYear(); //Returns the year, as a four-digit number, from a Date object
  var hours = date.getHours(); //Returns the hour of a Date object (from 0-23)
  var minutes = date.getMinutes(); //Returns the minutes of a Date object (from 0-59)
  var seconds = date.getSeconds(); //Returns the seconds of a Date object (from 0-59)
  var milliseconds = date.getMilliseconds(); //Returns the milliseconds of a Date object (from 0-999)
  var time = date.getTime(); //Returns the number of milliseconds since midnight Jan 1, 1970
  var timezone = date.getTimezoneOffset(); //Returns the difference in minutes between local time and Greenwich Mean Time (GMT)

  // Převedení částí data do formátovaných řetězců
  var value = new Object();

  // Století (rok vydělený 100 a zaokrouhlený na celé číslo, rozsah 00 až 99)
  value["%C"] = LZ(Math.floor(year / 100));

  // Den v měsíci jako číslo (rozsah 01 až 31)
  value["%d"] = LZ(dat);

  // Den v měsíci jako číslo, samostatná číslice je předcházena mezerou (rozsah ' 1' až '31')
  value["%e"] = (dat < 10) ? " " + dat : dat;

  // Stejné jako %b
  value["%h"] = value["%b"];

  // Hodina jako číslo, použití 24-hodinového systému (rozsah 00 až 23)
  value["%H"] = LZ(hours);

  // Hodina jako číslo, použití 12-hodinového systému (rozsah 01 až 12)
  if (hours == 0) {
    value["%I"] = 12;
  } else if (hours > 12) {
    value["%I"] = LZ(hours - 12);
  } else {
    value["%I"] = LZ(hours);
  }

  // Měsíc jako číslo (rozsah 01 až 12)
  value["%m"] = LZ(month + 1);

  // Minuta jako číslo
  value["%M"] = LZ(minutes);

  // Znak "nový řádek"
  value["%n"] = "\n";

  // AM nebo PM
  value["%p"] = (hours < 12) ? "AM" : "PM";

  // Sekunda jako číslo
  value["%S"] = LZ(seconds);

  // Zank "tabulátor"
  value["%t"] = "\t";

  // Rok jako číslo bez století (rozsah 00 až 99)
  value["%y"] = LZ(year % 100);

  // Rok jako číslo se stoletím
  value["%Y"] = year;

  // Zank "%"
  value["%%"] = "%";

  // Čas v am/pm notaci
  value["%r"] = value["%I"] + ":" + value["%M"] + ":" + value["%S"] + " " + value["%p"];

  // Čas ve 24-hodinové notaci
  value["%R"] = value["%H"] + ":" + value["%M"];

  // Projde celý formát a zástupné znaky (tokeny) nahradí zformátovanýmy řetězci
  while (i_format < format.length) {
    c = format.charAt(i_format);
    // První znak tokenu
    if (c == "%") {
      token = "%";
      i_format++;
      // Druhý znak tokenu
      if (i_format < format.length) {
        token += format.charAt(i_format);
      }
      // Pokud je token známý, nahradí se zformátovaným řetězcem
      if (value[token] != null) {
        result += value[token];
      // Neznámý token se vypíše
      } else {
        result += token;
      }
    // Ostatní znaky
    } else {
      result += c;
    }
    i_format++;
  }

  return result;
}

/**
 * Funkce získá datum z řetězce podle zadaného formátu
 * Podporuje tagy %H, %M, %S, %m, %d, %Y, %y, %D, %T
 * @param val Řetězec obsahující datum
 * @param format Formát data
 * @return Vrací timestamp jako číslo. Při neúspěšném překladu vrací 0.
 */
function getDateFromFormat(val, format) {

  /**
   * Pomocná funkce která upravuje požadovaný formát data
   */
  function rep(re, str) {
    format = format.replace(re, str);
  };

  format = format + "";
  val = val + "";

  // Standartní výpis data
  rep(/%D/, "%m/%d/%y");
  // Standartní výpis času
  rep(/%T/, "%H:%M:%S");

  var i_format = 0;
  var i_val = 0;
  var c = "";
  var token = "";

  var date = new Date();

  var dat = 0;
  var month = 0;
  var year = 2000;
  var hours = 0;
  var minutes = 0;
  var seconds = 0;

  // Projde formát a pokusí se získat ze zadaného řetězce příslušné hodnoty
  while (i_format < format.length) {
    c = format.charAt(i_format);
    // První nznak tokenu
    if (c == "%") {
      token = c;
      i_format++;
      // Druhý znak tokenu
      if (i_format < format.length) {
        token += format.charAt(i_format);
      }

      switch (token) {
        // Hodina jako číslo, použití 24-hodinového systému (rozsah 00 až 23)
        case "%H":
          hours = val.substr(i_val, 2);
          i_val += 2;

          if (!IsInteger(hours))
            return 0;
          break;

        // Minuta jako číslo
        case "%M":
          minutes = val.substr(i_val, 2);
          i_val += 2;

          if (!IsInteger(minutes))
            return 0;
          break;

        // Sekunda jako číslo
        case "%S":
          seconds = val.substr(i_val, 2);
          i_val += 2;

          if (!IsInteger(seconds))
            return 0;
          break;

        // Měsíc jako číslo (rozsah 01 až 12)
        case "%m":
          month = val.substr(i_val, 2);
          i_val += 2;

          if (!IsInteger(month))
            return 0;
          break;

        // Den v měsíci jako číslo (rozsah 01 až 31)
        case "%d":
          dat = val.substr(i_val, 2);
          i_val += 2;

          if (!IsInteger(dat))
            return 0;
          break;

        // Rok jako číslo se stoletím
        case "%Y":
          year = val.substr(i_val, 4);
          i_val += 4;

          if (!IsInteger(year))
            return 0;
          break;

        // Rok jako číslo bez století (rozsah 00 až 99)
        case "%y":
          year = val.substr(i_val, 2);
          i_val += 2;

          if (!IsInteger(year))
            return 0;

          year = parseInt(year);
          if (year >= 70) {
            year += 1900;
          } else {
            year += 2000;
          }

          break;

        default:   return 0;
      }
    } else {
      // Kontrola zda znak v řetězci odpovídá znaku ve formátu
      if (val.charAt(i_val) != c) {
        return 0;
      }
      i_val ++;
    }
    i_format++;
  }

  // Kontrola délek řetězce a formátu
  if (i_format != format.length || i_val != val.length)
    return 0;

  date.setDate(dat);
  date.setMonth(month - 1);
  date.setFullYear(year);
  date.setHours(hours);
  date.setMinutes(minutes);
  date.setSeconds(seconds);

  return date.getTime();
}

