
function dateTickGenerator(axis) {
	var res = [];
	var range = (axis.max-axis.min)*1000;
	var day = 3600*24*1000;
	var date = new Date(axis.min*1000);
	var months = ["J","F","M","A","M","J","J","A","S","O","N","D"];
	var monthsFull = ["Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"];
	var days = ["So", "Mo","Di","Mi","Do","Fr","Sa"];
	if (range<day){
		date.setMinutes(0);
		var adv = function(stamp) {
			return stamp+=day/24;
		}
		var ret = function(date) {
			var d = date.getHours();
			if (d%12==0)
				return d + ":00" + "<br/>"  + days[date.getDay()] + ", "+ date.getDate() + "." + (date.getMonth()+1);
			return d+ ":00";
		}
	}
	else if (range<day*2){
		date.setMinutes(0);
		var adv = function(stamp) {
			return stamp+=day/12;
		}
		var ret = function(date) {
			var d = date.getHours();
			if (d==0)
				return d + ":00" + "<br/>"  + days[date.getDay()] + ", "+ date.getDate() + "." + (date.getMonth()+1);
			return d+ ":00";
		}
	}
	else if (range<day*15){
		date.setHours(0);
		var adv = function(stamp) {
			return stamp+=day;
		}
		var ret = function(date) {
			var d = date.getHours();
			if (d==0)
				return days[date.getDay()] + "<br/>" + date.getDate() + "." + (date.getMonth()+1);
			return d;
		}
	}
	else if (range<day*30){
		date.setHours(0);
		var adv = function(stamp) {
			return stamp+=day;
		}
		var ret = function(date) {
			var d = date.getDate();
			if (d==15)
				return d + "<br/>" + monthsFull[date.getMonth()] + " " + date.getFullYear();
			return d;
		}
	}
	else {/* if (range<day*700)*/
		date.setDate(1);
		var adv = function(stamp) {
			return stamp+=day*31;
		}
		var ret = function(date) {
			var m = date.getMonth();
			if (m==6)
				return months[m] + "<br/>" + date.getFullYear();
			return months[m];
		}
	}
	var stamp = date.getTime(); 
	while (true) {
		//console.log(stamp);
		stamp = adv(stamp);
		var date = new Date(stamp);
		if (stamp > axis.max*1000)
			break;
		res.push([Math.round(stamp/1000), ret(date)]);
	}
	//console.log(res);
	return res;
}



function movingAverage(pairs, len, nofuture) {
	//pairs=[[x,y],[x,y],[x,y],[x,y]]
	var last=[],next=[],newpairs=[], sum=0, i=0, p, n, nexti=0;
	while(p=pairs[i++]) {
		var x = p[0],y = p[1];
		sum+=y;
		//analyze past data
		last.push(p);
		while (last[0] && Math.abs(last[0][0]-x)>=len) {
			sum -= last.shift()[1];
		}
		//look into the future
		if (!nofuture) {
			nexti = Math.max(nexti,i);
			while ((n = pairs[nexti]) && Math.abs(n[0]-x)<len) {
				next.push(n);
				sum+=n[1];
				nexti++;
			}
			
			while (next[0] && (Math.abs(next[0][0]-x)>=len || next[0][0]<x)) {
				sum -= next.shift()[1];
			}
		}
		//console.log(x,"nextlen",next.length,next,"diff",Math.abs(next[0][0]-x));
		newpairs.push([x, sum / ((last.length+next.length)||1)]);
	}
	return newpairs;
}



function formatDate(d, fmt, monthNames) {
    var leftPad = function(n) {
	n = "" + n;
	return n.length == 1 ? "0" + n : n;
    };
    
    var r = [];
    var escape = false;
    if (monthNames == null)
	monthNames = ["Jan", "Feb", "Mär", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"];
    for (var i = 0; i < fmt.length; ++i) {
	var c = fmt.charAt(i);
	
	if (escape) {
	    switch (c) {
	    case 'h': c = "" + d.getHours(); break;
	    case 'H': c = leftPad(d.getHours()); break;
	    case 'M': c = leftPad(d.getMinutes()); break;
	    case 'S': c = leftPad(d.getSeconds()); break;
	    case 'd': c = "" + d.getDate(); break;
	    case 'm': c = "" + (d.getMonth() + 1); break;
	    case 'y': c = "" + d.getFullYear(); break;
	    case 'b': c = "" + monthNames[d.getMonth()]; break;
	    }
	    r.push(c);
	    escape = false;
	}
	else {
	    if (c == "%")
		escape = true;
	    else
		r.push(c);
	}
    }
    return r.join("");
}
