	function formatDate(str, outFormat, lng, inFormat) {
		var dc = new DateTimeConverter();
		dc.strInDate = str;
		dc.outFormat = outFormat;
		dc.lng = lng;
		dc.inFormat = inFormat;
		dc.convert();
		document.write(dc.strOutDate);
	}

	function DateTimeConverter() {
		this.strInDate = null;
		this.strOutDate = null;
		this.inFormat = "";
		this.outFormat = "";
		this.inFormats = new inFormats();
		this.months = new Months();
		this.lng = "cz";

		this.date = null;
		this.day = 0;
		this.month = 0;
		this.year = null;
		this.sep = null;
		this.dIndex = 0;
		this.mIndex = 1;
		this.yIndex = 2;
		this.outParts = null
		this.outSep = null;
		this.namedMonth = false;

		this.convert = convert;

		this.create = create;
		this.parse = parse;
		this.validateInput = validateInput;

		this.processPart = pp;
		this.createPart = cp;
		this.createDay = cd;
		this.createMonth = cm;
		this.createYear = cy;

		this.isInFormat = isInFormat;

		function convert() {
			if ( isUnknown(this.lng) ) this.lng = "cz";
			if ( this.lng == "en" && isUnknown(this.outFormat) ) this.outFormat = "mm/dd/yyyy";
			if ( isUnknown(this.outFormat) ) this.outFormat = "d. m. yyyy";
			if ( isUnknown(this.inFormat) ) this.inFormat = "d.m.y";

			this.strOutDate = this.strInDate;
			if ( !this.validateInput() ) return this.strInDate; // 1) kontrola vstupnich parametru
			if ( !this.parse() ) return this.strfalse; // 2) kontrola vstupniho stringu, musi davat smysl; vytvoreni data
			this.create();
		}

		// sestavi vysledny string
		function create() {
			this.strOutDate = "";
			this.processPart(this.outParts[0], 1);
			this.processPart(this.outParts[1], 2);
			this.processPart(this.outParts[2], 3);

			return;
		}

		function pp(part, i) {
			var x, frm, arr;
			var prefix, suffix;

			x = part.toLowerCase();
			frm = x.replace(/ /g, "");
      arr = x.split(frm);
      prefix = arr[0].replace(/ /g, "&nbsp;");
      if ( arr.length > 1 ) suffix = arr[1].replace(/ /g, "&nbsp;");
      else suffix = "";
			part = getPart(frm);
			x = prefix + this.createPart(part, frm) + suffix;
			if ( i < 3 ) {
				if ( part == "m" ) {
					if ( !this.namedMonth ) x += this.outSep;
					else x += "&nbsp;";
				}
				else x += this.outSep;
			}
			this.strOutDate += x;

			return
			function getPart(x) {
				if ( x.indexOf("d") != -1 ) return "d";
				else if ( x.indexOf("m") != -1 ) return "m";
				else return "y";
			}
		}

		function cp(part, frm) {
			var x;

			switch ( part ) {
				case "d": x = this.createDay(frm); break;
				case "m": return this.createMonth(frm); break;
				case "y": return this.createYear(frm); break;
			}
			return x;
		}

		function cd(frm) {
			var x = String(this.date.getDate());
			if ( frm.length > 1 && x.length == 1 ) x = "0" + x;
			return x;
		}
		function cm(frm) {
			var i = this.date.getMonth() + 1;
			var x = String(i);
			switch ( frm.length ) {
				case 2:	if ( x.length == 1 ) x = "0" + x; break;
				case 3: eval("x = this.months[i-1]." + this.lng + ".nShort;"); this.namedMonth = true; break;
				case 4: eval("x = this.months[i-1]." + this.lng + ".nLong;"); this.namedMonth = true; break;
			}
			return x;
		}
		function cy(frm) {
			var x = this.date.getFullYear();
			if ( frm.length <= 2 ) {
				x = String(x).substr(2);
			}
			return x;
		}

		// fce parsuje jednotlive casti data
		function parse() {
			var i, di, mi, yi;
			var arr = new Array();

			this.strInDate = this.strInDate.replace(/ /g, ""); this.strInDate = this.strInDate.replace(/&nbsp;/g, "");

			di = this.inFormat.indexOf("d");
			mi = this.inFormat.indexOf("m");
			yi = this.inFormat.indexOf("y");

			arr[0] = new ni(di, "dIndex")
			arr[1] = new ni(mi, "mIndex")
			arr[2] = new ni(yi, "yIndex")

			// very primitive sort
			excompare(0, 1, arr); excompare(1, 2, arr); excompare(0, 1, arr);

			eval("this." + arr[0].part + "=0;");
			eval("this." + arr[1].part + "=1;");
			eval("this." + arr[2].part + "=2;");

			arr = this.strInDate.split(this.sep);
			for ( i=0;i<3;i++ ) if ( isNaN(arr[0]) ) return false;
			this.date = new Date(arr[this.yIndex], arr[this.mIndex] - 1, arr[this.dIndex]);

			return true;

			function excompare(i1, i2, arr) { if ( arr[i1].value > arr[i2].value ) exchange(i1, i2); }
			function exchange(i1, i2) { var tmp = arr[i1]; arr[i1] = arr[i2]; arr[i2] = tmp; }
			function ni(value, part) { this.value = value; this.part = part;}

		}

		// funkce kontroluje vstupni format a shodu s datem
		function validateInput() {
			var arr1, arr2;
			if ( !this.isInFormat() ) return false; // vstupni format neni znamy
			if ( this.strInDate.indexOf(this.sep) == -1 ) return false; // datum nema shodny oddelovac jako vstupni format
			if ( this.strInDate.indexOf(this.sep) == this.strInDate.lastIndexOf(this.sep) ) return false; // datum neni spravne formatovane

			if ( this.outFormat.indexOf(".") == -1 && this.outFormat.indexOf("/") == -1 ) return false;
			arr1 = this.outFormat.split("."); arr2 = this.outFormat.split("/");
			if ( arr1.length != 3 && arr2.length != 3 ) return false; // vystupni format neni v poradku
			if ( arr1.length == 3 && arr2.length != 1 || arr2.length == 3 && arr1.length != 1 ) return false; // vystupni format neni v poradku
			if ( arr1.length == 3 ) { this.outParts = arr1; this.outSep = "."; }
			else { this.outParts = arr2; this.outSep = "/"; }
			return true;
		}

		// testuje platnost vstupniho formatu
		function isInFormat() {
			for ( var i=0;i<this.inFormats.length;i++ ) if ( this.inFormat == this.inFormats[i] ) { this.sep = this.inFormat.substr(1,1); return true };
			return false;
		}
		function inFormats() {
			return "d/m/y;m/d/y;y/m/d;y/d/m;d.m.y;m.d.y;y.m.d;y.d.m".split(";");
		}
		function Months() {
			var i, arr = new Array(12);
			var arrLng = new Array();

			arrLng[0] = new Lng("cz", "Leden;Led|Únor;Únor|Březen;Bře|Duben;Dub|Květen;Kvě|Červen;Čer|Červenec;Čec|Srpen;Srp|Září;Zář|Říjen;Říj|Listopad;Lis|Prosinec;Pro");
			arrLng[1] = new Lng("en", "January;Jan|February;Feb|March;Mar|April;Apr|May;May|July;Jul|June;Jun|August;Aug|September;Sep|Otcober;Oct|November;Nov|December;Dec");

			for ( i=0;i<12;i++ ) arr[i] = new Month(i, arrLng);

			return arr;

			function Month(index, refA) {
        for ( var i=0;i<refA.length;i++ ) eval("this." + refA[i].lng + " = refA[" + i + "].items[" + index + "]");
      }
			function Lng(lng, str) {
				var i;
				var arr = str.split("|");
				for ( i=0;i<arr.length;i++ ) arr[i] = new nm(arr[i]);
				this.lng = lng;
				this.items = arr;
				function nm(m) {var a = m.split(";"); this.nLong = a[0]; this.nShort = a[1]; }
			}

		}
	}

function isUN(obj) {
	if ( typeof(obj) == "undefined" ) return true;
	return false;
}
function isUnknown(obj) {
	if ( isUN(obj) || obj == null || obj == "" ) return true;
	return false;
}