ac8c922003-03-12Martin Nilsson #pike __REAL_VERSION__ //! The Discordian calendar, as described on page 34 //! in the fourth edition of Principia Discordia.
dc21d42001-05-05Mirar (Pontus Hagland) //!
ac8c922003-03-12Martin Nilsson //! Chaotic enough, it's quite simpler then the @[Gregorian] calendar; //! weeks are 5 days, and evens up on a year. Months are 73 days.
78fd532000-07-12Mirar (Pontus Hagland) //!
ac8c922003-03-12Martin Nilsson //! The leap day is inserted at the 60th day of the first month //! (Chaos), giving the first month 74 days. The description of //! the calendar is a "perpetual date converter from the gregorian //! to the POEE calendar", so the leap years are the same as //! the gregorians.
78fd532000-07-12Mirar (Pontus Hagland) //!
ac8c922003-03-12Martin Nilsson //! The Principia calls months "seasons", but for simplicity I //! call them months in this calendar.
78fd532000-07-12Mirar (Pontus Hagland) //!
ac8c922003-03-12Martin Nilsson //! If anyone know more about how to treat the leap day - now it is //! inserted in the month and week where it lands, rather then being //! separated from month and weeks, I'm interested to know.
78fd532000-07-12Mirar (Pontus Hagland) //! //! - Mirar, Pope of POEE. // the discordian calendar follows the gregorian years, very practical ;)
9f0b6c2008-02-07Martin Stjernholm inherit Calendar.Gregorian:Gregorian;
78fd532000-07-12Mirar (Pontus Hagland) 
2099482001-01-11Mirar (Pontus Hagland) #include "constants.h"
78fd532000-07-12Mirar (Pontus Hagland) string calendar_name() { return "Discordian"; }
9eaf1d2008-06-28Martin Nilsson private protected mixed __initstuff=lambda()
78fd532000-07-12Mirar (Pontus Hagland) { // language setup f_week_day_shortname_from_number= "discordian_week_day_shortname_from_number"; f_week_day_name_from_number="discordian_week_day_name_from_number"; f_year_name_from_number="discordian_year_name_from_number"; f_month_name_from_number="discordian_month_name_from_number"; f_month_shortname_from_number="discordian_month_shortname_from_number"; f_month_number_from_name="discordian_month_number_from_name"; f_week_name_from_number="discordian_week_name_from_number"; f_week_day_number_from_name="discordian_week_day_number_from_name"; }();
9eaf1d2008-06-28Martin Nilsson protected int compat_week_day(int n)
78fd532000-07-12Mirar (Pontus Hagland) { return n; // N/A } // almost as gregorian
9eaf1d2008-06-28Martin Nilsson protected array year_from_julian_day(int jd)
78fd532000-07-12Mirar (Pontus Hagland) { array a=::year_from_julian_day(jd); return ({a[0]+1166,a[1]}); }
9eaf1d2008-06-28Martin Nilsson protected int julian_day_from_year(int y)
78fd532000-07-12Mirar (Pontus Hagland) { return ::julian_day_from_year(y-1166); }
9eaf1d2008-06-28Martin Nilsson protected int year_leap_year(int y)
78fd532000-07-12Mirar (Pontus Hagland) { return ::year_leap_year(y-1166); }
9eaf1d2008-06-28Martin Nilsson protected array(int) year_month_from_month(int y,int m)
78fd532000-07-12Mirar (Pontus Hagland) { // [y,m,ndays,myd] y+=(m-1)/5; m=1+(m-1)%5; switch (m) { case 1: return ({y,m,73+year_leap_year(y),1}); case 2..5: return ({y,m,73,1+73*(m-1)+year_leap_year(y)}); } error("month out of range\n"); }
9eaf1d2008-06-28Martin Nilsson protected array(int) month_from_yday(int y,int yd)
78fd532000-07-12Mirar (Pontus Hagland) { // [month,day-of-month,ndays,month-year-day] int l=year_leap_year(y); if (yd<=73+l) return ({1,yd,73+l,1}); yd-=l; int m=(yd+72)/73; return ({m,yd-(m-1)*73,73,(m-1)*73+l+1}); }
9eaf1d2008-06-28Martin Nilsson protected array(int) week_from_julian_day(int jd)
78fd532000-07-12Mirar (Pontus Hagland) { // [year,week,day-of-week,ndays,week-julian-day] [int y,int yjd]=year_from_julian_day(jd); int yday=jd-yjd+1; int l=year_leap_year(y); if (l) if (yday==60) return ({y,12,6,6,yjd+55}); else if (yday>55 && yday<62) return ({y,12,(yday==61)?5:yday-55,6,yjd+55}); else if (yday>60) yday--; else l=0; int w=(yday+4)/5; return ({y,w,(yday-1)%5+1,5,yjd+(w-1)*5+l}); }
9eaf1d2008-06-28Martin Nilsson protected array(int) week_from_week(int y,int w)
78fd532000-07-12Mirar (Pontus Hagland) { // [year,week,1 (wd),ndays,week-julian-day] y+=(w-1)/73; w=1+(w-1)%73; int yjd=julian_day_from_year(y); int l=year_leap_year(y); if (!l||w<12) return ({y,w,1,5,yjd+(w-1)*5}); return week_from_julian_day(yjd+(w-1)*5+(l&&w>12)); }
9eaf1d2008-06-28Martin Nilsson protected int year_remaining_days(int y,int yday)
78fd532000-07-12Mirar (Pontus Hagland) { return 365+year_leap_year(y)-yday; } class cYear { inherit Gregorian::cYear; int number_of_weeks() { return 73*n; }
a34df32005-01-06Mirar (Pontus Hagland)  int number_of_months() { return 5*n; }
78fd532000-07-12Mirar (Pontus Hagland)  TimeRange place(TimeRange what) { if (what->is_day) { int yd=what->yd; if (yd>=59) switch (year_leap_year(what->y)*10+year_leap_year(y)) { case 00: case 11: break; case 10: /* from leap to non-leap */ if (yd==59) return 0; // not this year yd--; break; case 01: /* from non-leap to leap */ yd++; break; } return Day("ymd_yd",rules,y,yjd,yjd+yd-1,yd,what->n); } return ::place(what); } } class cDay { inherit Gregorian::cDay; string nice_print() { mixed err=catch { if (m==CALUNKNOWN) make_month(); if (wd==CALUNKNOWN) make_week(); return sprintf("%s %d of %s %s", week_day_shortname(), md,month_shortname(), year_name()); }; return "error"; } } class cMonth { inherit Gregorian::cMonth;
d7db5d2013-05-31Martin Nilsson  protected void create(mixed ...args)
78fd532000-07-12Mirar (Pontus Hagland)  { ::create(@args); if (yjd+yd-1!=jd) error("yjd=%O yday=%O jd=%O != %O\n", yjd,yd,jd,jd+yd-1); } TimeRange place(TimeRange what,int|void force) { if (what->is_day) { int wmd=what->month_day(); if (md==CALUNKNOWN) make_month(); if (what->m==1 && m==1 && wmd>=60) { int l1=year_leap_year(what->y); int l2=year_leap_year(y); if (l1||l2) { if (l1 && wmd==60) if (l2) wmd=60; else { if (!force) return 0; } else { if (l1 && wmd>60) wmd--; if (l2 && wmd>60) wmd++; } } } if (!force && wmd>number_of_days()) return 0; return Day("ymd_yd",rules,y,yjd,jd+wmd-1,yd+wmd-1,what->n); } return ::place(what); } } class cWeek { inherit Gregorian::cWeek;
9eaf1d2008-06-28Martin Nilsson  protected int weeks_to_week(int y2,int w2)
78fd532000-07-12Mirar (Pontus Hagland)  { return (y2-y)*73+w2-w; } int number_of_days() { [int y2,int w2,int wd2,int nd2,int jd2]=week_from_week(y,w+n); return jd2-jd; } }