forsyth20121205-174063a80cc13 years agoHistory
495 lines · 11.1 KB · Brainfuck
RawDownload
# the Date object is founded on the Daytime module UTC: con 1;msPerSec: con big 1000; # based on Daytime->Tm with big fieldsbigTm: adt {	ms:	big;	sec:	big;	min:	big;	hour:	big;	mday:	big;	mon:	big;	year:	big;	tzoff:	int;}; isfinite(r: real): int{	if(math->isnan(r) || r == +Infinity || r == -Infinity)		return 0;	return 1;} time2Tm(t: real, utc: int): ref Daytime->Tm{	secs := int(big t / msPerSec);	if(big t % msPerSec < big 0)	# t<0?		secs -= 1;	if(utc)		tm := daytime->gmt(secs);	else		tm = daytime->local(secs);	return tm;} time2bigTm(t: real, utc: int): ref bigTm{	tm := time2Tm(t, utc);	btm := ref bigTm;	btm.ms = big t % msPerSec;	if(btm.ms < big 0)		btm.ms += msPerSec;	btm.sec = big tm.sec;	btm.min = big tm.min;	btm.hour = big tm.hour;	btm.mday = big tm.mday;	btm.mon = big tm.mon;	btm.year = big tm.year;	btm.tzoff = tm.tzoff;	return btm;} bigTm2time(btm: ref bigTm): real{	# normalize	if(btm.mon / big 12 != big 0){		btm.year += btm.mon / big 12;		btm.mon %= big 12;	}	if(btm.ms / msPerSec != big 0){		btm.sec += btm.ms / msPerSec;		btm.ms %= msPerSec;	}	if(btm.sec / big 60 != big 0){		btm.min += btm.sec / big 60;		btm.sec %= big 60;	}	if(btm.min / big 60 != big 0){		btm.hour += btm.hour / big 60;		btm.min %= big 60;	}	if(btm.hour / big 24 != big 0){		btm.mday += btm.mday / big 24;		btm.hour %= big 24;	} 	tm := ref Tm;	tm.sec = int btm.sec;	tm.min = int btm.min;	tm.hour = int btm.hour;	tm.mday = int btm.mday;	tm.mon = int btm.mon;	tm.year = int btm.year;	tm.tzoff = btm.tzoff;	secs := daytime->tm2epoch(tm);	# check for out-of-band times	if(secs == daytime->tm2epoch(daytime->gmt(secs)))		r := real(big secs * msPerSec + btm.ms);	else		r = Math->NaN;	return r;} str2time(s: string): real{	tm := daytime->string2tm(s);	if(tm == nil)		r := Math->NaN;	else		r = real (big daytime->tm2epoch(tm) * msPerSec);	return r;} cdate(nil: ref Exec, nil, nil: ref Ecmascript->Obj, nil: array of ref Val): ref Val{	return strval(daytime->time());} # process arguments of Date() [called as constructor] and Date.UTC()datectorargs(ex: ref Exec, args: array of ref Val): (int, ref bigTm){	x := array[7] of { * => big 0 };	ok := 1;	for(i := 0; i < 7 && i < len args; i++){		if(!isfinite(toNumber(ex, biarg(args, i))))			ok = 0;		else			x[i] = big toInteger(ex, biarg(args, i));	}	btm := ref bigTm;	yr := x[0];	if(yr >= big 0 && yr <= big 99)		btm.year = yr;	else		btm.year = yr - big 1900;	btm.mon = x[1];	btm.mday = x[2];	btm.hour = x[3];	btm.min = x[4];	btm.sec = x[5];	btm.ms = x[6];	return (ok, btm);} ndate(ex: ref Exec, nil: ref Ecmascript->Obj, args: array of ref Val): ref Ecmascript->Obj{	o := mkobj(ex.dateproto, "Date");	r := Math->NaN;	case len args{	0 =>		r = real(big daytime->now() * msPerSec);	1 =>		v := toPrimitive(ex, biarg(args, 0), NoHint);		if(isstr(v))			r = str2time(v.str);		else if(isfinite(toNumber(ex, v))){			t := big toInteger(ex, v);			secs := t / msPerSec;			if(big t % msPerSec < big 0)				secs -= big 1;			if(secs == big int secs)				r = real t;		}	* =>		(ok, btm) := datectorargs(ex, args);		if(ok){			tm := daytime->local(daytime->now());			btm.tzoff = tm.tzoff;			r = bigTm2time(btm);		}	}	o.val = numval(r);	return o;} cdateparse(ex: ref Exec, nil, nil: ref Ecmascript->Obj, args: array of ref Val): ref Val{	s := toString(ex, biarg(args, 0));	return numval(str2time(s));} cdateUTC(ex: ref Exec, nil, nil: ref Ecmascript->Obj, args: array of ref Val): ref Val{	r := Math->NaN;	if(len args == 0)		r = real(big daytime->now() * msPerSec);	else{		(ok, btm) := datectorargs(ex, args);		if(ok){			btm.tzoff = 0;			r = bigTm2time(btm);		}	}	return numval(r);} datecheck(ex: ref Exec, o: ref Ecmascript->Obj, f: string){	if(!isdateobj(o))		runtime(ex, TypeError, "Date.prototype." + f + " called on non-Date object");} cdateprototoString(ex: ref Exec, f, this: ref Ecmascript->Obj, nil: array of ref Val): ref Val{	datecheck(ex, this, f.val.str);	secs := 0;	t := this.val.num;	if(!math->isnan(t)){		secs = int(big t / msPerSec);		if(big t % msPerSec < big 0)			secs -= 1;	}	return strval(daytime->text(daytime->local(secs)));} cdateprototoDateString(ex: ref Exec, f, this: ref Ecmascript->Obj, nil: array of ref Val): ref Val{	datecheck(ex, this, f.val.str);	secs := 0;	t := this.val.num;	if(!math->isnan(t)){		secs = int(big t / msPerSec);		if(big t % msPerSec < big 0)			secs -= 1;	}	s := daytime->text(daytime->local(secs));	(n, ls) := sys->tokenize(s, " ");	if(n < 3)		return strval("");	return strval(hd ls + " " + hd tl ls + " " + hd tl tl ls);} cdateprototoTimeString(ex: ref Exec, f, this: ref Ecmascript->Obj, nil: array of ref Val): ref Val{	datecheck(ex, this, f.val.str);	secs := 0;	t := this.val.num;	if(!math->isnan(t)){		secs = int(big t / msPerSec);		if(big t % msPerSec < big 0)			secs -= 1;	}	s := daytime->text(daytime->local(secs));	(n, ls) := sys->tokenize(s, " ");	if(n < 4)		return strval("");	return strval(hd tl tl tl ls);} cdateprotovalueOf(ex: ref Exec, f, this: ref Ecmascript->Obj, nil: array of ref Val): ref Val{	datecheck(ex, this, f.val.str);	return this.val;} cdateprotoget(ex: ref Exec, f, this: ref Ecmascript->Obj, nil: array of ref Val, utc: int): ref Val{	datecheck(ex, this, f.val.str);	t := this.val.num;	if(!math->isnan(t)){		tm := time2Tm(t, utc);		case f.val.str{		"Date.prototype.getYear" =>			if (tm.year < 0 || tm.year > 99)				t = real(tm.year + 1900);			else				t = real tm.year;		"Date.prototype.getFullYear" or		"Date.prototype.getUTCFullYear" =>			t = real(tm.year + 1900);		"Date.prototype.getMonth" or		"Date.prototype.getUTCMonth" =>			t = real tm.mon;		"Date.prototype.getDate" or		"Date.prototype.getUTCDate" =>			t = real tm.mday;		"Date.prototype.getDay" or		"Date.prototype.getUTCDay" =>			t = real tm.wday;		"Date.prototype.getHours" or		"Date.prototype.getUTCHours" =>			t = real tm.hour;		"Date.prototype.getMinutes" or		"Date.prototype.getUTCMinutes" =>			t = real tm.min;		"Date.prototype.getSeconds" or		"Date.prototype.getUTCSeconds" =>			t = real tm.sec;		}	}	return numval(t);} cdateprotogetMilliseconds(ex: ref Exec, f, this: ref Ecmascript->Obj, nil: array of ref Val): ref Val{	datecheck(ex, this, f.val.str);	t := this.val.num;	if(!math->isnan(t)){		ms := big t % msPerSec;		if(ms < big 0)			ms += msPerSec;		t = real ms;	}	return numval(t);} cdateprotogetTimezoneOffset(ex: ref Exec, f, this: ref Ecmascript->Obj, nil: array of ref Val): ref Val{	datecheck(ex, this, f.val.str);	t := this.val.num;	if(!math->isnan(t)){		tm := time2Tm(t, !UTC);		t = real(tm.tzoff / 60);	}	return numval(t);} # process arguments of Date.prototype.set*() functionsdateprotosetargs(ex: ref Exec, this: ref Ecmascript->Obj, args: array of ref Val, n: int): (int, big, big, big, big){	x := array[4] of { * => big 0 };	ok := 1;	if(this != nil && !isfinite(this.val.num))		ok = 0;	for(i := 0; i < n && i < len args; i++){		if(!isfinite(toNumber(ex, biarg(args, i))))			ok = 0;		else			x[i] = big toInteger(ex, biarg(args, i));	}	return (ok, x[0], x[1], x[2], x[3]);} cdateprotosetTime(ex: ref Exec, f, this: ref Ecmascript->Obj, args: array of ref Val): ref Val{	datecheck(ex, this, f.val.str);	r := Math->NaN;	(ok, t, nil, nil, nil) := dateprotosetargs(ex, nil, args, 1);	if(ok){		secs := t / msPerSec;		if(big t % msPerSec < big 0)			secs -= big 1;		if(secs == big int secs)			r = real t;	}	this.val.num = r;	return numval(r);} cdateprotosetMilliseconds(ex: ref Exec, f, this: ref Ecmascript->Obj, args: array of ref Val, utc: int): ref Val{	datecheck(ex, this, f.val.str);	r := Math->NaN;	(ok, ms, nil, nil, nil) := dateprotosetargs(ex, this, args, 1);	if(ok){		btm := time2bigTm(this.val.num, utc);		btm.ms = ms;		r = bigTm2time(btm);	}	this.val.num = r;	return numval(r);} cdateprotosetSeconds(ex: ref Exec, f, this: ref Ecmascript->Obj, args: array of ref Val, utc: int): ref Val{	datecheck(ex, this, f.val.str);	r := Math->NaN;	(ok, sec, ms, nil, nil) := dateprotosetargs(ex, this, args, 2);	if(ok){		btm := time2bigTm(this.val.num, utc);		btm.sec = sec;		if(len args > 1)			btm.ms = ms;		r = bigTm2time(btm);	}	this.val.num = r;	return numval(r);} cdateprotosetMinutes(ex: ref Exec, f, this: ref Ecmascript->Obj, args: array of ref Val, utc: int): ref Val{	datecheck(ex, this, f.val.str);	r := Math->NaN;	(ok, min, sec, ms, nil) := dateprotosetargs(ex, this, args, 3);	if(ok){		btm := time2bigTm(this.val.num, utc);		btm.min = min;		if(len args > 1){			btm.sec = sec;			if(len args > 2)				btm.ms = ms;		}		r = bigTm2time(btm);	}	this.val.num = r;	return numval(r);} cdateprotosetHours(ex: ref Exec, f, this: ref Ecmascript->Obj, args: array of ref Val, utc: int): ref Val{	datecheck(ex, this, f.val.str);	r := Math->NaN;	(ok, hour, min, sec, ms) := dateprotosetargs(ex, this, args, 4);	if(ok){		btm := time2bigTm(this.val.num, utc);		btm.hour = hour;		if(len args > 1){			btm.min = min;			if(len args > 2){				btm.sec = sec;				if(len args > 3)					btm.ms = ms;			}		}		r = bigTm2time(btm);	}	this.val.num = r;	return numval(r);} cdateprotosetDate(ex: ref Exec, f, this: ref Ecmascript->Obj, args: array of ref Val, utc: int): ref Val{	datecheck(ex, this, f.val.str);	r := Math->NaN;	(ok, day, nil, nil, nil) := dateprotosetargs(ex, this, args, 1);	if(ok){		btm := time2bigTm(this.val.num, utc);		btm.mday = day;		r = bigTm2time(btm);	}	this.val.num = r;	return numval(r);} cdateprotosetMonth(ex: ref Exec, f, this: ref Ecmascript->Obj, args: array of ref Val, utc: int): ref Val{	datecheck(ex, this, f.val.str);	r := Math->NaN;	(ok, mon, day, nil, nil) := dateprotosetargs(ex, this, args, 2);	if(ok){		btm := time2bigTm(this.val.num, utc);		btm.mon = mon;		if(len args > 1)			btm.mday = day;		r = bigTm2time(btm);	}	this.val.num = r;	return numval(r);} cdateprotosetFullYear(ex: ref Exec, f, this: ref Ecmascript->Obj, args: array of ref Val, utc: int): ref Val{	datecheck(ex, this, f.val.str);	r := Math->NaN;	(ok, year, mon, day, nil) := dateprotosetargs(ex, nil, args, 3);	if(ok){		t := this.val.num;		if(!isfinite(t))			t = 0.;		btm := time2bigTm(t, utc);		btm.year = (year - big 1900);		if(len args > 1){			btm.mon = mon;			if(len args > 2)				btm.mday = day;		}		r = bigTm2time(btm);	}	this.val.num = r;	return numval(r);} cdateprotosetYear(ex: ref Exec, f, this: ref Ecmascript->Obj, args: array of ref Val): ref Val{	datecheck(ex, this, f.val.str);	r := Math->NaN;	(ok, year, nil, nil, nil) := dateprotosetargs(ex, nil, args, 1);	if(ok){		t := this.val.num;		if(!isfinite(t))			t = 0.;		btm := time2bigTm(t, !UTC);		if(year >= big 0 && year <= big 99)			btm.year = year;		else			btm.year = year - big 1900;		r = bigTm2time(btm);	}	this.val.num = r;	return numval(r);} cdateprototoUTCString(ex: ref Exec, f, this: ref Ecmascript->Obj, nil: array of ref Val): ref Val{	datecheck(ex, this, f.val.str);	secs := 0;	t := this.val.num;	if(!math->isnan(t)){		secs = int(big t / msPerSec);		if(big t % msPerSec < big 0)			secs -= 1;	}	return strval(daytime->text(daytime->gmt(secs)));}