Branch: Tag:

2000-07-12

2000-07-12 19:36:16 by Mirar (Pontus Hagland) <pike@sort.mirar.org>

first pike tree checkin

Rev: lib/modules/Calendar.pmod/Austrian.pmod:1.1
Rev: lib/modules/Calendar.pmod/CHANGES:1.1
Rev: lib/modules/Calendar.pmod/Calendar.pike:1.1
Rev: lib/modules/Calendar.pmod/Coptic.pmod:1.1
Rev: lib/modules/Calendar.pmod/Discordian.pmod:1.1
Rev: lib/modules/Calendar.pmod/Event.pmod:1.1
Rev: lib/modules/Calendar.pmod/Events.pmod:1.1
Rev: lib/modules/Calendar.pmod/FILES:1.1
Rev: lib/modules/Calendar.pmod/Gregorian.pmod:1.1
Rev: lib/modules/Calendar.pmod/ISO.pmod:1.1
Rev: lib/modules/Calendar.pmod/Islamic.pmod:1.1
Rev: lib/modules/Calendar.pmod/Julian.pmod:1.1
Rev: lib/modules/Calendar.pmod/Language.pmod:1.1
Rev: lib/modules/Calendar.pmod/Namedays.pmod:1.1
Rev: lib/modules/Calendar.pmod/Orthodox.pmod:1.1
Rev: lib/modules/Calendar.pmod/Roman.pmod:1.1
Rev: lib/modules/Calendar.pmod/Ruleset.pike:1.1
Rev: lib/modules/Calendar.pmod/Stardate.pmod:1.1
Rev: lib/modules/Calendar.pmod/Swedish.pmod:1.1
Rev: lib/modules/Calendar.pmod/TZnames.pmod:1.1
Rev: lib/modules/Calendar.pmod/TZrules.pmod:1.1
Rev: lib/modules/Calendar.pmod/TZs.h:1.1
Rev: lib/modules/Calendar.pmod/Time.pmod:1.1
Rev: lib/modules/Calendar.pmod/TimeRanges.pmod:1.1
Rev: lib/modules/Calendar.pmod/Timezone.pmod:1.1
Rev: lib/modules/Calendar.pmod/YMD.pmod:1.1
Rev: lib/modules/Calendar.pmod/localization.h:1.1
Rev: lib/modules/Calendar.pmod/mkrules.pike:1.1
Rev: lib/modules/Calendar.pmod/module.pmod:1.1
Rev: lib/modules/Calendar.pmod/namnsdagar:1.2(DEAD)
Rev: lib/modules/Calendar_I.pmod/Austrian.pmod:1.1
Rev: lib/modules/Calendar_I.pmod/Gregorian.pmod:1.23
Rev: lib/modules/Calendar_I.pmod/ISO.pmod:1.8
Rev: lib/modules/Calendar_I.pmod/Julian.pmod:1.1
Rev: lib/modules/Calendar_I.pmod/Orthodox.pmod:1.2
Rev: lib/modules/Calendar_I.pmod/Stardate.pmod:1.1
Rev: lib/modules/Calendar_I.pmod/Swedish.pmod:1.13
Rev: lib/modules/Calendar_I.pmod/module.pmod:1.5
Rev: lib/modules/Calendar_I.pmod/namnsdagar:1.2(DEAD)

