From cf5bf41d382ead79c99a58247bb75bcdbb9eb8fe Mon Sep 17 00:00:00 2001 From: "Mirar (Pontus Hagland)" <pike@sort.mirar.org> Date: Sat, 17 Jan 1998 00:13:46 +0100 Subject: [PATCH] Calendar moved from pike-modules repository Rev: lib/modules/Calendar.pmod/Gregorian.pmod:1.1 Rev: lib/modules/Calendar.pmod/Orthodox.pmod:1.1 Rev: lib/modules/Calendar.pmod/Swedish.pmod:1.1 --- lib/modules/Calendar.pmod/Gregorian.pmod | 758 +++++++++++++++++++++++ lib/modules/Calendar.pmod/Orthodox.pmod | 23 + lib/modules/Calendar.pmod/Swedish.pmod | 22 + 3 files changed, 803 insertions(+) create mode 100644 lib/modules/Calendar.pmod/Gregorian.pmod create mode 100644 lib/modules/Calendar.pmod/Orthodox.pmod create mode 100644 lib/modules/Calendar.pmod/Swedish.pmod diff --git a/lib/modules/Calendar.pmod/Gregorian.pmod b/lib/modules/Calendar.pmod/Gregorian.pmod new file mode 100644 index 0000000000..118edac67e --- /dev/null +++ b/lib/modules/Calendar.pmod/Gregorian.pmod @@ -0,0 +1,758 @@ + +//! module Calendar +//! +//! This module implements calendar calculations, and base classes +//! for time units. +//! +//! class time_unit +//! +//! method array(string) lesser() +//! Gives a list of methods to get lesser (shorter) time units. +//! ie, for a month, this gives back <tt>({"day"})</tt> +//! and the method <tt>day(mixed n)</tt> gives back that +//! day object. The method <tt>days()</tt> gives back a +//! list of possible argument values to the method <tt>day</tt>. +//! Concurrently, <tt>Array.map(o->days(),o->day)</tt> gives +//! a list of day objects in the object <tt>o</tt>. +//! +//! method array(string) greater() +//! Gives a list of methods to get greater (longer) time units +//! from this object. For a month, this gives back <tt>({"year"})</tt>, +//! thus the method <tt>month->year()</tt> gives the year object. +//! +//! method object next() +//! method object prev() +//! method object `+(int n) +//! method object `-(int n) +//! method object `-(object x) +//! next and prev gives the logical next and previous object. +//! The <tt>+</tt> operator gives that logical relative object, +//! ie <tt>my_day+14</tt> gives 14 days ahead. +//! <tt>-</tt> works the same way, but can also take an object +//! of the same type and give the difference as an integer. +//! +//! submodule Gregorian +//! time units: +//! <ref>Year</ref>, <ref>Month</ref>, <ref>Week</ref>, <ref>Day</ref> +//! +//! class + +array(string) month_names= + ({"January","February","Mars","April","May","June","July","August", + "September","October","November","December"}); + +array(string) week_day_names= + ({"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}); + +/* calculated on need */ + +mapping week_day_mapping,month_mapping; + +//== Year ==================================================================== + +class Year +{ +//! class Year +//! A <ref>Calendar.time_unit</ref>. +//! +//! Lesser units: <ref>Month</ref>, <ref>Week</ref>, <ref>Day</ref> +//! Greater units: none +//! +//! + +//-- variables ------------------------------------------------------ + + object this=this_object(); + program vYear=function_object(object_program(this))->Year; + program vDay=function_object(object_program(this))->Day; + program vMonth=function_object(object_program(this))->Month; + program vWeek=function_object(object_program(this))->Week; + + int y; + + array days_per_month; + array month_start_day; + +//-- standard methods ----------------------------------------------- + + array(string) lesser() + { + return ({"month","week","day"}); + } + + array(string) greater() + { + return ({}); + } + + void create(int ... arg) + { + if (!sizeof(arg)) + { + mapping t=localtime(time()); + y=1900+t->year; + } + else + y=arg[0]; + + int l=this->leap(); + days_per_month= + ({-17, 31,28+l,31,30,31,30,31,31,30,31,30,31}); + + month_start_day=allocate(sizeof(days_per_month)); + + for (int i=1,l=0; i<sizeof(days_per_month); i++) + month_start_day[i]=l,l+=days_per_month[i]; + } + + int `<(object x) + { + return y<(int)x; + } + + int `==(object x) + { + return + object_program(x)==object_program(this) && + (int)x==y; + } + + int `>(object x) + { + return y>(int)x; + } + + object next() + { + return vYear(y); + } + + object prev() + { + return vYear(y); + } + + object `+(int n) + { + return vYear(y+n); + } + + int|object `-(int|object n) + { + if (objectp(n) && object_program(n)==vYear) return y-n->y; + return this+-n; + } + +//-- nonstandard methods -------------------------------------------- + + int julian_day(int d) // jd%7 gives weekday, mon=0, sun=6 + { + int a; + a = (y-1)/100; + return 1721426 + d - a + (a/4) + (36525*(y-1))/100; + } + + int leap() + { + if (!(y%400)) return 1; + if (!(y%100)) return 0; + return !(y%4); + } + + int number_of_weeks() + { + int j=julian_day(0)%7; + + // years that starts on a thursday has 53 weeks + if (j==3) return 53; + // leap years that starts on a wednesday has 53 weeks + if (j==2 && this->leap()) return 53; + // other years has 52 weeks + return 52; + } + + int number_of_days() + { + return 365+this->leap(); + } + + int number() + { + return y; + } + + string name() + { + if (y>0) return (string)y+" AD"; + else return (string)(-y+1)+" BC"; + } + + mixed cast(string what) + { + switch (what) + { + case "int": return this->number(); + case "string": return this->name(); + default: + throw(({"can't cast to "+what+"\n",backtrace()})); + } + } + +//-- less ----------------------------------------------------------- + + object month(string|int n) + { + if (stringp(n)) + { + if (!week_day_mapping) + month_mapping= + mkmapping(Array.map(month_names,lower_case), + indices(allocate(13))[1..]); + n=month_mapping[n]; + } + + if (n<0) + return vMonth(y,13+n); + else + return vMonth(y,n); + } + + array(mixed) months() + { + return ({1,2,3,4,5,6,7,8,9,10,11,12}); + } + + object week(int n) + { + if (n<0) + return vWeek(y,this->number_of_weeks+n+1); + else + return vWeek(y,n||1); + } + + array(mixed) weeks() + { + return indices(allocate(this->number_of_weeks()+1))[1..]; + } + + object day(int n) + { + if (n<0) + return vDay(y,this->number_of_days()+n); + else + return vDay(y,n); + } + + array(mixed) days() + { + return indices(allocate(this->number_of_days())); + } + +//-- more ----------------------------------------------------------- + + // none +}; + + +// + +//== Month =================================================================== + +class Month +{ +//-- variables ------------------------------------------------------ + + object this=this_object(); + program vYear=function_object(object_program(this))->Year; + program vDay=function_object(object_program(this))->Day; + program vMonth=function_object(object_program(this))->Month; + program vWeek=function_object(object_program(this))->Week; + + int y; + int m; + +//-- standard methods ----------------------------------------------- + + array(string) lesser() + { + return ({"day"}); + } + + array(string) greater() + { + return ({"year"}); + } + + void create(int ... arg) + { + if (!sizeof(arg)) + { + mapping t=localtime(time()); + y=1900+t->year; + m=t->mon+1; + } + else + { + y=arg[0]; + m=arg[1]; + } + } + + int `<(object x) + { + return + (object_program(x)==object_program(this) && + (x->y==y && x->m<m) || (x->y<y)); + } + + int `==(object x) + { + return + object_program(x)==object_program(this) && + x->y==y && x->m==m; + } + + int `>(object x) + { + return + (object_program(x)==object_program(this) && + (x->y==y && x->m>m) || (x->y>y)); + } + + object `+(int n) + { + int m2=m; + int y2=y; + m2+=n; + while (m2>12) { y2++; m2-=12; } + while (m2<1) { y2--; m2+=12; } + return vMonth(y2,m2); + } + + int|object `-(object|int n) + { + if (objectp(n) && object_program(n)==vMonth) + return m-n->m+(y-n->y)*12; + return this+(-n); + } + + object next() + { + return this+1; + } + + object prev() + { + return this-1; + } + +//-- internal ------------------------------------------------------- + + int yday() + { + return this->year()->month_start_day[m]; + } + +//-- nonstandard methods -------------------------------------------- + + int number_of_days() + { + return this->year()->days_per_month[m]; + } + + int number() + { + return m; + } + + string name() + { + return month_names[this->number()-1]; + } + + mixed cast(string what) + { + switch (what) + { + case "int": return this->number(); + case "string": return this->name(); + default: + throw(({"can't cast to "+what+"\n",backtrace()})); + } + } + +//-- less ----------------------------------------------------------- + + object day(int n) + { + if (n<0) + return vDay(y,yday()+this->number_of_days()+n); + else + return vDay(y,yday()+(n||1)-1); + } + + array(mixed) days() + { + return indices(allocate(this->number_of_days()+1))[1..]; + } + +//-- more ----------------------------------------------------------- + + object year() + { + return vYear(y); + } +}; + + +// +//== Week ==================================================================== + +class Week +{ +//-- variables ------------------------------------------------------ + + object this=this_object(); + program vYear=function_object(object_program(this))->Year; + program vDay=function_object(object_program(this))->Day; + program vMonth=function_object(object_program(this))->Month; + program vWeek=function_object(object_program(this))->Week; + + int y; + int w; + +//-- standard methods ----------------------------------------------- + + array(string) lesser() + { + return ({"day"}); + } + + array(string) greater() + { + return ({"year"}); + } + + void create(int ... arg) + { + if (!sizeof(arg)) + { + object wp=vDay()->week(); + y=wp->y; + w=wp->w; + } + else + { + y=arg[0]; + w=arg[1]; + } + } + + int `<(object x) + { + return + (object_program(x)==object_program(this) && + (x->y==y && x->w<w) || (x->y<y)); + } + + int `==(object x) + { + return + object_program(x)==object_program(this) && + x->y==y && x->w==w; + } + + int `>(object x) + { + return + (object_program(x)==object_program(this) && + (x->y==y && x->w>w) || (x->y>y)); + } + + object `+(int n) + { + int y2=y,nd; + int w2=w; + w2+=n; + + if (w2>0) + { + nd=vYear(y)->number_of_weeks(); + while (w2>nd) + { + w2-=nd; + y2++; + nd=vYear(y2)->number_of_weeks(); + } + } + else + while (w2<1) + { + y2--; + w2+=vYear(y2)->number_of_weeks(); + } + return vWeek(y2,w2); + } + + int|object `-(int|object n) + { + if (object_program(n)==vWeek && objectp(n)) + return (this->day(1)-n->day(1))/7; + return this+(-n); + } + + object next() + { + return this+1; + } + + object prev() + { + return this-1; + } + +//-- internal ------------------------------------------------------- + + int yday() + { + return + ({-1,-2,-3,-4,5,6,7})[this->year()->julian_day(0)%7] + +7*(w-1); + } + +//-- nonstandard methods -------------------------------------------- + + int number_of_days() + { + return 7; + } + + int number() + { + return w; + } + + string name() + { + return "w"+(string)this->number(); + } + + mixed cast(string what) + { + switch (what) + { + case "int": return this->number(); + case "string": return this->name(); + default: + throw(({"can't cast to "+what+"\n",backtrace()})); + } + } + +//-- less ----------------------------------------------------------- + + object day(int|string n) + { + if (stringp(n)) + { + if (!week_day_mapping) + week_day_mapping= + mkmapping(Array.map(week_day_names,lower_case), + indices(allocate(8))[1..]); + n=week_day_mapping[n]; + } + + if (n<0) n=8+n; + else if (!n) n=1; + n+=yday()-1; + if (n<0) return vYear(y-1)->day(n+1); + if (n+1>this->year()->number_of_days()) + return vYear(y+1)->day(n-this->year()->number_of_days()); + return vDay(y,n+1); + } + + array(mixed) days() + { + return ({1,2,3,4,5,6,7}); + } + +//-- more ----------------------------------------------------------- + + object year() + { + return vYear(y); + } +}; + +// +//== Day ===================================================================== + +class Day +{ +//-- variables ------------------------------------------------------ + + object this=this_object(); + program vYear=function_object(object_program(this))->Year; + program vDay=function_object(object_program(this))->Day; + program vMonth=function_object(object_program(this))->Month; + program vWeek=function_object(object_program(this))->Week; + + int y; + int d; + +//-- standard methods ----------------------------------------------- + + array(string) lesser() + { + return ({}); + } + + array(string) greater() + { + return ({"year","month","week"}); + } + + void create(int ... arg) + { + if (!sizeof(arg)) + { + mapping t=localtime(time()); + y=1900+t->year; + d=t->yday; + } + else + { + y=arg[0]; + d=arg[1]; + } + } + + int `<(object x) + { + return + (object_program(x)==object_program(this) && + (x->y==y && x->d<d) || (x->y<y)); + } + + int `==(object x) + { + return + object_program(x)==object_program(this) && + x->y==y && x->d==d; + } + + int `>(object x) + { + return + (object_program(x)==object_program(this) && + (x->y==y && x->d>d) || (x->y>y)); + } + + object `+(int n) + { + int y2=y,nd; + int d2=d; + d2+=n; + + if (d2>0) + { + nd=vYear(y)->number_of_days(); + while (d2>=nd) + { + d2-=nd; + y2++; + nd=vYear(y2)->number_of_days(); + } + } + else + while (d2<0) + { + y2--; + d2+=vYear(y2)->number_of_days(); + } + return vDay(y2,d2); + } + + int|object `-(object|int n) + { + if (objectp(n) && object_program(n)==vDay) + return (this->julian_day()-n->julian_day()); + + return this+(-n); + } + + object next() + { + return this+1; + } + + object prev() + { + return this-1; + } + +//-- nonstandard methods -------------------------------------------- + + int julian_day() + { + return vYear(y)->julian_day()+d; + } + + int year_day() + { + return d; + } + + int month_day() + { + int d=year_day(); + int pj=0; + foreach (this->year()->month_start_day,int j) + if (d<j) return d-pj+1; + else pj=j; + return d-pj+1; + } + + int week_day() + { + return (julian_day()%7+1); + } + + string week_day_name() + { + return week_day_names[(this->week_day()+6)%7]; + } + +//-- less ----------------------------------------------------------- + + // none + +//-- more ----------------------------------------------------------- + + object year() + { + return vYear(y); + } + + object month() + { + int d=year_day(); + array a=year()->month_start_day; + for (int i=2; i<sizeof(a); i++) + if (d<a[i]) return vMonth(y,i-1); + return vMonth(y,12); + } + + object week() + { + int n; + object ye=this->year(); + n=(-({-1,-2,-3,-4,5,6,7})[this->year()->julian_day(0)%7]+d-1)/7+1; + if (n>ye->number_of_weeks()) + return vWeek(y+1,1); + else if (n<=0) + return vWeek(y-1,ye->prev()->number_of_weeks()); + return vWeek(y,n); + } +}; + + diff --git a/lib/modules/Calendar.pmod/Orthodox.pmod b/lib/modules/Calendar.pmod/Orthodox.pmod new file mode 100644 index 0000000000..b144d3d3a1 --- /dev/null +++ b/lib/modules/Calendar.pmod/Orthodox.pmod @@ -0,0 +1,23 @@ +inherit Calendar.Gregorian : christ; + +class Year +{ + inherit Calendar.Gregorian.Year; + + int leap() // tack, hubbe... :-) + { + switch(y%900) + { + case 0: + case 100: + case 300: + case 400: + case 500: + case 700: + case 800: return 0; + case 200: + case 600: return 1; + default: return !(y%4); + } + } +}; diff --git a/lib/modules/Calendar.pmod/Swedish.pmod b/lib/modules/Calendar.pmod/Swedish.pmod new file mode 100644 index 0000000000..eb1f2470d1 --- /dev/null +++ b/lib/modules/Calendar.pmod/Swedish.pmod @@ -0,0 +1,22 @@ +inherit Calendar.Gregorian : christ; + +void create() +{ + month_names= + ({"Januari","Februari","Mars","April","Maj","Juni","Juli","Augusti", + "September","Oktober","November","December"}); + + week_day_names= + ({"M�ndag","Tisdag","Onsdag","Torsdag", + "Fredag","L�rdag","S�ndag"}); +} + +class Week +{ + inherit Calendar.Gregorian.Week; + + string name() + { + return "v"+(string)this->number(); + } +} -- GitLab