pike.git / lib / modules / Calendar.pmod / Event.pmod

version» Context lines:

pike.git/lib/modules/Calendar.pmod/Event.pmod:75:    //! Joins several events into one @[SuperEvent].    SuperEvent `|(Event ... with)    {    with-=({0});    with|=({this});    if (sizeof(with)==1) return with[0];    return SuperEvent(with);    }    SuperEvent ``|(Event with) { return `|(with); }    -  string _sprintf(int t) +  protected string _sprintf(int t)    {    return (t!='O')?0:sprintf("Event(%s:%O)",id,name);    }    -  array(Event) cast(string to) +  protected array(Event) cast(string to)    { -  if (to[..4]=="array") +  if (to=="array")    return ({this}); -  else -  error("Can't cast to %O\n",to); +  return UNDEFINED;    }       //! Returns a description of the event.    string describe()    {    return "Unknown event";    }   }      //! A non-event.
pike.git/lib/modules/Calendar.pmod/Event.pmod:139:    constant is_day_event=1;       //! Returned from @[scan_jd] if the even searched for did not    //! exist.    constant NODAY=-1;       int nd=1;       //! @decl int scan_jd(Calendar.Calendar realm, int jd,@    //! int(-1..-1)|int(1..1) direction) -  //! These methods has to be defined, and is what -  //! really does some work. It should return the next or previos -  //! julian day (>@i{jd@}) when the event occurs, -  //! or the constant @[NODAY] if it doesn't. +  //! This method has to be defined, and is what +  //! really does some work.    //!    //! @param direction    //! @int    //! @value 1    //! Forward (next),    //! @value -1    //! Backward (previous).    //! @endint -  +  //! +  //! @returns +  //! It should return the next or previous +  //! julian day (>@i{jd@}) when the event occurs, +  //! or the constant @[NODAY] if it doesn't.       int scan_jd(Calendar.Calendar realm,int jd,int(1..1)|int(-1..-1) direction);       //! Uses the virtual method @[scan_jd].    //! @seealso    //! @[Event.next]    Calendar.TimeRanges.TimeRange next(void|Calendar.TimeRanges.TimeRange from,    void|int(0..1) including)    {    if (!from) from=std_day();
pike.git/lib/modules/Calendar.pmod/Event.pmod:210:    name=_name;    jd=_jd;    }       int scan_jd(Calendar.Calendar realm,int sjd,int(1..1)|int(-1..-1) direction)    {    if (direction==1) return sjd<=jd?jd:NODAY;    else return sjd>=jd?jd:NODAY;    }    -  string _sprintf(int t) +  protected string _sprintf(int t)    {    return t=='O'?sprintf("Nameday(%s:%O)",id,name):0;    }   }      //! This contains a ruleset about namedays.   class Namedays   {    inherit Event;   
pike.git/lib/modules/Calendar.pmod/Event.pmod:372:    {    return _find(from,including,1);    }       Calendar.TimeRanges.TimeRange previous(Calendar.TimeRanges.TimeRange from,    void|int(0..1) including)    {    return _find(from,including,-1);    }    -  string _sprintf(int t) +  protected string _sprintf(int t)    {    return t=='O'?sprintf("Namedays(%s:%O)",id,name):0;    }       string describe()    {    return "Namedays";    }       SuperEvent|SuperNamedays|Namedays
pike.git/lib/modules/Calendar.pmod/Event.pmod:401:    array a=({e})|({this});    if (!sizeof(a)) res=this;    else if (e->is_namedays && e->id==id) res=SuperNamedays(a,id);    else res=SuperEvent(a);    }    if (sizeof(extra)) return predef::`|(res,@extra);    return res;    }   }    - //! Container for merged @[Namedays] objects. - class SuperNamedays + //! Container for merged @[Namedays] objects. Presumes non-overlapping + //! namedays + class SuperNamedays (array(Nameday) namedayss, string id)   {    inherit Event;    constant is_namedays_wrapper=1;    - // presumed non-overlapping namedays -  array(Nameday) namedayss; -  string id; -  -  void create(array(Nameday) _namedays,string _id) +  protected string _sprintf(int t)    { -  name=id=_id; -  namedayss=_namedays; +  return t=='O' && sprintf("SuperNamedays(%s [%d])",id,sizeof(namedayss));    }    -  string _sprintf(int t) -  { -  return t=='O'?sprintf("SuperNamedays(%s [%d])",id,sizeof(namedayss)):0; -  } -  +     string describe()    {    return "Namedays";    }       array(Calendar.TimeRanges.TimeRange) scan(Calendar.TimeRanges.TimeRange in)    {    return indices(namedays(in));    }   
pike.git/lib/modules/Calendar.pmod/Event.pmod:563:    inherit Day_Event;       //! This constant may be used to identify @[Gregorian_Fixed] objects.    constant is_fixed=1;       int md,mn;    int yd;       //! @decl void create(string id, string name, int(1..31) month_day,@    //! int(1..12) month, int extra) -  void create(string _id,string _name, -  int(1..31) _md,int(1..12) _mn,int ... _n) +  protected void create(string id, string name, +  int(1..31) month_day, int(1..12) month, +  int ... extra)    { -  id=_id; -  name=_name; -  md=_md; -  mn=_mn; +  this::id=id; +  this::name=name; +  md=month_day; +  mn=month;       yd=M_YD[mn]+md; -  if (sizeof(_n)) nd=_n[0]; +  if (sizeof(extra)) nd=extra[0];    }       int scan_jd(Calendar.Calendar realm,int jd,int(-1..1) direction)    {    [int y,int yjd,int leap]=gregorian_yjd(jd);    int njd;       for (;;)    {    if (leap && yd>59)
pike.git/lib/modules/Calendar.pmod/Event.pmod:661:   {    inherit Day_Event;       int md,mn;       int yd;       //! @decl void create(int(1..31) month_day, int(1..12) month)    //! The event is created by a given month day and a month number    //! (1=January, 12=December). -  void create(int _md,int _mn) +  protected void create(int _md,int _mn)    {    md=_md;    mn=_mn;    name=M_NAME[mn]+" "+md;       yd=M_YD[mn]+md;    }       int scan_jd(Calendar.Calendar realm,int jd,int(-1..1) direction)    {
pike.git/lib/modules/Calendar.pmod/Event.pmod:717:       //! @decl void create(int month_day, int month, int weekday)    //! The event is created by a given month day,    //! a month number (1=January, 12=December), and a    //! weekday number (1=Monday, 7=Sunday).    //!    //! @note    //! The week day numbers used are the same as the day of week in    //! the @[ISO] calendar - the @[Gregorian] calendar has 1=Sunday,    //! 7=Saturday. -  void create(int _md,int _mn,int wd) +  protected void create(int _md,int _mn,int wd)    {    md=_md;    mn=_mn;    name=M_NAME[mn]+" "+md+" "+WD_NAME[wd];       yd=M_YD[mn]+md;    jd_wd=(wd+6)%7;    }       int scan_jd(Calendar.Calendar realm,int jd,int(-1..1) direction)
pike.git/lib/modules/Calendar.pmod/Event.pmod:773:    int jd_wd;       //! @decl void create(int month_day,int weekday)    //! The event is created by a given month day,    //! and a weekday number (1=Monday, 7=Sunday).    //!    //! @note    //! The week day numbers used are the same as the day of week in    //! the @[ISO] calendar - the @[Gregorian] calendar has 1=Sunday,    //! 7=Saturday. -  void create(int _md,int wd) +  protected void create(int _md,int wd)    {    md=_md;    name=md+","+WD_NAME[wd];    jd_wd=(wd+6)%7;    }       int scan_jd(Calendar.Calendar realm,int jd,int(-1..1) direction)    {    if (md>31 || md<1) return 0;    [int y,int yjd,int leap]=gregorian_yjd(jd);
pike.git/lib/modules/Calendar.pmod/Event.pmod:834:       int jd_wd;       //! @decl void create(int weekday, void|string id)    //! The event is created by a given weekday number (1=Monday, 7=Sunday).    //!    //! @note    //! The week day numbers used are the same as the day of week in    //! the @[ISO] calendar - the @[Gregorian] calendar has 1=Sunday,    //! 7=Saturday. -  void create(int wd,void|string _id) +  protected void create(int wd,void|string _id)    {    jd_wd=(wd+6)%7; // convert to julian day numbering    name=WD_NAME[wd];    if (!id) id=name; else id=_id;    }       int scan_jd(Calendar.Calendar realm,int jd,int(-1..1) direction)    {    if (direction==-1) return jd-(jd-jd_wd)%7;    return jd+(7-(jd-jd_wd))%7;    }   }    -  + //! This class represents a solar event as observed from Earth. + //! + //! The @[event_type] is one of + //! @int + //! @value 0 + //! Northern hemisphere spring equinox. + //! @value 1 + //! Northern hemisphere summer solstice. + //! @value 2 + //! Northern hemisphere autumn equinox. + //! @value 3 + //! Northern hemisphere winter solstice. + //! @endint + class Solar(int|void event_type) + { +  inherit Day_Event;    -  +  //! @array +  //! @elem array(float) 0.. +  //! @array +  //! @elem float 0 +  //! Amplitude in days. +  //! @elem float 1 +  //! Cosine phase in radians in year 2000. +  //! @elem float 2 +  //! Period in radians/year. +  //! @endarray +  //! @endarray +  protected constant periodic_table = ({ +  ({ 0.00485, 5.67162, 33.757041, }), +  ({ 0.00203, 5.88577, 575.338485, }), +  ({ 0.00199, 5.97042, 0.352312, }), +  ({ 0.00182, 0.48607, 7771.377155, }), +  ({ 0.00156, 1.27653, 786.041946, }), +  ({ 0.00136, 2.99359, 393.020973, }), +  ({ 0.00077, 3.8841, 1150.67697, }), +  ({ 0.00074, 5.1787, 52.96910, }), +  ({ 0.00070, 4.2513, 157.73436, }), +  ({ 0.00058, 2.0911, 588.49268, }), +  ({ 0.00052, 5.1866, 2.62983, }), +  ({ 0.00050, 0.3669, 39.81490, }), +  ({ 0.00045, 4.3204, 522.36940, }), +  ({ 0.00044, 5.6749, 550.75533, }), +  ({ 0.00029, 1.0634, 77.55226, }), +  ({ 0.00018, 2.7074, 1179.06290, }), // NB: Some have amplitude 28 here. +  ({ 0.00017, 5.0403, 79.62981, }), +  ({ 0.00016, 3.4565, 1097.70789, }), +  ({ 0.00014, 3.4865, 548.67778, }), +  ({ 0.00012, 1.6649, 254.43145, }), +  ({ 0.00012, 5.0110, 557.31428, }), +  ({ 0.00012, 5.5992, 606.97767, }), +  ({ 0.00009, 3.9746, 21.32991, }), +  ({ 0.00008, 0.2697, 294.24635, }), +  }); +  +  //! Calculate the next event. +  //! +  //! Based on Meeus Astronomical Algorithms Chapter 27. +  array(int|float) solar_event(int y) +  { +  int jd; +  float offset; +  +  // First calculate an initial guess for the Julian day. +  if (y < 1000) { +  float yy = y/1000.0; +  float y2 = yy*yy; +  float y3 = y2*yy; +  float y4 = y3*yy; +  +  // 4th degree polynomial around year 2BC. +  switch (event_type) { +  case 0: +  offset = 365242 * yy; +  jd = 1721139 + (int)floor(offset); +  offset -= floor(offset); +  offset += 0.29189 + 0.13740 * yy + 0.06134 * y2 - +  0.00111 * y3 - 0.00071 * y4; +  break; +  case 1: +  offset = 365241 * yy; +  jd = 1721233 + (int)floor(offset); +  offset -= floor(offset); +  offset += 0.25401 + 0.72562 * yy + 0.05323 * y2 - +  0.00907 * y3 - 0.00025 * y4; +  break; +  case 2: +  offset = 365242 * yy; +  jd = 1721325 + (int)floor(offset); +  offset -= floor(offset); +  offset += 0.70455 + 0.49558 * yy + 0.11677 * y2 - +  0.00297 * y3 - 0.00074 * y4; +  break; +  case 3: +  offset = 365242 * yy; +  jd = 1721414 + (int)floor(offset); +  offset -= floor(offset); +  offset += 0.39987 + 0.88257 * yy + 0.00769 * y2 - +  0.00933 * y3 - 0.00006 * y4; +  break; +  } +  } else { +  float yy = (y - 2000)/1000.0; +  float y2 = yy*yy; +  float y3 = y2*yy; +  float y4 = y3*yy; +  +  // 4th degree polynomial around year 2000. +  switch (event_type) { +  case 0: +  offset = 365242 * yy; +  jd = 2451623 + (int)floor(offset); +  offset -= floor(offset); +  offset += 0.80984 + 0.37404 * yy + 0.05169 * y2 - +  0.00411 * y3 - 0.00057 * y4; +  break; +  case 1: +  offset = 365241 * yy; +  jd = 2451716 + (int)floor(offset); +  offset -= floor(offset); +  offset += 0.56767 + 0.62603 * yy + 0.00325 * y2 - +  0.00888 * y3 - 0.00030 * y4; +  break; +  case 2: +  offset = 365242 * yy; +  jd = 2451810 + (int)floor(offset); +  offset -= floor(offset); +  offset += 0.21715 + 0.01767 * yy + 0.11575 * y2 - +  0.00337 * y3 - 0.00078 * y4; +  break; +  case 3: +  offset = 365242 * yy; +  jd = 2451900 + (int)floor(offset); +  offset -= floor(offset); +  offset += 0.05952 + 0.74049 * yy + 0.06223 * y2 - +  0.00823 * y3 - 0.00032 * y4; +  break; +  } +  } +  +  float delta_y = ((jd - 2451545) + offset) / 36525.0; +  +  // Omega is in radians. +  float omega = 628.30759 * delta_y - 0.0431096; +  float l = 1.0 + 0.0334 * cos(omega) + 0.0007 * cos(2.0 * omega); +  +  // Adjusted to radians. +  float S = 0.0; +  foreach(periodic_table; int i; array(float) fun) { +  S += fun[0] * cos(fun[1] + fun[2] * delta_y); +  } +  +  offset += S / l; +  +  // Adjust for Meeus starting julian days at 12:00 UTC. +  offset += 0.5; +  +  jd += (int)floor(offset); +  offset -= (int)floor(offset); +  return ({ jd, offset }); +  } +  +  //! @note +  //! Returns unixtime in UTC to avoid losing the decimals! +  int scan_jd(Calendar.Calendar realm, int jd, int(1..1)|int(-1..-1) direction) +  { +  [int y, int yjd, int leap] = gregorian_yjd(jd); +  +  [int new_jd, float offset] = solar_event(y); +  +  if ((direction > 0) && (new_jd < jd)) { +  [new_jd, offset] = solar_event(y + 1); +  } else if ((direction < 0) && (new_jd >= jd)) { +  [new_jd, offset] = solar_event(y - 1); +  } +  +  // Convert into an UTC timestamp. +  int utc = (new_jd - 2440588)*86400 + (int)(offset * 86400.0); +  return utc - (int)round(.ISO.deltat(utc)); +  } +  +  Calendar.TimeRanges.TimeRange next(void|Calendar.TimeRanges.TimeRange from, +  void|int(0..1) including) +  { +  if (!from) from=std_day(); +  int jd; +  if (including) jd=(int)(from->julian_day()); +  else jd=(int)(from->end()->julian_day()); +  int utc = scan_jd(from->calendar(),jd-nd+1,1); +  return (from->calendar()->Day)("unix_r",utc,from->ruleset())*nd; +  } +  +  //! Uses the virtual method @[scan_jd]. +  //! @seealso +  //! @[Event.previous] +  Calendar.TimeRanges.TimeRange previous(void|Calendar.TimeRanges.TimeRange from, +  void|int(0..1) including) +  { +  if (!from) from=std_day(); +  int jd; +  if (including) jd=(int)(from->end()->julian_day()); +  else jd=(floatp(from->julian_day()) +  ?(int)floor(from->julian_day()) +  :(from->julian_day()-1)); +  int utc = scan_jd(from->calendar(),jd+nd-1,-1); +  return (from->calendar()->Day)("unix_r",utc,from->ruleset())*nd; +  } + } +    //! This class represents an easter.   class Easter   {    inherit Day_Event;       int shift=1582;       //! @decl void create(void|int shift)    //! @[shift] is the year to shift from old to new style easter    //! calculation. Default is 1582. -  void create(void|int _shift) +  protected void create(void|int _shift)    {    if (_shift) shift=_shift;    }       protected int new_style(int y)    {    int century=y/100;    int solar=century-century/4;    int lunar=(century-15-(century-17)/25)/3;    int epact=(13+11*(y%19)-solar+lunar)%30;
pike.git/lib/modules/Calendar.pmod/Event.pmod:957:   //! This class represents an easter relative event.   class Easter_Relative   {    inherit Easter;       constant is_easter_relative=1;       int offset;       //! @decl void create(string id, string name, int offset) -  void create(string _id,string _name,void|int _offset) +  protected void create(string _id,string _name,void|int _offset)    {    id=_id;    name=_name;    offset=_offset;    }       int scan_jd(Calendar.Calendar realm,int jd,int(-1..1) direction)    {    return offset+::scan_jd(realm,jd-direction*offset,direction);    }
pike.git/lib/modules/Calendar.pmod/Event.pmod:987:   //! This class represents an orthodox easter relative event.   class Orthodox_Easter_Relative   {    inherit Easter_Relative;       constant is_orthodox_easter_relative=1;       int offset;       //! @decl void create(string id, string name, int offset) -  void create(string _id,string _name,void|int _offset) +  protected void create(string _id,string _name,void|int _offset)    {    ::create(_id,_name,_offset);    shift=9999999;    }   }      //! This class represents a monthday weekday relative event or   //! n:th special weekday event, e.g.   //! "fourth sunday before 24 dec" => md=24,mn=12,wd=7,n=-4   class Monthday_Weekday_Relative
pike.git/lib/modules/Calendar.pmod/Event.pmod:1010:       constant is_fixed=0;    constant is_monthday_weekday_relative=1;       int offset;    int wd;       int n,inclusive;       //! -  void create(string id,string name,int(1..31) md,int(1..12) mn, +  protected void create(string id,string name,int(1..31) md,int(1..12) mn,    int(1..7) _wd,int _n,void|int(0..1) _inclusive)    {    ::create(id,name,md,mn);       n=_n;    inclusive=_inclusive;      // offset is the offset to the last possible day    if (n<0)    offset=(n+1)*7-!inclusive;
pike.git/lib/modules/Calendar.pmod/Event.pmod:1194:    }    Event ``|(Event|SuperEvent with) { return `|(with); }       Event `-(Event|SuperEvent ...subtract)    {    array(Event) res=events-subtract;    if (res==events) return this;    return SuperEvent(res,flags&res,"?");    }    -  array(Event) cast(string to) +  protected array(Event) cast(string to)    { -  if (to[..4]=="array") +  if (to=="array")    return events; -  else -  error("Can't cast to %O\n",to); +  return UNDEFINED;    }    -  string _sprintf(int t) +  protected string _sprintf(int t)    {    return (t!='O')?0:    (sizeof(events)>5    ? sprintf("SuperEvent(%s:%O,%O..%O [%d])",    id,events[0],events[1],events[-1],    sizeof(events))    : sprintf("SuperEvent(%s:%s)",    id,map(events,lambda(Event e) { return sprintf("%O",e); })*    ","));    }
pike.git/lib/modules/Calendar.pmod/Event.pmod:1246:      //! Event containing information about when a timezone is changed.   class TZShift_Event   {    inherit Event;       constant is_tzshift_event=1;       Calendar.Rule.Timezone timezone;    -  void create(void|Calendar.Rule.Timezone _tz) +  protected void create(void|Calendar.Rule.Timezone _tz)    {    timezone=_tz;    }       Calendar.TimeRanges.TimeRange next(void|Calendar.TimeRanges.TimeRange from,    void|int(0..1) including)    {    if (!from) from=std_second();    return scan_shift(timezone||from->timezone(),    from,1,including);