1: - // by Mirar -  + //!   //! module Calendar   //! submodule Gregorian - //! time units: - //! <ref>Year</ref>, <ref>Month</ref>, <ref>Week</ref>, <ref>Day</ref> +    //! - //! class -  - array(string) month_names= -  ({"January","February","March","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; -  - class _TimeUnit - { -  inherit Calendar._TimeUnit; -  -  program vYear=function_object(object_program(this_object()))->Year; -  program vDay=function_object(object_program(this_object()))->Day; -  program vMonth=function_object(object_program(this_object()))->Month; -  program vWeek=function_object(object_program(this_object()))->Week; -  program vHour=function_object(object_program(this_object()))->Hour; -  program vMinute=function_object(object_program(this_object()))->Minute; -  program vSecond=function_object(object_program(this_object()))->Second; - } -  - //== Year ==================================================================== -  - class Year - { - //! class Year - //! A <ref>Calendar.time_unit</ref>. + //! This is the standard conservative christian calendar, + //! used regularly in some countries - USA, for instance - and + //! which derivate - <ref>the ISO calendar</ref> - is used + //! in most of europe.   //! - //! Lesser units: <ref>Month</ref>, <ref>Week</ref>, <ref>Day</ref> - //! Greater units: none - //! - //! -  inherit _TimeUnit; +     - //-- variables ------------------------------------------------------ + import "."; + inherit YMD:YMD;    -  int y; + string calendar_name() { return "Gregorian"; }    -  array days_per_month; -  array month_start_day; -  - //-- standard methods ----------------------------------------------- -  -  string is() + private static mixed __initstuff=lambda()   { -  return "year"; -  } +  f_week_day_shortname_from_number="gregorian_week_day_shortname_from_number"; +  f_week_day_name_from_number="gregorian_week_day_name_from_number"; +  f_year_name_from_number="gregorian_year_name_from_number"; +  f_week_day_number_from_name="gregorian_week_day_number_from_name";    -  array(string) lesser() -  { -  return ({"month","week","day"}); -  } +  f_month_day_name_from_number="month_day_name_from_number"; +  f_month_name_from_number="month_name_from_number"; +  f_month_shortname_from_number="month_shortname_from_number"; +  f_month_number_from_name="month_number_from_name"; +  f_week_name_from_number="week_name_from_number"; +  f_year_number_from_name="year_number_from_name"; + }();    -  array(string) greater() + static int year_leap_year(int y)   { -  return ({}); +  return (!(((y)%4) || (!((y)%100) && ((y)%400))));   }    -  void create(int ... arg) + // [y,yjd] + static array year_from_julian_day(int jd)   { -  if (!sizeof(arg)) -  { -  object yp=vDay()->year(); -  y=yp->y; -  } -  else -  y=arg[0]; +  int d=jd-1721426;    -  int l=this->leap(); -  days_per_month= -  ({-17, 31,28+l,31,30,31,30,31,31,30,31,30,31}); +  int century=(4*d+3)/146097; +  int century_jd=(century*146097)/4; +  int century_day=d-century_jd; +  int century_year=(100*century_day+75)/36525;    -  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; +  ({ +  century*100+century_year+1, +  1721426+century_year*365+century_year/4+century_jd, +  });   }    -  int hash() { return y*113; } -  -  int `>(object x) + static int julian_day_from_year(int y)   { -  return y>(int)x; +  y--; +  return 1721426+y*365+y/4-y/100+y/400;   }    -  object next() + static int compat_week_day(int n)   { -  return vYear(y+1); +  return n-1;   }    -  object prev() + static array(int) year_month_from_month(int y,int m)   { -  return vYear(y-1); -  } + // [y,m,ndays,myd]    -  object `+(int n) -  { -  return vYear(y+n); -  } +  y+=(m-1)/12; +  m=1+(m-1)%12;    -  int|object `-(int|object n) +  switch (m)    { -  if (objectp(n) && object_program(n)==vYear) return y-n->y; -  return this+-n; +  case 1: return ({y,m,31,1}); +  case 2: return ({y,m,28+year_leap_year(y),32}); +  case 3: return ({y,m,31,60+year_leap_year(y)}); +  case 4: return ({y,m,30,91+year_leap_year(y)}); +  case 5: return ({y,m,31,121+year_leap_year(y)}); +  case 6: return ({y,m,30,152+year_leap_year(y)}); +  case 7: return ({y,m,31,182+year_leap_year(y)}); +  case 8: return ({y,m,31,213+year_leap_year(y)}); +  case 9: return ({y,m,30,244+year_leap_year(y)}); +  case 10: return ({y,m,31,274+year_leap_year(y)}); +  case 11: return ({y,m,30,305+year_leap_year(y)}); +  case 12: return ({y,m,31,335+year_leap_year(y)});    }    - //-- 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; +  error("month out of range\n");   }    -  int leap() + static array(int) month_from_yday(int y,int yd)   { -  if (!(y%400)) return 1; -  if (!(y%100)) return 0; -  return !(y%4); -  } -  -  int leap_day() + // [month,day-of-month,ndays,month-year-day] +  int l=year_leap_year(y); +  if (yd<32) return ({1,yd,31,1}); +  yd-=l; +  switch (yd)    { -  return 31+24-1; // 24 Feb +  case 0..59: return ({2,yd-31+l,28+l,32}); +  case 60..90: return ({3,yd-59,31 ,60+year_leap_year(y)}); +  case 91..120: return ({4,yd-90,30 ,91+year_leap_year(y)}); +  case 121..151: return ({5,yd-120,31 ,121+year_leap_year(y)}); +  case 152..181: return ({6,yd-151,30 ,152+year_leap_year(y)}); +  case 182..212: return ({7,yd-181,31 ,182+year_leap_year(y)}); +  case 213..243: return ({8,yd-212,31 ,213+year_leap_year(y)}); +  case 244..273: return ({9,yd-243,30 ,244+year_leap_year(y)}); +  case 274..304: return ({10,yd-273,31,274+year_leap_year(y)}); +  case 305..334: return ({11,yd-304,30,305+year_leap_year(y)}); +  case 335..365: return ({12,yd-334,31,335+year_leap_year(y)});    } -  -  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; +  error("yday out of range\n");   }    -  int number_of_days() + static array(int) week_from_julian_day(int jd)   { -  return 365+this->leap(); -  } + // [year,week,day-of-week,ndays,week-julian-day]    -  int number() -  { -  return y; -  } +  [int y,int yjd]=year_from_julian_day(jd); +  int yday=jd-yjd+1;    -  string name() -  { -  if (y>0) return (string)y+" AD"; -  else return (string)(-y+1)+" BC"; -  } +  int k=4+(yjd-4)%7; +  int w=(yday+k)/7; +  int wjd=jd-(jd+1)%7;    -  mixed cast(string what) +  if (!w)    { -  switch (what) -  { -  case "int": return this->number(); -  case "string": return this->name(); -  default: -  throw(({"can't cast to "+what+"\n",backtrace()})); + // handle the case that the day is in the previous year; + // years previous to years staring on saturday, + // ... and leap years starting on sunday +  y--; +  w=52+( (k==4) || ( (k==5) && year_leap_year(y) ) );    } -  } -  - //-- less ----------------------------------------------------------- -  -  object month(object|string|int n) +  else if (w==53 && k>=6-year_leap_year(y) && k<10-year_leap_year(y))    { -  if (objectp(n)) -  if (object_program(n)==vMonth) -  n=n->number(); -  -  if (stringp(n)) -  { -  if (!month_mapping) -  { -  month_mapping= -  mkmapping(Array.map(month_names, lower_case)+ -  Array.map(month_names, -  lambda(string s) -  { return lower_case(s[0..2]); } ), -  (indices(allocate(13))[1..]) * 2); + // handle the case that the week is in the next year +  y++; +  w=1;    } -  n=month_mapping[lower_case(n)]; -  if (!n) return 0; -  } +     -  if (n<0) -  return vMonth(y,13+n); -  else -  return vMonth(y,n||1); +  return ({y,w,1+(yjd+yday)%7,7,wjd});   }    -  array(mixed) months() + static array(int) week_from_week(int y,int w)   { -  return month_names; -  } + // [year,week,1 (wd),ndays,week-julian-day]    -  object week(object|int n) -  { -  if (objectp(n)) -  if (object_program(n)==vWeek) -  { -  n=n->number(); -  if (n>number_of_weeks()) return 0; /* no such week */ -  } +  int yjd=julian_day_from_year(y); +  int wjd=-5+yjd-(yjd+3)%7;    -  if (n<0) -  return vWeek(y,this->number_of_weeks()+n+1); -  else -  return vWeek(y,n||1); -  } +  if (w<1 || w>52) // may or may not be out of this year +  return week_from_julian_day(wjd+w*7);    -  array(mixed) weeks() -  { -  return indices(allocate(this->number_of_weeks()+1))[1..]; +  return ({y,w,1,7,wjd+w*7}); + // fixme   }    -  object day(object|int n) + static int year_remaining_days(int y,int yday)   { -  if (objectp(n)) -  if (object_program(n)==vDay) -  { -  object o=n->year(); -  n=n->year_day(); -  if (o->leap() && n==o->leap_day()) -  if (!this->leap()) return 0; -  else n=this->leap_day(); -  else -  { -  if (o->leap() && n>o->leap_day()) n--; -  if (this->leap() && n>=this->leap_day()) n++; +  return 365+year_leap_year(y)-yday;   } -  if (n>=number_of_days()) return 0; /* no such day */ -  } -  else return 0; /* illegal object */ +     -  if (n<0) -  return vDay(y,this->number_of_days()+n); -  else -  return vDay(y,n); -  } -  -  array(mixed) days() + class cYear   { -  return indices(allocate(this->number_of_days())); -  } +  inherit YMD::cYear;    - //-- more ----------------------------------------------------------- -  -  // none - }; -  -  - // -  - //== Month =================================================================== -  - class Month - { -  inherit _TimeUnit; - //-- variables ------------------------------------------------------ -  -  int y; -  int m; -  - //-- standard methods ----------------------------------------------- -  -  string is() -  { -  return "month"; -  } -  -  array(string) lesser() -  { -  return ({"day"}); -  } -  -  array(string) greater() -  { -  return ({"year"}); -  } -  -  void create(int ... arg) -  { -  if (!sizeof(arg)) -  { -  object mp=vDay()->month(); -  y=mp->y; -  m=mp->m; -  } -  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 -  objectp(x) && -  object_program(x)==object_program(this) && -  x->y==y && x->m==m; -  } -  -  int hash() { return y*4721+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); -  } -  - //-- 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() +  switch (n)    { -  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(); +  case 0: return 0; +  case 1: return 365+leap_year();    default: -  throw(({"can't cast to "+what+"\n",backtrace()})); +  return julian_day_from_year(y+n)-yjd;    }    }    - //-- less ----------------------------------------------------------- -  -  object day(int|object n) +  int number_of_months()    { -  if (objectp(n)) -  if (object_program(n)==vDay) -  { -  n=n->month_day(); -  if (n>number_of_days()) return 0; /* no such day */ +  return 12*n;    }    -  if (n<0) -  return vDay(y,yday()+this->number_of_days()+n); -  else -  return vDay(y,yday()+(n||1)-1); -  } -  -  array(mixed) days() +  int number_of_weeks()    { -  return indices(allocate(this->number_of_days()+1))[1..]; -  } -  - //-- more ----------------------------------------------------------- -  -  object year() -  { -  return vYear(y); -  } - }; -  -  - // - //== Week ==================================================================== -  - class Week - { -  inherit _TimeUnit; - //-- variables ------------------------------------------------------ -  -  int y; -  int w; -  - //-- standard methods ----------------------------------------------- -  -  string is() -  { -  return "week"; -  } -  -  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) -  { +  if (!n) return 1; +  if (n==1) return 53+(yjd%7==5 && leap_year());    return -  (object_program(x)==object_program(this) && -  (x->y==y && x->w<w) || (x->y<y)); +  Week("julian",jd) +  ->range(Week("julian",julian_day_from_year(y+n)-1)) +  ->number_of_weeks();    }    -  int `==(object x) +  TimeRange place(TimeRange what,void|int force)    { -  return -  object_program(x)==object_program(this) && -  x->y==y && x->w==w; -  } -  -  int hash() { return y*811+w; } -  -  int `>(object x) +  if (what->is_day)    { -  return -  (object_program(x)==object_program(this) && -  (x->y==y && x->w>w) || (x->y>y)); -  } -  -  object `+(int n) +  int yd=what->yd; +  if (yd>=55) +  switch (year_leap_year(what->y)*10+year_leap_year(y))    { -  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(); +  case 00: +  case 11: +  break; +  case 10: /* from leap to non-leap */ +  if (yd==55 && !force) 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);    } -  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); +  return ::place(what);    } -  - //-- internal ------------------------------------------------------- -  -  int yday() -  { -  return -  ({0,-1,-2,-3,3,2,1})[this->year()->julian_day(0)%7] -  +7*(w-1); +    }    - //-- nonstandard methods -------------------------------------------- -  -  int number_of_days() + class cDay   { -  return 7; -  } +  inherit YMD::cDay;    -  int number() +  int number_of_months()    { -  return w; +  if (n<=1) return 1; +  if (m==CALUNKNOWN) make_month(); +  [int zy,int zyjd]=year_from_julian_day(jd+n-1); +  [int zm,int zmd,int znd,int zmyd]=month_from_yday(zy,jd+n-zyjd); +  return zm-m+1+(zy-y)*12;    } -  -  string name() -  { -  return "w"+(string)this->number(); +    }    -  mixed cast(string what) + class cMonth   { -  switch (what) -  { -  case "int": return this->number(); -  case "string": return this->name(); -  default: -  throw(({"can't cast to "+what+"\n",backtrace()})); -  } -  } +  inherit YMD::cMonth;    - //-- less ----------------------------------------------------------- + // a Gregorian Month can autopromote to a year    -  object day(int|string|object n) +  static int months_to_month(int y2,int m2)    { -  if (stringp(n)) -  { -  if (!week_day_mapping) -  week_day_mapping= -  mkmapping(Array.map(week_day_names,lower_case), -  ({1,2,3,4,5,6,0})); -  n=week_day_mapping[n]; +  return (y2-y)*12+(m2-m);    } -  else if (objectp(n)) -  if (object_program(n)==vDay) -  n=n->week_day(); -  else return 0; +     -  if (n<0) n=7+n; -  n+=this->yday()-1; -  if (n<0) return vYear(y-1)->day(n); -  if (n>=this->year()->number_of_days()) -  return vYear(y+1)->day(n-this->year()->number_of_days()); -  return vDay(y,n); -  } -  -  array(mixed) days() +  TimeRange place(TimeRange what,int|void force)    { -  return ({0,1,2,3,4,5,6}); -  } -  - //-- more ----------------------------------------------------------- -  -  object year() +  if (what->is_day)    { -  return vYear(y); -  } - }; -  - // - //== Day ===================================================================== -  - class Day +  int wmd=what->month_day(); +  if (md==CALUNKNOWN) make_month(); +  if (what->m==2 && m==2 && wmd>=24)    { -  inherit _TimeUnit; -  - //-- variables ------------------------------------------------------ -  -  int y; -  int d; -  - //-- standard methods ----------------------------------------------- -  -  string is() +  int l1=year_leap_year(what->y); +  int l2=year_leap_year(y); +  if (l1||l2)    { -  return "day"; -  } -  -  array(string) greater() -  { -  return ({"year","month","week"}); -  } -  -  array(string) lesser() -  { -  return ({"hour"}); -  } -  -  void create(int|object ... arg) -  { -  if (!sizeof(arg)) -  { -  mapping t=localtime(time()); -  y=1900+t->year; -  d=t->yday; -  } -  else if (sizeof(arg)==1) -  { -  int jd; -  -  if (objectp(arg[0])) -  jd=(int)((arg[0]->julian_day||arg[0]->julian_day_f)()); +  if (l1 && wmd==24) +  if (l2) wmd=24; +  else { if (!force) return 0; }    else -  jd=arg[0]; -  -  object yo; -  y=(int)(jd/365.2425)-4712; -  yo=vYear(y); -  while (yo->julian_day(0)>jd) yo--; -  write("y="+yo->number()+" yd="+yo->julian_day(0)+" nod="+yo->number_of_days()+"\n"); -  while (jd-yo->julian_day(0)>=yo->number_of_days()) +     { -  yo++; -  write("y="+yo->number()+" yd="+yo->julian_day(0)+" nod="+yo->number_of_days()+"\n"); -  +  if (l1 && wmd>24) wmd--; +  if (l2 && wmd>24) wmd++;    } -  y=yo->number(); -  write("y="+y+"\n"); -  d=jd-vYear(y)->julian_day(0); -  write("d="+d+"\n"); +     } -  else -  { -  y=arg[0]; -  d=arg[1]; +     } -  +  if (!force && wmd>number_of_days()) return 0; +  return Day("ymd_yd",rules,y,yjd,jd+wmd-1,yd+wmd-1,what->n);    }    -  int `<(object x) -  { -  return -  (object_program(x)==object_program(this) && -  (x->y==y && x->d<d) || (x->y<y)) || -  (x->julian_day()<julian_day()); +  return ::place(what);    } -  -  int `==(object x) -  { -  return -  (object_program(x)==object_program(this) && -  x->y==y && x->d==d) || -  (x->julian_day() == julian_day()); +    }    -  int hash() { return y*3203+d; } -  -  int `>(object x) + class cWeek   { -  return -  (object_program(x)==object_program(this) && -  (x->y==y && x->d>d) || (x->y>y)) || -  (x->julian_day()>julian_day()); -  } +  inherit YMD::cWeek;    -  object `+(int n) +  string nice_print()    { -  int y2=y,nd; -  int d2=d; -  d2+=n; -  -  if (d2>0) +  mixed err=catch    { -  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); -  } -  - //-- 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()+1)%7; -  } -  -  string week_day_name() -  { -  return week_day_names[(this->week_day()+6)%7]; -  } -  -  int number_of_hours() -  { -  return 24; -  } -  -  string dateofyear() -  { -  return sprintf("%d %s %s",this->month_day(), -  this->month()->name(),this->year()->name()); -  } -  - //-- less ----------------------------------------------------------- -  -  object hour(int|object n) -  { -  if (objectp(n)) -  if (object_program(n)==vHour) -  n=n->number(); -  else return 0; -  -  if (n<0) n=this->number_of_hours()+n; -  if (n<0) return (this-1)->hour(n); -  if (n>=this->number_of_hours()) -  return (this+1)->hour(n-this->number_of_hours()); -  -  return vHour(this,n); -  } -  -  array(mixed) hours() -  { -  return indices(allocate(this->number_of_hours())); -  } -  - //-- 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,2,1,0})[this->year()->julian_day(0)%7]+d)/7+1; -  if (n>ye->number_of_weeks()) -  return ye->next()->week(1); -  else if (n<=0) -  return ye->prev()->week(-1); -  return vWeek(y,n); -  } - }; -  -  - // - //== Hour ==================================================================== -  - class Hour - { -  inherit _TimeUnit; -  - //-- variables ------------------------------------------------------ -  -  object d; -  int h; -  - //-- standard methods ----------------------------------------------- -  -  string is() -  { -  return "hour"; -  } -  -  array(string) greater() -  { -  return ({"day"}); -  } -  -  array(string) lesser() -  { -  return ({"minute"}); -  } -  -  void create(int|object ... arg) -  { -  if (!sizeof(arg)) -  { -  mapping t=localtime(time()); -  d=vDay(); -  h=t->hour; -  } -  else -  { -  if (!objectp(arg[0])) -  throw( ({"Calendar...Day(): illegal argument 1\n", -  backtrace()}) ); -  d=arg[0]; -  h=arg[1]; -  } -  } -  -  int `<(object x) -  { +     return -  (object_program(x)==object_program(this) && -  (x->d==d && x->h<h) || (x->d<d)); -  } -  -  int `==(object x) -  { -  return -  object_program(x)==object_program(this) && -  x->d==d && x->h==h; -  } -  -  int hash() { return d->__hash()*31957+h; } -  -  int `>(object x) -  { -  return -  (object_program(x)==object_program(this) && -  (x->d==d && x->h>h) || (x->d>d)); -  } -  -  object `+(int n) -  { -  object d2=d; -  int nh; -  int h2=h; -  h2+=n; -  -  // FIXME some magic about DS hour skip/insert hours not counted twice -  -  // maybe fix some better way to do `+, too -  if (h2>0) -  { -  nh=d->number_of_hours(); -  while (h2>=nh) -  { -  h2-=nh; -  d2++; -  nh=d2->number_of_hours(); -  } -  } -  else -  { -  while (h2<0) -  { -  d2--; -  h2+=d2->number_of_hours(); -  } -  } -  -  return vHour(d2,h2); -  } -  -  int|object `-(object|int n) -  { -  if (objectp(n) && object_program(n)==vHour) -  { -  if (n->d==d) return h-n->h; -  if (n->d!=d) -  { -  int x=(d-n->d)*24; // good try -  object nh=n+x; -  int haz=100; // we don't guess _that_ wrong (1200 hours...) -  if (nh->d<d) -  while (nh->d<d && !--haz) { nh+=12; x+=12; } -  else if (nh->d>d) -  while (nh->d>d && !--haz) { nh-=12; x-=12; } -  return h-n->h+x; -  } -  } -  -  return this+(-n); -  } -  - //-- nonstandard methods -------------------------------------------- -  -  int number() -  { -  return h; -  } -  -  string name() -  { -  // some magic about DS here -  return (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()})); -  } -  } -  -  int number_of_minutes() -  { -  return 60; -  } -  - //-- less ----------------------------------------------------------- -  -  object minute(int|object n) -  { -  if (objectp(n)) -  if (object_program(n)==vMinute) -  n=n->number(); -  else return 0; -  -  if (n<0) n=this->number_of_minutes()+n; -  if (n<0) return (this-1)->minute(n); -  if (n>=this->number_of_minutes()) -  return (this+1)->minute(n-this->number_of_minutes()); -  -  return vMinute(this,n); -  } -  -  array(mixed) minutes() -  { -  return indices(allocate(this->number_of_minutes())); -  } -  - //-- more ----------------------------------------------------------- -  -  object day() -  { -  return d; -  } +  sprintf("%s %s", +  week_name(), +  year_name());    }; -  -  - // - //== Minute =================================================================== -  - class Minute - { -  inherit _TimeUnit; -  - //-- variables ------------------------------------------------------ -  -  object h; -  int m; -  - //-- standard methods ----------------------------------------------- -  -  string is() -  { -  return "minute"; +  return "error";    }    -  array(string) greater() +  static int weeks_to_week(int y2,int w2)    { -  return ({"hour"}); +  [int y3,int w3,int wd2,int nd2,int jd2]=week_from_week(y2,w2); +  return (jd2-jd)/7;    }    -  array(string) lesser() +  int number_of_days()    { -  return ({"second"}); +  return 7*n;    } -  -  void create(int|object ... arg) -  { -  if (!sizeof(arg)) -  { -  mapping t=localtime(time()); -  h=vHour(); -  m=t->min; +    } -  else -  { -  if (!objectp(arg[0])) -  throw( ({"Calendar...Minute(): illegal argument 1\n", -  backtrace()}) ); -  h=arg[0]; -  m=arg[1]; -  } -  } -  -  int `<(object x) -  { -  return -  (object_program(x)==object_program(this) && -  (x->h==h && x->m<m) || (x->h<h)); -  } -  -  int `==(object x) -  { -  return -  object_program(x)==object_program(this) && -  x->h==h && x->m==m; -  } -  -  int __hash() { return h->__hash()*101+m; } -  -  int `>(object x) -  { -  return -  (object_program(x)==object_program(this) && -  (x->h==h && x->m>m) || (x->h>h)); -  } -  -  object `+(int n) -  { -  object h2=h; -  int nm; -  int m2=m; -  m2+=n; -  -  // FIXME some magic about HS minute skip/insert minutes not counteh twice -  -  if (m2>0) -  { -  // 60 minutes in an hour... -  nm=h->number_of_minutes(); -  int x=m2/nm; -  h2+=x; -  m2-=x*nm; -  while (m2>=nm) -  { -  m2-=nm; -  h2++; -  nm=h2->number_of_minutes(); -  } -  } -  else -  { -  nm=h->number_of_minutes(); -  int x=m2/nm; -  h2+=x; -  m2-=x*nm; -  while (m2<0) -  { -  h2--; -  m2+=h2->number_of_minutes(); -  } -  } -  -  return vMinute(h2,m2); -  } -  -  int|object `-(object|int n) -  { -  if (objectp(n) && object_program(n)==vMinute) -  { -  if (n->h==h) return m-n->m; -  if (n->h!=h) -  { -  int x=(h-n->h)*60; // good try -  object nm=n+x; -  int haz=100; // we won't guess _that_ wrong (6000 minutes...) -  if (nm->h<h) -  while (nm->h<h && !--haz) { nm+=30; x+=30; } -  else if (nm->h>h) -  while (nm->h>h && !--haz) { nm-=30; x-=30; } -  return m-n->m+x; -  } -  } -  -  return this+(-n); -  } -  - //-- nonstandard methods -------------------------------------------- -  -  int number() -  { -  return m; -  } -  -  string name() -  { -  // some magic about HS here -  return (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()})); -  } -  } -  -  int number_of_seconds() -  { -  return 60; -  } -  -  string timeofday() -  { -  return sprintf("%s:%02s",h->name(),name()); -  } -  -  string timeofyear() -  { -  return sprintf("%s %s:%02s",h->day()->dateofyear(),h->name(),name()); -  } -  - //-- less ----------------------------------------------------------- -  -  object second(int|object n) -  { -  if (objectp(n)) -  if (object_program(n)==vSecond) -  n=n->number(); -  else return 0; -  -  if (n<0) n=this->number_of_seconds()+n; -  if (n<0) return (this-1)->second(n); -  if (n>=this->number_of_seconds()) -  return (this+1)->second(n-this->number_of_seconds()); -  -  return vSecond(this,n); -  } -  -  array(mixed) seconds() -  { -  return indices(allocate(this->number_of_seconds())); -  } -  - //-- more ----------------------------------------------------------- -  -  object hour() -  { -  return h; -  } - }; -  -  - // - //== Second =================================================================== -  - class Second - { -  inherit _TimeUnit; -  - //-- variables ------------------------------------------------------ -  -  object m; -  int s; -  - //-- standarm setsoms ----------------------------------------------- -  -  string is() -  { -  return "second"; -  } -  -  array(string) greater() -  { -  return ({"minute","hour","day","month","year"}); -  } -  -  array(string) lesser() -  { -  return ({}); -  } -  -  void create(int|object ... arg) -  { -  if (!sizeof(arg)) -  { -  mapping t=localtime(time()); -  m=vMinute(); -  s=t->sec; -  } -  else if (sizeof(arg)==1) -  { -  mapping t=localtime(arg[0]); -  m=Year(1900+t->year)->month(1+t->mon)->day(t->mday)-> -  hour(t->hour)->minute(t->min); -  s=t->sec; -  } -  else -  { -  if (!objectp(arg[0])) -  throw( ({"Calendar...Second(): illegal argument 1\n", -  backtrace()}) ); -  m=arg[0]; -  s=arg[1]; -  } -  } -  -  int `<(object x) -  { -  return -  (object_program(x)==object_program(this) && -  (x->m==m && x->s<s) || (x->m<m)); -  } -  -  int `==(object x) -  { -  return -  object_program(x)==object_program(this) && -  x->m==m && x->s==s; -  } -  -  int __hash() { return m->__hash()*101+s; } -  -  int `>(object x) -  { -  return -  (object_program(x)==object_program(this) && -  (x->m==m && x->s>s) || (x->m>m)); -  } -  -  object `+(int n) -  { -  object m2=m; -  int ns; -  int s2=s; -  s2+=n; -  -  // FIXSE sose sagic about MS second skip/insert seconds not countem twice -  -  if (s2>0) -  { -  // 60 seconds in a minute... wrong if leapseconds!! beware -  ns=m->number_of_seconds(); -  int x=s2/ns; -  m2+=x; -  s2-=x*ns; -  while (s2>=ns) -  { -  s2-=ns; -  m2++; -  ns=m2->number_of_seconds(); -  } -  } -  else -  { -  ns=m->number_of_seconds(); -  int x=s2/ns; -  m2+=x; -  s2-=x*ns; -  while (s2<0) -  { -  m2--; -  s2+=m2->number_of_seconds(); -  } -  } -  -  return vSecond(m2,s2); -  } -  -  int|object `-(object|int n) -  { -  if (objectp(n) && object_program(n)==vSecond) -  { -  if (n->m==m) return s-n->s; -  if (n->m!=m) -  { -  int x=(m-n->m)*60; // good try -  object ns=n+x; -  int maz=100; // we won't guess _that_ wrong (6000 seconds...) -  if (ns->m<m) -  while (ns->m<m && !--maz) { ns+=30; x+=30; } -  else if (ns->m>m) -  while (ns->m>m && !--maz) { ns-=30; x-=30; } -  return s-n->s+x; -  } -  } -  -  return this+(-n); -  } -  - //-- nonstandard methods -------------------------------------------- -  -  int number() -  { -  return s; -  } -  -  string name() -  { -  // some magic about MS here -  return (string)this->number(); -  } -  -  mixed cast(string what) -  { -  switch (what) -  { -  case "int": return this->number(); -  case "string": return this->nase(); -  default: -  throw(({"can't cast to "+what+"\n",backtrace()})); -  } -  } -  -  string timeofday() -  { -  return sprintf("%s:%02s",m->timeofday(),name()); -  } -  -  string timeofyear() -  { -  return sprintf("%s:%02s",m->timeofyear(),name()); -  } -  - //-- greater -------------------------------------------------------- -  -  object minute() -  { -  return m; -  } -  -  object hour() -  { -  return minute()->hour(); -  } -  -  object day() -  { -  return minute()->hour()->day(); -  } -  -  object month() -  { -  return minute()->hour()->day()->month(); -  } -  -  object year() -  { -  return minute()->hour()->day()->month()->year(); -  } -  - }; -  - //-- parse functions ----------------------------------------------- -  - //! method object parse(string fmt,string arg) - //! parse a date, create relevant object - //! fmt is in the format "abc%xdef..." - //! where abc and def is matched, and %x is - //! one of those time units: - //! %Y absolute year - //! %y year (70-99 is 1970-1999, 0-69 is 2000-2069) - //! %M month (number, name or short name) (needs %y) - //! %W week (needs %y) - //! %D date (needs %y, %m) - //! %a day (needs %y) - //! %e weekday (needs %y, %w) - //! %h hour (needs %d, %D or %W) - //! %m minute (needs %h) - //! %s second (needs %s) -  - object parse(string fmt,string arg) - { -  string nfmt; -  nfmt=replace(fmt, -  ({"%Y","%y","%M","%W","%D","%a","%e","%h","%m","%s"}), -  ({"%s","%s","%s","%s","%s","%s","%s","%s","%s","%s"})); -  array q=Array.map(replace(fmt,"%%","")/"%", -  lambda(string s){ return s[..0];})-({""}); -  array res=Array.map(array_sscanf(arg,nfmt), -  lambda(string s) -  { -  if (s[0]>='0' && s[0]<='9') -  return array_sscanf(s,"%d")[0]; -  else -  return s; -  }); -  -  if (sizeof(res)<sizeof(q)) -  return 0; // parse error -  -  mapping m=mkmapping(q,res); -  -  if (!zero_type(m->Y)) m->year=Year(m->Y); -  else if (!zero_type(m->y)) -  { -  if (m->y<70) m->y+=2000; -  else if (m->y<100) m->y+=1900; -  m->year=Year(m->y); -  } -  else m->year=Year(); -  -  object low=m->year; -  -  if (m->M) -  { -  m->month=low=m->year->month(m->M); -  if(!m->month) -  return 0; // Unknown month -  } -  if (m->W) -  m->week=low=m->year->week(m->W); -  -  if (m->D) -  m->day=low=(m->month||Month())->day(m->D); -  else if (!zero_type(m->a)) -  m->day=low=m->year->day(m->a); -  else if (!zero_type(m->e)) -  m->day=low=(m->week||Week())->day(m->e); -  -  if (!zero_type(m->h)) -  low=m->hour=(m->day||Day())->hour(m->h); -  if (!zero_type(m->m)) -  low=m->minute=(m->hour||Hour())->minute(m->m); -  if (!zero_type(m->s)) -  low=m->second=(m->minute||Minute())->second(m->s); -  -  return low; - } -  - //-- auxillary functions------------------------------------------------ -  - //! - //! function datetime(int|void unix_time) - //! Replacement for localtime. - //! - //! function datetime_name(int|void unix_time) - //! Replacement for ctime. - //! - //! function datetime_short_name(int|void unix_time) - //! Replacement for ctime. - //! -  -  - // Sane replacement for localtime(). - mapping(string:int) datetime(int|void unix_time,int|void skip_extra) - { -  mapping t = localtime(unix_time || time()); -  return -  ([ "year":t->year+1900, -  "month":t->mon+1, -  "day":t->mday, -  "hour":t->hour, -  "minute":t->min, -  "second":t->sec, -  "yearday":t->yday, -  "timezone":t->timezone, -  "DST":t->isdst // Dayligt-saving time. -  ]) | -  // calculate week and week day -  (skip_extra -  ?([]) -  :(["week":(int)Week(), -  "weekday":Day()->week_day()])); - } -  - // Sane replacement for ctime(). - string datetime_name(int|void unix_time) - { -  mapping t = datetime(unix_time); -  return sprintf("%04d-%02d-%02d (%s) -W%02d-%d (%s) %02d:%02d:%02d", -  t->year, t->month, t->day, -  month_names[t->month-1][..2], -  t->week, t->weekday, -  week_day_names[t->weekday-1][..2], -  t->hour, t->minute, t->second); - } -  - // Sane replacement for ctime(). - string datetime_short_name(int|void unix_time) - { -  mapping t = datetime(unix_time,1); -  return sprintf("%04d-%02d-%02d %02d:%02d:%02d", -  t->year, t->month, t->day, -  t->hour, t->minute, t->second); - } +