diff --git a/.gitattributes b/.gitattributes
index 6861ae761f53c9f43cf7312b098d3b3032952890..1c09c76b30be830269963076040424b27f584f25 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -44,6 +44,7 @@ testfont binary
 /lib/modules/Cache.pmod/Storage.pmod/Memory.pike foreign_ident
 /lib/modules/Cache.pmod/Storage.pmod/Yabu.pike foreign_ident
 /lib/modules/Cache.pmod/cache.pike foreign_ident
+/lib/modules/Calendar.pmod/mkrules.pike foreign_ident
 /lib/modules/Crypto/_rsa.pike foreign_ident
 /lib/modules/Crypto/des3.pike foreign_ident
 /lib/modules/Crypto/des3_cbc.pike foreign_ident
diff --git a/lib/modules/Calendar.pmod/CHANGES b/lib/modules/Calendar.pmod/CHANGES
new file mode 100644
index 0000000000000000000000000000000000000000..10afe847fb5f8b14ff0ebc0daa96bc815fe79066
--- /dev/null
+++ b/lib/modules/Calendar.pmod/CHANGES
@@ -0,0 +1,176 @@
+Calendar -> Calendar II 
+changes and backwards issues
+================================================================
+
+a-b => b->range(a)/a
+
+	a-b does no longer give the number of a's between a and b.
+	Correct use to get the number of something in a time period
+	is to create the period using
+	
+            b->range(a)
+	or, depending on context
+	    b->distance(a)
+	
+	and then divide by the type that you wish to count,
+
+	    b->xxx(a)/a
+
+	so the old use of
+
+	    day2-day1
+
+	will now be
+
+	    day1->distance(day2)/day1
+
+	with more units allowed, so for instance
+
+	    day1->distance(day2)/Month()
+
+        will count the number of months.
+	
+	    a-b
+
+	will now return a stepped back b time,
+	    
+	    day2-day1
+	    
+	therefore means "the day before day2",
+	which might be quite not what you want in your old code.
+
+----------------------------------------------------------------
+
+a->days(), a->months(), etc
+
+	x->units() no longer gives the possible arguments
+	to x->unit(), but the timerange objects themselves:
+
+		Week()->days() 
+		=> ({day,day,day,...,day})
+
+	instead of
+		=> ({0,1,2,3,...,6})
+
+	which is quite more useful. But 
+
+	       map(x->days(),x->day)
+
+	no longer works!
+
+	Also note that ->units() and ->unit() works on 
+	*all* overlapping timeranges of that unit - 
+	this means that
+
+	    year->week(1)
+	or
+	    year->weeks()[0]
+
+	not always is week 1, but some times week 53
+	of the previous year.
+
+----------------------------------------------------------------	
+
+iso_name and other quick string formats
+	
+	The methods to conjure formats has changed name;
+	since all units are interchangable, the old method
+	names "iso_name" and "iso_short_name" are too non-
+	descript and are now represented by some new methods,
+	named "format_xxx" - depending on what unit you wish to print:
+
+         format_...
+	   iso_ymd_full   "2000-06-02 (Jun) -W22-5 (Fri)" [2]
+           ymd            "2000-06-02" 
+           ymd_short      "20000602"
+           ymd_xshort     "000602" [1]
+           iso_week       "2000-W22"
+           iso_week_short "2000W22"
+           week           "2000-w22" [2]
+           week_short     "2000w22" [2]
+           month          "2000-06"
+           month_short    "200006" [1]
+           iso_time_full  "2000-06-02 (Jun) -W22-5 (Fri) 20:53:14 UTC+1" [2]
+           ctime          "Fri Jun  2 20:53:14 2000\n" [2] [3]
+           http           "Fri, 02 Jun 2000 20:53:14 GMT" [4]
+           time           "2000-06-02 20:53:14" 
+           time_short     "20000602 20:53:14"
+           time_xshort    "000602 20:53:14"
+           mtime          "2000-06-02 20:53" 
+           xtime          "2000-06-02 20:53:14.123456" 
+           tod            "20:53:14"
+           tod_short      "205314"
+           todz           "20:53:14 CET"
+           todz_iso       "20:53:14 UTC+1"
+           xtod           "20:53:14.123456"
+           mod            "20:53"
+	
+	[1] note conflict (think 1 February 2003)
+	[2] language dependent
+	[3] as from the libc function ctime()
+	[4] as specified by the HTTP standard;
+	    not language or timezone dependant
+
+Note
+	iso_name and iso_short_name are backwards compatible
+	in the Day and Second objects. 
+
+----------------------------------------------------------------	
+
+(int), (string), number() and name()
+
+	For the same reason, these doesn't exist either.
+	Instead, there are the "datetime" method,
+	that returns a convinient mapping from any object:
+
+	 ([ "year":     int        // year number (2000 AD=2000, 1 BC==0)
+	    "month":    int(1..)   // month of year
+	    "day":      int(1..)   // day of month
+	    "yearday":  int(1..)   // day of year
+	    "week":	int(1..)   // week of year
+	    "week_day": int(1..)   // day of week (depending on calendar)
+
+	    "hour":     int(0..)   // hour of day, including dst
+	    "minute":   int(0..59) // minute of hour
+	    "second":   int(0..59) // second of minute 
+	    "fraction": float      // fraction of second
+	    "timezone": int        // offset to utc, including dst
+
+	    "unix":     int        // unix time
+	    "julian":   int|float  // julian day
+	 ]);
+	
+	and a number of query methods,
+
+	    int month_day()		 
+	    int month_no()		 
+	    int week_day()		 
+	    int week_no()		 - iso week number
+	    int year_day()		 - day of year, 1... 
+	    int year_no()		 - year number, 1AD=1, 1BC=0, 2BC=-1
+
+	    timezone dependant:
+	    float fraction_no()          
+	    int hour_no()		 
+	    int minute_no()		 
+	    int second_no()		 
+
+	    string tzname()		 - CET, CEST, etc
+	    string tzname_iso()		 - UTC+1 - always UTC something
+	    int utc_offset()		 - seconds to utc
+
+	    language dependant:
+	    string month_name()		 - "February"
+	    string month_shortname()	 - "Feb" 
+	    string week_day_name()	 - "Monday"
+	    string week_day_shortname()	 - "Mon"
+	    string week_name()		 - "w42", "v42"
+	    string year_name()		 - "2000", "437 BC"
+
+	    int leap_year()		 - 1 if year is leap year
+
+	    int|float julian_day()	 - julian day
+	    int unix_time()              - unix time
+
+	which should solve the problem better.
+		
diff --git a/lib/modules/Calendar.pmod/Calendar.pike b/lib/modules/Calendar.pmod/Calendar.pike
new file mode 100644
index 0000000000000000000000000000000000000000..adbdb9854d492d72e7bb47f819b944868309412f
--- /dev/null
+++ b/lib/modules/Calendar.pmod/Calendar.pike
@@ -0,0 +1,12 @@
+import ".";
+
+//! module Calendar
+//! class Calendar
+//!	This is the base class of the calendars.
+
+//! method TimeRange now()
+//!	Give the zero-length time period of the
+//!	current time.
+
+TimeRanges.TimeRange now();
+
diff --git a/lib/modules/Calendar.pmod/Coptic.pmod b/lib/modules/Calendar.pmod/Coptic.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..968e48c21d3b5f8179fbbb142effa3ee3041ea0e
--- /dev/null
+++ b/lib/modules/Calendar.pmod/Coptic.pmod
@@ -0,0 +1,98 @@
+//!
+//! module Calendar
+//! submodule Coptic
+//!
+//! 	This is the Coptic Orthodox Church calendar,
+//!	that starts the 11th or 12th September and has
+//!	13 months. 
+//!
+//! note:
+//!	The (default) names of the months
+//!	are different then other the emacs calendar;
+//!	I do not know which ones are used - the difference
+//!	seem to be only the transcription of the phonetic sounds
+//!	(B <-> P, etc).
+//!
+//!	I do not know for how long back the calendar is valid,
+//!	either. My sources claim that the calendar is synchronized
+//!	with the <ref>Gregorian</ref> calendar, which is odd.
+//! 	
+
+import ".";
+// inherit some rules from Gregorian, like week numbering
+inherit Gregorian:Gregorian;
+
+string calendar_name() { return "Coptic"; }
+
+private static mixed __initstuff=lambda()
+{
+   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_week_day_number_from_name="gregorian_week_day_number_from_name";
+
+   f_year_name_from_number="coptic_year_name_from_number";
+   f_month_name_from_number="coptic_month_name_from_number";
+   f_month_shortname_from_number="coptic_month_shortname_from_number";
+   f_month_number_from_name="coptic_month_number_from_name";
+   f_week_name_from_number="week_name_from_number";
+}();
+
+static constant year_offset=-284;
+static constant start=1720949;
+
+static array year_from_julian_day(int jd)
+{
+   int d=jd-start;
+
+   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;
+
+   return 
+   ({
+      century*100+century_year+year_offset,
+      start+century_year*365+century_year/4+century_jd,
+   });
+}
+
+static int julian_day_from_year(int y)
+{
+   y-=year_offset;
+   return start+y*365+y/4-y/100+y/400;
+}
+
+static int year_leap_year(int y) 
+{ 
+   y-=year_offset;
+   werror("%O\n",y);
+   return (!(((y)%4) || (!((y)%100) && ((y)%400))));
+}
+
+static array(int) year_month_from_month(int y,int m)
+{
+// [y,m,ndays,myd]
+
+   y+=(m-1)/13;
+   m=1+(m-1)%13;
+
+   return ({y,m,m==13?year_leap_year(y)+5:30,1+30*(m-1)});
+}
+
+static array(int) month_from_yday(int y,int yd)
+{
+// [month,day-of-month,ndays,month-year-day]
+   int m=(yd-1)/30+1;
+   int myd=1+30*(m-1);
+   return ({m,1+yd-myd,m==13?year_leap_year(y)+5:30,myd});
+}
+
+class cYear
+{
+   inherit Gregorian::cYear;
+
+   int number_of_months()
+   {
+      return 13*n;
+   }
+}
diff --git a/lib/modules/Calendar.pmod/Discordian.pmod b/lib/modules/Calendar.pmod/Discordian.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..3c2b08db8cbede7ee623bd5dddd2eefdb2857393
--- /dev/null
+++ b/lib/modules/Calendar.pmod/Discordian.pmod
@@ -0,0 +1,254 @@
+//!
+//! module Calendar
+//! submodule Discordian
+//!	The Discordian calendar, as described on page 34
+//!	in the fourth edition of Principia Discordia.
+//!
+//!	Chaotic enough, it's quite simpler then the Gregorian calendar;
+//!	weeks are 5 days, and evens up on a year. Months are 73 days.
+//!
+//!	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.
+//!
+//!	The Principia calls months "seasons", but for simplicity I 
+//!	call them months in this calendar.
+//!
+//!	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.
+//!
+//!	- Mirar, Pope of POEE.
+//!
+
+// the discordian calendar follows the gregorian years, very practical ;)
+
+import ".";
+inherit Gregorian:Gregorian;
+
+string calendar_name() { return "Discordian"; }
+
+private static mixed __initstuff=lambda()
+{
+// 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";
+}();
+
+static int compat_week_day(int n)
+{
+   return n; // N/A
+}
+
+// almost as gregorian
+static array year_from_julian_day(int jd)
+{
+   array a=::year_from_julian_day(jd);
+   return ({a[0]+1166,a[1]});
+}
+
+static int julian_day_from_year(int y)
+{
+   return ::julian_day_from_year(y-1166);
+}
+
+static int year_leap_year(int y) 
+{ 
+   return ::year_leap_year(y-1166);
+}
+
+static array(int) year_month_from_month(int y,int m)
+{
+// [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");
+}
+
+static array(int) month_from_yday(int y,int yd)
+{
+// [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});
+}
+
+static array(int) week_from_julian_day(int jd)
+{
+// [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});
+}
+
+static array(int) week_from_week(int y,int w)
+{
+// [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));
+}
+
+static int year_remaining_days(int y,int yday)
+{
+   return 365+year_leap_year(y)-yday;
+}
+
+class cYear
+{
+   inherit Gregorian::cYear;
+
+   int number_of_weeks()
+   {
+      return 73*n;
+   }
+
+   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);
+   }
+
+   int year_no() { return y+1166; }
+}
+
+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";
+   }
+
+   int year_no() { return y+1166; }
+}
+
+class cMonth
+{
+   inherit Gregorian::cMonth;
+
+   void create(mixed ...args)
+   {
+      ::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);
+   }
+
+   int year_no() { return y+1166; }
+}
+
+class cWeek
+{
+   inherit Gregorian::cWeek;
+
+   static int weeks_to_week(int y2,int w2)
+   {
+      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;
+   }
+
+   int year_no() { return y+1166; }
+}
diff --git a/lib/modules/Calendar.pmod/Event.pmod b/lib/modules/Calendar.pmod/Event.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..ecd8edb15e1fdca40384bc53fa50eae3eab57323
--- /dev/null
+++ b/lib/modules/Calendar.pmod/Event.pmod
@@ -0,0 +1,1103 @@
+import ".";
+constant TimeRange=TimeRanges.TimeRange;
+
+constant M_YD=({0,0,31,59,90,120,151,181,212,243,273,304,334});
+constant M_ED=({({0,31,59,90,120,151,181,212,243,273,304,334,365}),
+		({0,31,60,91,121,152,182,213,244,274,305,335,366}),
+		({0,31,60,90,120,151,181,212,243,273,304,334,365}) });
+constant M_NAME="---JanFebMarAprMayJunJulAugSepOctNovDec"/3;
+constant WD_NAME="---MonTueWedThuFriSatSun"/3;
+
+// ----------------------------------------------------------------
+// base classes
+// ----------------------------------------------------------------
+
+//! module Calendar
+//! submodule Event
+//! subclass Event
+//! 	<ref>Event</ref> is a base class, defining what
+//!	methods an Event need to have.
+
+//! method array(TimeRange) scan(TimeRange in)
+//!	This calculates the eventual events that
+//!	is contained or overlapped by the given timerange.
+//!	
+//!	Example:
+//!	<tt>Event.christmas_eve->scan(Year(2000))</tt>
+//!	=> <tt>({ Day(Sun 24 Dec 2000) })</tt>
+//!
+//!	<ref>scan</ref> uses <ref>next</ref> if not overloaded.
+//!
+//! note:
+//!	<ref>scan</ref> can return an array of overlapping timeranges.
+//!	
+//!	This method must use <tt>in->calendar_object-></tt><i>type</i>
+//!	to create the returned timeranges, and must keep the ruleset.
+
+//! method TimeRange next(TimeRange from,void|int(0..1) including)
+//! method TimeRange previous(TimeRange from,void|int(0..1) including)
+//!	This calculates the next or previous occurance of the event,
+//!	from the given timerange's <b>start</b>,
+//!	including any event occuring at the start if that flag is set.
+//!
+//!	It returns zero if there is no next event.
+//!
+//!	This method is virtual in the base class.
+
+class Event
+{
+   string name;
+
+   constant is_event=1;
+
+   TimeRange next(TimeRange from,void|int(0..1) including);
+   TimeRange previous(TimeRange from,void|int(0..1) including);
+
+// what events in this period?
+   array(TimeRange) scan(TimeRange in)
+   {
+      array res=({});
+      TimeRange t=next(in,1);
+      for (;;)
+      {
+	 if (!t || !t->overlaps(in)) return res;
+	 res+=({t});
+	 t=next(t);
+      }
+   }
+
+   mapping(TimeRange:Event) scan_events(TimeRange in)
+   {
+      array r=scan(in);
+      return mkmapping(r,allocate(sizeof(r),this_object()));
+   }
+
+   Event `|(Event ... with)
+   {
+      with-=({0});
+      with|=({this_object()});
+      if (sizeof(with)==1) return with[0];
+      return SuperEvent(with);
+   }
+   Event ``|(Event with) { return `|(with); }
+
+   string _sprintf(int t)
+   {
+      return (t!='O')?0:sprintf("Event(%s)",name);
+   }
+
+   array(Event) cast(string to)
+   {
+      if (to[..4]=="array")
+	 return ({this_object()});
+      else
+	 error("Can't cast to %O\n",to);
+   }
+
+   string describe()
+   {
+      return "Unknown event";
+   }
+}
+
+class NullEvent
+{
+   inherit Event;
+
+   void create(mixed ...args) {}
+ 
+   TimeRange next(TimeRange from,void|int(0..1) including)
+   {
+      return 0;
+   }
+
+   TimeRange previous(TimeRange from,void|int(0..1) including)
+   {
+      return 0;
+   }
+}
+
+//! module Calendar
+//! submodule Event
+//! subclass Day_Event
+//! 	<ref>Day_Event</ref> is a base class, extending <ref>Event</ref>
+//!	for events that are single days, using julian day numbers
+//!	for the calculations.
+//!
+//! method array(TimeRange) scan(TimeRange in)
+//! method TimeRange next(TimeRange from)
+//! method TimeRange next(TimeRange from,int(0..1) including)
+//!	These methods are implemented, using the
+//!	virtual method <ref>scan_jd</ref>.
+//! see also: Event
+//!
+//! method int scan_jd(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 (&gt;<i>jd</i>) when the event occurs,
+//!	or the constant <tt>NODAY</tt> if it doesn't.
+//!
+//!	<i>direction</I> <tt>1</tt> is forward (next), 
+//!	<tt>-1</tt> is backward (previous).
+
+class Day_Event
+{
+   inherit Event;
+
+   constant is_day_event=1;
+   constant NODAY=-1;
+
+   int nd=1;
+
+// find the next (or same) jd with the event
+   int scan_jd(Calendar realm,int jd,int(1..1)|int(-1..-1) direction);
+
+// find
+   TimeRange next(TimeRange from,void|int(0..1) including)
+   {
+      int jd=(int)(from->julian_day())+!including;
+      jd=scan_jd(from->calendar(),jd,1);
+      if (jd==NODAY) return 0;
+      return (from->calendar()->Day)("julian_r",jd,from->ruleset())*nd;
+   }
+
+   TimeRange previous(TimeRange from,void|int(0..1) including)
+   {
+      float|int jd=from->julian_day();
+      if (floatp(jd)) jd=(int)ceil(jd);
+      if (!including) jd--;
+      jd=scan_jd(from->calendar(),jd,-1);
+      if (jd==NODAY) return 0;
+      return (from->calendar()->Day)("julian_r",jd,from->ruleset())*nd;
+   }
+}
+
+
+//! module Calendar
+//! submodule Event
+//! subclass Nameday
+//!	This is created by the <ref>Namedays</ref> classes
+//!	to represent an event for a name.
+
+class Nameday
+{
+   inherit Day_Event;
+
+   constant is_nameday=1;
+
+   int jd;
+
+   void create(string _name,int _jd)
+   {
+      name=_name;
+      jd=_jd;
+   }
+
+   int scan_jd(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)
+   {
+      return t=='O'?sprintf("Nameday(%s)",name):0;
+   }
+}
+
+//! module Calendar
+//! submodule Event
+//! subclass Namedays
+//!	This contains a ruleset about namedays. It 
+//!	is a virtual base class.
+//! inherits Event
+
+class Namedays
+{
+   inherit Event;
+   constant is_namedays=1;
+
+//! method array(string) names(TimeRange t)
+//!	Gives back an array of names that occur during
+//!	the time period, in no particular order.
+
+   array(string) names(TimeRange t)
+   {
+// optimize this?
+      return predef::`|(({}),@values(namedays(t)));
+   }
+
+//! method mapping(TimeRange:array(string)) namedays(TimeRange t)
+//!	Gives back an table of days with names that occur during
+//!	the time period. Note that days without names will not
+//!	appear in the returned mapping.
+
+   mapping(TimeRange:array(string)) namedays(TimeRange t)
+   {
+      int jd=t->julian_day();
+      mapping res=([]);
+      function(mixed...:TimeRange) day=t->calendar()->Day;
+      Ruleset rules=t->ruleset();
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      int ld;
+      array(string) names=namedays_year(y);
+      if (y<2000) ld=55-1; // 24 feb
+      else ld=60-1;        // 29 feb
+
+      for (;;)
+      {
+	 TimeRange td=day("julian_r",jd,rules);
+	 if (!td->overlaps(t)) return res; 
+
+	 if (jd>=yjd+365+leap)  // next year
+	 {
+	    [y,yjd,leap]=gregorian_yjd(jd);
+	    names=namedays_year(y);
+	    if (y<2000) ld=55-1; // 24 feb
+	    else ld=60-1;        // 29 feb
+	 }
+
+	 if (!names) 
+	 {
+	    jd=yjd+365+leap; // next year, please
+	 }
+	 else
+	 {
+	    string n;
+	    int d=jd-yjd;
+	    if (leap)
+	    { 
+	       if (d<ld) n=names[d];
+	       else if (d>ld) n=names[d-1];
+	       else n=names[-1];
+	    }
+	    else
+	       n=names[d];
+
+	    if (n) res[td]=n/",";
+	    jd++;
+	 }
+      }
+   }
+   
+//! method TimeRange next_name(TimeRange from,string name,int inclusive)
+//! method TimeRange previous_name(TimeRange from,string name,int inclusive)
+//!	Gives back the next or previous day where the name
+//!	occurs, inclusive the start of the given timerange if
+//!	that flag is non-zero.
+
+//! method array(string) namedays_year(int y)
+//!	Static virtual function that should give back the array
+//!	of namedays that year, or zero if there
+//!	are no named days for that year.
+//!
+//!	The array is arranged as day 1..365
+//!	a non-leap year, followed by the leap day.
+//!	If a day doesn't contain names, it should be zero,
+//!	not a string. If a day has more then one name,
+//!	it should be separated by a comma (in the string!).
+
+   static array(string) namedays_year(int y);
+
+//! method int nameday_lookup(int y,string name)
+//!	Static virtual function that gives back the
+//!	day (1..) of the year for the given name -
+//!	if the year is a non-leap year (!), -1
+//!	if the name is on the leap day, or zero if
+//!	the name doesn't exist that year.
+
+   static int nameday_lookup(int y,string s);
+
+//! method mapping make_lookup(array(string) names)
+//!	Help function to make a lookup mapping
+//!	of the names feeded to it.
+//! note:
+//!	This function is <tt>static</tt>.
+
+   static mapping make_lookup(array(string) a)
+   {
+      mapping m=([]);
+      int i;
+      foreach (a,string z)
+      {
+	 if (i++==365) i=-1; // leap day last
+	 if (z) foreach (z/",",string s)
+	    m[lower_case(s)]=i;
+      }
+   }
+
+   mapping(TimeRange:Event) scan_events(TimeRange in)
+   {
+      mapping res=([]);
+      foreach ((array)namedays(in),[TimeRange t,array(string) s])
+	 res[t]=predef::`|(@map(s,Nameday,t->julian_day()));
+      return res;
+   }
+
+   array(TimeRange) scan(TimeRange in)
+   {
+      return indices(namedays(in));
+   }
+
+//! method TimeRange previous(TimeRange from,void|int(0..1) including)
+//! method TimeRange next(TimeRange from,void|int(0..1) including)
+//! known bugs:
+//!	Just returns the argument converted to a day.
+
+   TimeRange next(TimeRange from,void|int(0..1) including)
+   {
+      return from->calendar()
+	 ->Day("julian_r",(int)(from->julian_day()),from->ruleset());
+   }
+
+   TimeRange previous(TimeRange from,void|int(0..1) including)
+   {
+      return from->calendar()
+	 ->Day("julian_r",(int)(from->julian_day()),from->ruleset());
+   }
+
+   string _sprintf(int t)
+   {
+      return t=='O'?sprintf("Namedays(%s)",name):0;
+   }
+
+   string describe()
+   {
+      return "Namedays";
+   }
+}
+
+
+// ----------------------------------------------------------------
+// simple Gregorian date events
+// ----------------------------------------------------------------
+
+static array gregorian_yjd(int jd)
+{
+   int d=jd-1721426;
+
+   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;
+
+   int y=century*100+century_year+1;
+
+   return 
+   ({
+      y,
+      1721426+century_year*365+century_year/4+century_jd,
+      (!(((y)%4) || (!((y)%100) && ((y)%400))))
+   });
+}
+
+static array gregorian_year(int y)
+{
+   return
+   ({
+      y,
+      1721426+(y-1)*365+(y-1)/4-(y-1)/100+(y-1)/400,
+      (!(((y)%4) || (!((y)%100) && ((y)%400))))
+   });
+}
+
+static array julian_yjd(int jd)
+{
+   int d=jd-1721058;
+
+   int quad=d/1461;
+   int quad_year=max( (d%1461-1)/365, 0);
+
+   int y=quad*4+quad_year;
+
+   return 
+   ({
+      y,
+      1721424+(y-1)*365+(y-1)/4,
+      !(y%4),
+   });
+}
+
+static array julian_year(int y)
+{
+   return
+   ({
+      y,
+      1721424+(y-1)*365+(y-1)/4,
+      !(y%4),
+   });
+}
+
+// a set date of year, counting leap day in february -
+// used for the gregorian fixed events in the events list
+class Gregorian_Fixed
+{
+   inherit Day_Event;
+
+   constant is_fixed=1;
+
+   int md,mn;
+   int yd;
+
+   void create(string _name,int(1..31) _md,int(1..12) _mn,int ... _n)
+   {
+      name=_name;
+      md=_md;
+      mn=_mn;
+
+      yd=M_YD[mn]+md;
+//        if (sizeof(_n)) nd=_n[0];
+      nd=1;
+   }
+
+   int scan_jd(Calendar realm,int jd,int(-1..1) direction)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      int njd;
+
+      if (leap && yd>59) 
+	 njd=yjd+yd;
+      else 
+	 njd=yjd+yd-1; // yd start with 1
+      
+      if (direction==1) 
+      {
+	 if (njd>=jd) return njd;
+	 return scan_jd(realm,yjd+365+leap,1);
+      }
+      if (njd<=jd) return njd;
+      return scan_jd(realm,yjd-1,-1);
+   }
+
+   string describe()
+   {
+      return sprintf("%s %2d",M_NAME[mn],md);
+   }
+}
+
+// same, but julian
+class Julian_Fixed
+{
+   inherit Gregorian_Fixed;
+
+   int scan_jd(Calendar realm,int jd,int(-1..1) direction)
+   {
+      [int y,int yjd,int leap]=julian_yjd(jd);
+      int njd;
+
+      for (;;)
+      {
+	 if (leap && yd>59) 
+	    njd=yjd+yd;
+	 else 
+	    njd=yjd+yd-1; // yd start with 1
+
+	 if (direction==1) 
+	 {
+	    if (njd>=jd) return njd;
+	    [y,yjd,leap]=julian_year(y+1);
+	 }
+	 else
+	 {
+	    if (njd<=jd) return njd;
+	    [y,yjd,leap]=julian_year(y-1);
+	 }
+      }
+   }
+
+   string describe()
+   {
+      return sprintf("%s %2d julian",M_NAME[mn],md);
+   }
+}
+
+//! module Calendar
+//! submodule Event
+//! subclass Date
+//! 	This class represents the event of a given gregorian date.
+//!	For instance, 
+//!	<tt>Event.Date(12,10)->next(Day())</tt>
+//!	finds the next 12 of October.
+//!
+//! method void create(int month_day,int month)
+//!	The event is created by a given month day and
+//!	a month number (1=January, 12=December).
+
+class Date
+{
+   inherit Day_Event;
+
+   int md,mn;
+   
+   int yd;
+
+   void create(int _md,int _mn)
+   {
+      md=_md;
+      mn=_mn;
+      name=M_NAME[mn]+" "+md;
+
+      yd=M_YD[mn]+md;
+   }
+
+   int scan_jd(Calendar realm,int jd,int(-1..1) direction)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      for (;;)
+      {
+	 int njd;
+
+	 if (leap && yd>60) 
+	    njd=yjd+yd;
+	 else  
+	    njd=yjd+yd-1; // yd start with 1
+      
+	 if (((direction==1)?njd>=jd:(njd<=jd)) && 
+	     njd-yjd<M_ED[leap][mn]) return njd;
+
+	 if (yd>M_ED[2][mn]) return NODAY;  // will never happen
+
+	 if (direction==1) 
+	    [y,yjd,leap]=gregorian_yjd(yjd+365+leap);
+	 else
+	    [y,yjd,leap]=gregorian_yjd(yjd-1);
+      }
+   }
+}
+
+//! module Calendar
+//! submodule Event
+//! subclass Date_Weekday
+//! 	This class represents the event that a given gregorian date appears
+//!	a given weekday.
+//!	For instance, 
+//!	<tt>Event.Date_Weekday(12,10,5)->next(Day())</tt>
+//!	finds the next 12 of October that is a friday.
+//! 
+//! method 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 <ref>ISO</ref> calendar -
+//!	the <ref>Gregorian</ref> calendar has 1=Sunday, 7=Saturday.
+
+class Date_Weekday
+{
+   inherit Day_Event;
+
+   int md,mn;
+   
+   int yd;
+   int jd_wd;
+
+   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 realm,int jd,int(-1..1) direction)
+   {
+      if (md<1) return 0;
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      for (;;)
+      {
+	 int njd;
+
+	 if (leap && yd>60) 
+	    njd=yjd+yd;
+	 else 
+	    njd=yjd+yd-1; // yd start with 1
+      
+	 if (jd_wd==njd%7 && 
+	     ((direction==1)?njd>=jd:(njd<=jd)) &&
+	     njd-yjd<M_ED[leap][mn]) return njd;
+
+	 if (yd>M_ED[2][mn]) return NODAY;  // will never happen
+
+	 if (direction==1) 
+	    [y,yjd,leap]=gregorian_yjd(yjd+365+leap);
+	 else
+	    [y,yjd,leap]=gregorian_yjd(yjd-1);
+      }
+   }
+}
+
+//! module Calendar
+//! submodule Event
+//! subclass Monthday_Weekday
+//! 	This class represents the event that a given gregorian 
+//!	day of month appears a given weekday.
+//!	For instance, 
+//!	<tt>Event.Date_Weekday(13,5)->next(Day())</tt>
+//!	finds the next friday the 13th.
+//! 
+//! method 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 <ref>ISO</ref> calendar -
+//!	the <ref>Gregorian</ref> calendar has 1=Sunday, 7=Saturday.
+
+class Monthday_Weekday
+{
+   inherit Day_Event;
+
+   int md;
+   int jd_wd;
+
+   void create(int _md,int wd)
+   {
+      md=_md;
+      name=md+","+WD_NAME[wd];
+      jd_wd=(wd+6)%7;
+   }
+
+   int scan_jd(Calendar realm,int jd,int(-1..1) direction)
+   {
+      if (md>31 || md<1) return 0;
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      for (;;)
+      {
+	 array z,w;
+
+	 if (!leap) 
+	    z=({0,31,59,90,120,151,181,212,243,273,304,334});
+	 else 
+	    z=({0,31,60,91,121,152,182,213,244,274,305,335});
+
+	 z=map(z,`+,yjd,md,-1);
+	 w=map(z,`%,7);
+
+	 if (direction==1) 
+	 {
+	    foreach (enumerate(12),int i)
+	       if (w[i]==jd_wd && z[i]>=jd &&
+		   z[i]-yjd<M_ED[leap][i+1]) return z[i];
+	    [y,yjd,leap]=gregorian_yjd(yjd+365+leap);
+	 }
+	 else
+	 {
+	    foreach (enumerate(12),int i)
+	       if (w[i]==jd_wd && z[i]<=jd &&
+		   z[i]-yjd<M_ED[leap][i+1]) return z[i];
+	    [y,yjd,leap]=gregorian_yjd(yjd-1);
+	 }
+      }
+   }
+}
+
+//! module Calendar
+//! submodule Event
+//! subclass Weekday
+//! 	This class represents any given weekday.
+//!	For instance, 
+//!	<tt>Event.Weekday(5)->next(Day())</tt>
+//!	finds the next friday.
+//!
+//!	These are also available as the pre-defined events
+//!	"monday", "tuesday", "wednesday", "thursday", 
+//!	"friday", "saturday" and "sunday".
+//! 
+//! method 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 <ref>ISO</ref> calendar -
+//!	not the <ref>Gregorian</ref> or <ref>Julian</ref>
+//!	calendar that has 1=Sunday, 7=Saturday.
+
+class Weekday
+{
+   inherit Day_Event;
+   constant is_weekday=1;
+
+   int jd_wd;
+
+   void create(int wd)
+   {
+      jd_wd=(wd+6)%7; // convert to julian day numbering
+      name=WD_NAME[wd];
+   }
+
+   int scan_jd(Calendar realm,int jd,int(-1..1) direction)
+   {
+      if (direction==-1) return jd-(jd-jd_wd)%7;
+      return jd+(7-(jd-jd_wd))%7;
+   }
+}
+
+
+// Easter
+
+class Easter
+{
+   inherit Day_Event;
+
+// shift is the year to shift from old to new style
+
+   int shift=1582;
+
+   void create(void|int _shift)
+   {
+      if (_shift) shift=_shift;
+   }
+
+   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;
+//  if (epact<0) epact+=30; // not neccesary for pike
+      int new_moon=31-epact;
+//        werror("epact: %O\n",epact);
+//        werror("new_moon: %O\n",new_moon);
+      if (new_moon<8)
+	 if (epact==24 || epact==25 && (y%19)>10)
+	    new_moon+=29;
+	 else
+	    new_moon+=30;
+      int full_moon=new_moon+13;
+      int week_day=(2+y+y/4-solar+full_moon)%7;
+      return full_moon+7-week_day;
+   }
+
+   int old_style(int y)
+   {
+#if 1
+      int new_moon=23-11*(y%19);
+      while (new_moon<8) new_moon+=30;
+      int full_moon=new_moon+13;
+      int week_day=(y+y/4+full_moon)%7;
+      return full_moon+7-week_day;
+#else
+      int g=y%19;
+      int i=(19*g+15)%30;
+      int j=(y+y/4+i)%7;
+      int l=i-j;
+      int m=3+(l+40)/44;
+      int d=l+28-31*(m/4);
+//        werror("y=%d m=%d d=%d l=%d\n",y,m,d,l);
+      return l+28;
+#endif
+   }
+
+   int easter_yd(int y,int yjd,int leap)
+   {
+      int z=(y<shift)?old_style(y):new_style(y);
+      return `+(yjd,z,58,leap);
+   }
+
+   array(int) my_year(int y)
+   {
+      if (y<shift) return julian_year(y);
+      return gregorian_year(y);
+   }
+
+   int scan_jd(Calendar realm,int jd,int(-1..1) direction)
+   {
+      int y,yjd,leap,ejd;
+
+//        werror("scan %O %O\n",jd,direction);
+
+      [y,yjd,leap]=gregorian_yjd(jd);
+      if (y<shift)
+	 [y,yjd,leap]=julian_yjd(jd);
+
+      for (;;)
+      {
+	 ejd=easter_yd(y,yjd,leap);
+
+//  	 werror("[%O %O %O] %O (%O)\n",y,yjd,leap,ejd,ejd-yjd+1);
+
+	 if (direction==1) 
+	 {
+	    if (ejd>=jd) return ejd;
+	    [y,yjd,leap]=my_year(y+1);
+	 }
+	 else
+	 {
+	    if (ejd<=jd) return ejd;
+	    [y,yjd,leap]=my_year(y-1);
+	 }
+      }
+   }
+}
+
+// Easter relative
+
+class Easter_Relative
+{
+   inherit Easter;
+
+   constant is_easter_relative=1;
+
+   int offset;
+
+   void create(string _name,void|int _offset)
+   {
+      name=_name;
+      offset=_offset;
+   }
+
+   int scan_jd(Calendar realm,int jd,int(-1..1) direction)
+   {
+      return offset+::scan_jd(realm,jd-direction*offset,direction);
+   }
+
+   string describe()
+   {
+      return sprintf("%seaster %+2d, %s",
+		     shift>2000?"orthodox ":"",
+		     offset,WD_NAME[(offset-1)%7+1]);
+   }
+}
+
+// Orthodox Easter relative
+// simple set shift year very high
+
+class Orthodox_Easter_Relative
+{
+   inherit Easter_Relative;
+
+   constant is_easter_relative=1;
+
+   int offset;
+
+   void create(string _name,void|int _offset)
+   {
+      ::create(_name,_offset);
+      shift=9999999;
+   }
+}
+
+// Monthday Weekday relative,
+// n:th special weekday,
+// "fourth sunday before 24 dec" => md=24,mn=12,wd=7,n=-4
+
+class Monthday_Weekday_Relative
+{
+   inherit Gregorian_Fixed;
+
+   constant is_fixed=0;
+
+   int offset;
+   int wd;
+
+   int n,inclusive;
+
+   void create(string name,int(1..31) md,int(1..12) mn,
+	       int(1..7) _wd,int _n,void|int(0..1) _inclusive)
+   {
+      ::create(name,md,mn);
+
+      n=_n;
+      inclusive=_inclusive;
+
+// offset is the offset to the last possible day
+      if (n<0)
+	 offset=(n+1)*7-!inclusive;
+      else if (n>0)
+	 offset=n*7-!!inclusive;
+      else 
+	 offset=3;
+
+      wd=_wd;
+   }
+
+   int scan_jd(Calendar realm,int jd,int(-1..1) direction)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd-offset);
+      for (;;)
+      {
+	 int njd;
+
+	 int d=yd+offset;
+	 if (leap && d>59) 
+	    njd=(yjd+((d)-1)+leap-( (yjd+leap+((d)+(8-wd)-1)) % 7));
+	 else 
+	    njd=(yjd+((d)-1)-( (yjd+((d)+(8-wd)-1)) % 7));
+      
+	 if (direction==1) 
+	 {
+	    if (njd>=jd) return njd;
+	    [y,yjd,leap]=gregorian_year(y+1);
+	 }
+	 else
+	 {
+	    if (njd<=jd) return njd;
+	    [y,yjd,leap]=gregorian_year(y-1);
+	 }
+      }
+   }
+
+   string describe()
+   {
+      return sprintf("%s %2d %s %+2d %s [<=%+d]",
+		     M_NAME[mn],md,WD_NAME[wd],n,
+		     inclusive?"incl":"",offset);
+   }
+}
+
+//! module Calendar
+//! submodule Event
+//! subclass SuperEvent
+//!	This class holds any number of events,
+//!	and adds the functionality of event flags.
+//!
+//! note:
+//!	Scanning (scan_events,next,etc) will drop flag information.
+//!	Dig out what you need with -><ref>holidays</ref> et al first.
+
+class SuperEvent
+{
+   inherit Event;
+   
+   constant is_superevent=1;
+   string name="SuperEvent";
+   
+   mapping(Event:multiset(string)) flags=([]);
+
+   array(Event) events=({});
+
+   array(Event) day_events=({});
+   array(Namedays) namedays=({});
+   array(Event) other_events=({});
+
+   mapping year_cache=([]);
+
+   static void create(array(Event) _events,
+		      void|mapping(Event:multiset(string)) _flags)
+   {
+      if (_flags) flags=_flags;
+
+      foreach (_events,Event e)
+	 if (e->is_superevent) 
+	 {
+	    events|=e->events;
+	    if (flags[e] && flags[e]!=(<>))
+	       foreach (e->events,Event e2)
+		  flags[e2]=flags[e]|(e->flags[e2]||(<>));
+	    else
+	       flags|=e->flags;
+
+	    m_delete(flags,e);
+	 }
+	 else events|=({e});
+
+      foreach (events,Event e)
+	 if (e->is_day_event) day_events+=({e});
+	 else if (e->is_namedays) namedays+=({e});
+	 else other_events+=({e});
+   }
+
+//! method SuperEvent filter_flag(string flag)
+//! method SuperEvent holidays()
+//! method SuperEvent flagdays()
+//!	Filter out the events that has a certain flag set.
+//!	Holidays (flag "h") are the days that are marked
+//!	red in the calendar (non-working days),
+//!	Flagdays (flag "f") are the days that the flag
+//!	should be visible in (only some countries).
+
+   SuperEvent filter_flag(string flag)
+   {
+      array res=({});
+      multiset m;
+      foreach (events,Event e)
+	 if ((m=flags[e]) && m[flag]) res+=({e});
+      return SuperEvent(res,flags&res);
+   }
+
+   SuperEvent holidays() { return filter_flag("h"); }
+   SuperEvent flagdays() { return filter_flag("f"); }
+
+   mapping(TimeRange:Event) scan_events(TimeRange in)
+   {
+      mapping res=([]);
+      foreach (events,Event e)
+      {
+	 mapping er=e->scan_events(in);
+	 foreach ((array)er,[TimeRange t,Event e])
+	    if (res[t]) res[t]|=e; // join 
+	    else res[t]=e;
+      }
+      return res;
+   }
+
+   array(TimeRange) scan(TimeRange in)
+   {
+      return indices(scan_events(in));
+   }
+
+   TimeRange next(TimeRange from,void|int(0..1) including)
+   {
+      TimeRange best=0;
+      foreach (events,Event e)
+      {
+	 TimeRange y=e->next(from,including);
+	 if (!best || y->preceeds(best)) best=y;
+	 else if (y->starts_with(best)) best|=y;
+      }
+      return best;
+   }
+    
+   TimeRange previous(TimeRange from,void|int(0..1) including)
+   {
+      TimeRange best=0;
+      foreach (events,Event e)
+      {
+	 TimeRange y=e->previous(from,including);
+	 if (!best || best->preceeds(y)) best=y;
+	 else if (y->ends_with(best)) best|=y;
+      }
+      return best;
+   }
+
+   Event `|(Event ... with)
+   {
+      with-=({0});
+      return SuperEvent(events|with,flags);
+   }
+   Event ``|(Event with) { return `|(with); }
+
+   Event `-(Event ...subtract)
+   {
+      array(Event) res=events-subtract;
+      if (res==events) return this_object();
+      return SuperEvent(res,flags&res);
+   }
+
+   array(Event) cast(string to)
+   {
+      if (to[..4]=="array")
+	 return events;
+      else
+	 error("Can't cast to %O\n",to);
+   }
+
+   string _sprintf(int t)
+   {
+      return (t!='O')?0:
+	 (sizeof(events)>5 
+	  ? sprintf("SuperEvent(%O,%O..%O [%d])",
+		    events[0],events[1],events[-1],
+		    sizeof(events))
+	  : sprintf("SuperEvent(%s)",
+		    map(events,lambda(Event e) { return sprintf("%O",e); })*
+		    ","));
+   }
+}
+
diff --git a/lib/modules/Calendar.pmod/Events.pmod b/lib/modules/Calendar.pmod/Events.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..0c82ee6a2eebbebe2c3c81daaf599adbb932445e
--- /dev/null
+++ b/lib/modules/Calendar.pmod/Events.pmod
@@ -0,0 +1,5416 @@
+import ".";
+import Event;
+
+program|Event `[](string s)
+{
+   return ::`[](s) || magic_event(s);
+}
+function `-> = `[];
+
+Event|Namedays|Magic_Index magic_event(string s)
+{
+   s=replace(s,"_"," ");
+   Event e;
+   if ( (e=made_events[s]) ) return e;
+   array a=events[s];
+   if (a)
+      return made_events[s]=a[0](@a[1..]);
+
+   if (sizeof(glob(s+"/*",indices(events))))
+      return made_events[s]=Magic_Index(s);
+   return ([])[0];
+}
+
+mapping made_events=([]);
+
+class Magic_Index
+{
+   string base;
+   void create(string s) { base=s+"/"; }
+   Event|Namedays|Magic_Index `[](string s) { return magic_event(base+s); }
+   Event|Namedays|Magic_Index `->(string s) { return `[](s); }
+
+   array(string) _indices()
+   {
+      return map(glob(base+"*",indices(events)),
+		 lambda(string s) { return array_sscanf(s,base+"%[^/]")[0]; });
+   }
+
+   array(Event|Namedays|Magic_Index) _values()
+   {
+      return map(_indices(),`[]);
+   }
+
+   string _sprintf(int t) 
+   { return (t!='O')?0:sprintf("Event index(%O)",base); }
+}
+
+#if 1
+
+mapping(string:SuperEvent) made_countries=([]);
+
+Event country(string name)
+{
+   if (made_countries[name]) return made_countries[name];
+
+   array z=country_events[name];
+   if (!z) return 0;
+
+   array(Event) ze=({});
+   mapping(Event:multiset(string)) zf=([]);
+// reuse those multisets
+   mapping(string:multiset) flags=(["":0,"h":(<"h">),"f":(<"f">)]);
+   flags->hf=flags->fh=(<"h","f">);
+
+   foreach (z,string id)
+      if (id[0]=='+')
+      {
+	 Event e=country(id[1..]);
+	 if (!e) werror("internal error: Missing country %O, can't inherit\n",
+			id[1..]);
+	 else
+	    ze=e->events|ze, zf=e->flags|zf;
+      }
+      else if (id[0]=='-')
+      {
+	 Event e=magic_event(id[1..]);
+	 if (!zf[e]) 
+	    werror("internal error: Missing event %O, can't remove\n",id[1..]);
+	 m_delete(zf,e);
+	 ze-=({e});
+      }
+      else
+      {
+	 string fs="";
+	 sscanf(id,"%s|%s",id,fs);
+	 Event e=magic_event(id);
+	 if (!e) werror("internal error: Missing event %O\n",id);
+	 else ze|=({e});
+	 if (fs!="") zf[e]=flags[fs]||mkmultiset( (array)fs );
+      }
+   return made_countries[name]=SuperEvent(ze,zf);
+}
+#endif
+
+// ----------------------------------------------------------------
+// event definitions
+// ----------------------------------------------------------------
+
+#define FIXED(NAME,MD,MN) \
+	({Gregorian_Fixed,NAME,MD,MN})
+#define FIX_M(NAME,MD,MN,N) \
+	({Gregorian_Fixed,NAME,MD,MN,N})
+
+// relative week day (n: 1=first following, 2=2nd, -1=previous, -2=2nd prev)
+#define DWDR(NAME,MD,MN,WD,N) \
+	({Monthday_Weekday_Relative,NAME,MD,MN,WD,N})
+
+// relative week day, inclusive
+#define DWDRI(NAME,MD,MN,WD,N) \
+	({Monthday_Weekday_Relative,NAME,MD,MN,WD,N,1})
+
+#define EASTER_REL(NAME,OFFSET) \
+	({Easter_Relative,NAME,OFFSET})
+
+#define ORTH_EASTER_REL(NAME,OFFSET) \
+	({Orthodox_Easter_Relative,NAME,OFFSET})
+
+#define J_FIXED(NAME,MD,MN) \
+	({Julian_Fixed,NAME,MD,MN})
+#define J_FIX_M(NAME,MD,MN,N) \
+	({Julian_Fixed,NAME,MD,MN,N})
+
+constant events=([
+// ----------------------------------------------------------------
+// standard
+   "monday":	({Weekday,1}),
+   "tuesday":	({Weekday,2}),
+   "wednesday":	({Weekday,3}),
+   "thursday":	({Weekday,4}),
+   "friday":	({Weekday,5}),
+   "saturday":	({Weekday,6}),
+   "sunday":	({Weekday,7}),
+
+// ----------------------------------------------------------------------
+// global events
+// ----------------------------------------------------------------------
+
+   "new year":		FIXED("New Year's Day",     1, 1),
+   "unity":             FIXED("Unity Day",         22, 2),
+   "womens":		FIXED("Int. Women's Day",   8, 3),
+   "arab league":       FIXED("Arab League Day",   22, 3),
+   "anzac":             FIXED("ANZAC Day",         25, 4),
+   "labor":		FIXED("Labor Day", 	    1, 5),
+   "may day":           FIXED("May Day",            1, 5),
+   "africa":            FIXED("Africa Day",        25, 5),
+   "perseid meteor shower":FIXED("Perseid Meteor Shower",11,8),
+   "columbus":          FIXED("Columbus Day",      12,10),
+   "un":		FIXED("UN Day",	   	   24,10),
+   "halloween":         FIXED("Halloween",         31,10),
+   "armistice":         FIXED("Armistice Day",     11,11),
+   "family":            FIXED("Family Day",        25,12),
+   "kwanzaa":           FIXED("Kwanzaa",           26,12),
+   "new years eve":	FIXED("New Year's Eve",    31,12),
+
+   "mardi gras":        EASTER_REL("Mardi Gras",-47),
+
+   "mothers":          	DWDRI("Mother's Day",	1,5,7,2),
+   "fathers":          	DWDRI("Father's Day",	1,6,7,3),
+
+// ----------------------------------------------------------------------
+// religious events
+// ----------------------------------------------------------------------
+
+// common (catholic) christianity
+
+   "c/circumcision":    FIXED("Feast of the Circumcision",1,1),
+   "c/epiphany":	FIXED("Epiphany",        6, 1),
+   "c/presentation":	FIXED("Presentation",    2, 2),
+   "c/candlemas":       FIXED("Candlemas",       2, 2),
+   "c/annunciation":	FIXED("Annunciation",   25, 3),
+   "c/transfiguration": FIXED("Transfiguration", 6, 8),
+   "c/assumption":      FIXED("Assumption Day", 15, 8),
+   "c/nativity of mary":FIXED("Nativity of Mary",8, 9),
+   "c/all saints":	FIXED("All Saints Day",  1,11),
+   "c/all souls":	FIXED("All Souls Day",   2,11),
+   "c/immaculate conception":FIXED("Immaculate Conception",8,12),
+   "c/christmas eve":	FIXED("Christmas Eve",  24,12),
+   "c/christmas":	FIXED("Christmas Day",  25,12),
+   "c/christmas2d":	FIX_M("Christmas",      25,12,2),
+   "c/boxing":		FIXED("Boxing Day",     26,12),
+   "c/childermas":      FIXED("Childermas",     28,12),
+
+   "c/shrove sunday":   EASTER_REL("Shrove Sunday",   -49),
+   "c/shrove monday":   EASTER_REL("Shrove Monday",   -48),
+   "c/rose monday":     EASTER_REL("Rose Monday",     -48), // aka
+   "c/shrove tuesday":  EASTER_REL("Shrove Tuesday",  -47),
+   "c/fat tuesday":     EASTER_REL("Fat Tuesday",     -47), // aka
+   "c/ash wednesday":   EASTER_REL("Ash wednesday",   -46),
+   "c/palm sunday":     EASTER_REL("Palm Sunday",      -7),
+   "c/holy thursday":   EASTER_REL("Holy Thursday",    -3),
+   "c/maundy thursday": EASTER_REL("Maundy Thursday",  -3), // aka
+   "c/holy friday":     EASTER_REL("Holy Friday",      -2), 
+   "c/good friday":     EASTER_REL("Good Friday",      -2), // aka
+   "c/holy saturday":   EASTER_REL("Holy Saturday",    -1), 
+   "c/easter eve":      EASTER_REL("Easter Eve",       -1), // aka
+   "c/easter":          EASTER_REL("Easter",            0),
+   "c/easter monday":   EASTER_REL("Easter Monday",     1),
+   "c/rogation sunday": EASTER_REL("Rogation Sunday",  35),
+   "c/ascension":       EASTER_REL("Ascension",        39),
+   "c/pentecost eve":   EASTER_REL("Pentecost Eve",    48),
+   "c/pentecost":       EASTER_REL("Pentecost",        49),
+   "c/whitsunday":      EASTER_REL("Whitsunday",       49), // aka
+   "c/pentecost monday":EASTER_REL("Pentecost Monday",50),
+   "c/whitmonday":      EASTER_REL("Whitmonday",       50), // aka
+   "c/trinity":         EASTER_REL("Trinity",          56),
+   "c/corpus christi":  EASTER_REL("Corpus Christi",   60),
+
+   "c/advent 1":        DWDR ("Advent 1",24,12,7,-4),
+   "c/advent 2":        DWDR ("Advent 2",24,12,7,-3),
+   "c/advent 3":        DWDR ("Advent 3",24,12,7,-2),
+   "c/advent 4":        DWDR ("Advent 4",24,12,7,-1),
+
+// other
+
+   "catholic church/baptism of christ":
+                                 FIXED("Feast of the Baptism of Christ",13,1),
+   "catholic church/christ the king":
+                                 DWDRI("Feast of Christ the King",1,10,7,-1),
+   "catholic church/gaurdian angles":
+                                 FIXED("Feast of the Gaurdian Angles",2,10),
+   "catholic church/transfiguration":FIXED("Transfiguration",6,8),
+
+// orthodox
+
+// I don't know which of these are/will be needed:
+   "orhodox/circumcision":    	J_FIXED("Feast of the Circumcision",1,1),
+   "orthodox/epiphany":		J_FIXED("Epiphany",        6, 1),
+   "orthodox/presentation":	J_FIXED("Presentation",    2, 2),
+   "orthodox/candlemas":       	J_FIXED("Candlemas",       2, 2),
+   "orthodox/annunciation":	J_FIXED("Annunciation",   25, 3),
+   "orthodox/transfiguration": 	J_FIXED("Transfiguration", 6, 8),
+   "orthodox/assumption":      	J_FIXED("Assumption Day", 15, 8),
+   "orthodox/nativity of mary":	J_FIXED("Nativity of Mary",8, 9),
+   "orthodox/immaculate conception":J_FIXED("Immaculate Conception",8,12),
+   "orthodox/christmas eve":	J_FIXED("Christmas Eve",  24,12),
+   "orthodox/christmas":	J_FIXED("Christmas Day",  25,12),
+   "orthodox/christmas2d":	J_FIX_M("Christmas",      25,12,2),
+   "orthodox/boxing":		J_FIXED("Boxing Day",     26,12),
+   "orthodox/childermas": 	J_FIXED("Childermas",     28,12),
+
+   "orthodox/triodon":		ORTH_EASTER_REL("Triodon",-70),
+   "orthodox/sat. of souls":	ORTH_EASTER_REL("Sat. of Souls",-57),
+   "orthodox/meat fare":	ORTH_EASTER_REL("Meat Fare",-56),
+   "orthodox/2nd sat. of souls":ORTH_EASTER_REL("2nd Sat. of Souls",-50),
+   "orthodox/lent begins":	ORTH_EASTER_REL("Lent Begins",-48),
+   "orthodox/saints/theodore":	ORTH_EASTER_REL("St. Theodore",-43),
+   "orthodox/orthodoxy":	ORTH_EASTER_REL("Sunday of Orthodoxy",-42),
+   "orthodox/lazarus":		ORTH_EASTER_REL("Saturday of Lazarus",-8),
+   "orthodox/palm sunday":	ORTH_EASTER_REL("Palm Sunday",-7),
+   "orthodox/good friday":	ORTH_EASTER_REL("Good Friday",-2),
+   "orthodox/holy saturday":	ORTH_EASTER_REL("Holy Saturday",-1),
+   "orthodox/easter":		ORTH_EASTER_REL("Easter",0),
+   "orthodox/easter monday":	ORTH_EASTER_REL("Easter Monday",1),
+   "orthodox/ascension":	ORTH_EASTER_REL("Ascension",39),
+   "orthodox/sat. of souls":	ORTH_EASTER_REL("Sat. of Souls",48),
+   "orthodox/pentecost":	ORTH_EASTER_REL("Pentecost",49),
+   "orthodox/pentecost monday":	ORTH_EASTER_REL("Pentecost Monday",50),
+   "orthodox/all saints":	ORTH_EASTER_REL("All Saints",56),
+
+   "bahai/ascension of abdul-baha":FIXED("Ascension of 'Abdu'l-Baha",28,11),
+   "bahai/ascension of bahaullah":FIXED("Ascension of Baha'u'llah",29,5),
+   "bahai/birth of bab":         FIXED("Birth of Bab",20,10),
+   "bahai/birth of bahaullah":   FIXED("Birth of Baha'u'llah",12,11),
+   "bahai/day of the covenant":  FIXED("Day of the Covenant",27,11),
+   "bahai/declaration of bab":   FIXED("Declaration of B\341b",23,5),
+   "bahai/festival of ridvan":   FIXED("Festival of Ridv\341n",21,4),
+   "bahai/martyrdom of bab":     FIXED("Martyrdom of Bab",9,7),
+   "bahai/naw-ruz":              FIXED("Naw-R\372z",21,3),
+
+// temporary
+   "saints/basil":      FIXED("St. Basil",1,1),
+   "saints/devote":     FIXED("St. Devote",27,1),
+   "saints/blaise":     FIXED("St. Blaise",3,2),
+   "saints/valentine":	FIXED("St. Valentine",14,2),
+   "saints/john the baptist": FIXED("St. John the Baptist",24,6),
+   "saints/peter":	FIXED("St. Peter",29,6),
+   "saints/paul":	FIXED("St. Paul",29,6),
+   "saints/demetrios":  FIXED("St. Demetrios",26,10),
+   "saints/lucy": 	FIXED("St. Lucy",13,12),
+   "saints/stephen":	FIXED("St. Stephen",26,12), // aka boxing day
+   "saints/patrick":	FIXED("St. Patrick",17,3),
+   "saints/david":      FIXED("St. David",1,3),
+
+// ---------------------------------------------------------------------
+// historic and political
+// ---------------------------------------------------------------------
+
+#if 0
+// this should be the julian dates...
+   "roman festivals/agonalia":   FIXED("Agonalia",9,1),
+   "roman festivals/ambarvalia": FIXED("Ambarvalia",29,5),
+   "roman festivals/carmentalia":FIX_M("Carmentalia",11,1,5),
+   "roman festivals/cerealia":   FIXED("Cerealia",19,4),
+   "roman festivals/equiria":    FIXED("Equiria",14,3),
+   "roman festivals/faunalia":   FIXED("Faunalia",13,2),
+   "roman festivals/feralia":    FIXED("Feralia",18,2),
+   "roman festivals/festival of anna perenna":
+                                 FIXED("festival of Anna Perenna",15,3),
+   "roman festivals/festival of the lares pr\346stites":
+                               FIXED("festival of the Lares Pr\346stites",1,5),
+   "roman festivals/floria":     FIXED("Floria",28,4),
+   "roman festivals/fools":      FIXED("Feast of Fools",17,2),
+   "roman festivals/fordicidia": FIXED("Fordicidia",15,4),
+// "roman festivals/fornicalia": February,
+   "roman festivals/lemuria":    FIX_M("Lemuria",9,5,5),
+   "roman festivals/liberalia":  FIXED("Liberalia",17,3),
+   "roman festivals/ludi apollinares":FIXED("Ludi Apollinares",5,7),
+   "roman festivals/ludi consualia":FIXED("Ludi Consualia",21,8),
+   "roman festivals/ludi martiales":FIXED("Ludi Martiales",12,5),
+   "roman festivals/ludi merceruy":FIXED("Ludi Merceruy",15,5),
+   "roman festivals/lupercalia": FIXED("Lupercalia",15,2),
+   "roman festivals/magalesia":  FIX_M("Magalesia",4,4,7),
+   "roman festivals/matralia":   FIXED("Matralia",11,6),
+   "roman festivals/matronalia": FIXED("Matronalia",1,3),
+   "roman festivals/nemoralia":  FIXED("Nemoralia",13,8),
+   "roman festivals/neptunalia": FIXED("Neptunalia",23,7),
+   "roman festivals/paganalia":  FIX_M("Paganalia",24,1,3),
+   "roman festivals/parentalia": FIX_M("Parentalia",13,2,9),
+   "roman festivals/parilia":    FIXED("Parilia",21,4),
+   "roman festivals/portunalia": FIXED("Portunalia",17,8),
+   "roman festivals/quinquatrus minusculoe":
+                                 FIXED("Quinquatrus Minusculoe",13,6),
+   "roman festivals/quinquatrus[quinquatria?]":
+                                 FIX_M("Quinquatrus[Quinquatria?]",19,3,3),
+   "roman festivals/quirinalia": FIXED("Quirinalia",17,2),
+   "roman festivals/regifugium": FIXED("Regifugium",24,2),
+   "roman festivals/robigalia":  FIXED("Robigalia",25,4),
+// "roman festivals/semo sanctus":occurred in June,
+   "roman festivals/terminalia": FIXED("Terminalia",23,2),
+   "roman festivals/the vestalia":FIXED("The Vestalia",9,6),
+   "roman festivals/tubilustrium":FIXED("Tubilustrium",23,3),
+   "roman festivals/vinalia":    FIXED("Vinalia",23,4),
+   "roman festivals/vinalia rustica":FIXED("Vinalia Rustica",19,8),
+   "roman festivals/volcanalia": FIXED("Volcanalia",23,8),
+#endif
+
+   "british commonwealth/august bank holiday":
+                                 DWDRI("August Bank Holiday",1,8,1,1),
+   "british commonwealth/empire":FIXED("Empire Day",24,5),
+   "british commonwealth/prince of wales":
+                                 FIXED("Prince of Wales' Birthday",14,11),
+   "british commonwealth/queens":FIXED("Queen's Birthday",4,6),
+
+   "caribbean/caricom":          DWDRI("CARICOM Day",1,7,1,1),
+   "caribbean/emancipation":     DWDRI("Emancipation Day",1,8,1,1),
+   "caribbean/schoelcher":       FIXED("Schoelcher Day",21,7),
+
+// ----------------------------------------------------------------
+// verified
+// ----------------------------------------------------------------
+
+   "argentina/revolution":	FIXED("Revolution Anniversary",25,5),
+   "argentina/soberanys":	FIXED("Soberany's Day",10,6),
+   "argentina/flag":		FIXED("Flag's Day",20,6),
+   "argentina/independence":    FIXED("Independence Day",9,7),
+   "argentina/gral san martin": FIXED("Gral San Martín decease",17,8),
+   "argentina/race":            FIXED("Race's Day",12,10),
+   "argentina/malvinas":         FIXED("Malvinas Day",2,4),  
+
+   "sweden/kings birthday":     FIXED("King's Birthday",30,4),
+   "sweden/kings nameday 2":    FIXED("King's Nameday",28,1),
+   "sweden/crown princess nameday": FIXED("Crown Princess' Nameday",12,3),
+   "sweden/crown princess birthtday":FIXED("Crown Princess' Birthday",14,7),
+   "sweden/flag":               FIXED("Sweden's Flag Day",6,6),
+   "sweden/kings nameday":      FIXED("King's Nameday",6,11),
+   "sweden/nobel":              FIXED("Nobel Day",10,12),
+   "sweden/queens birthday":    FIXED("Queen's Birthday",23,12),
+   "sweden/queens nameday":     FIXED("Queen's Nameday",8,8),
+   "sweden/valborg eve":        FIXED("Valborgsmässoafton",30,4),
+   "sweden/waffle":             FIXED("Waffle Day",25,3),
+   "sweden/all saints":         DWDRI("Alla helgons dag",1,11,6,1),
+   "sweden/midsummers eve":     DWDRI("Midsummer's Eve",20,6,5,1),
+   "sweden/midsummer":          DWDRI("Midsummer's Day",21,6,6,1),
+   "sweden/mothers":           	DWDR  ("Mother's Day",	1,6,7,-1),
+   "sweden/fathers":           	DWDRI("Father's Day",	1,11,7,2),
+
+   "russia/state sovereignity":  FIXED("State Sovereignity Day",12,6),
+   "russia/victory":             FIXED("Victory Day",9,5),
+   "russia/valpurgis":           FIXED("Valpurgis Night",1,5),
+   "russia/warriors":            FIXED("Warriors Day",23,2),
+   "russia/teachers":            FIXED("Teachers Day",1,10),
+
+// ----------------------------------------------------------------
+// not verified
+// ----------------------------------------------------------------
+
+   "afghanistan/afghan new year":FIXED("Afghan New Year",21,3),
+   "afghanistan/childrens":      FIXED("Children's Day",30,8),
+   "afghanistan/independence":   FIXED("Independence Day",27,5),
+// "afghanistan/jeshyn-afghans": August [28-31?],
+   "afghanistan/mothers":        FIXED("Mother's Day",14,6),
+   "afghanistan/national assembly":DWDRI("National Assembly Day",1,9,3,2),
+   "afghanistan/revolution":     FIXED("Revolution Day",27,4),
+   "afghanistan/workers":        FIXED("Workers' Day",1,5),
+
+   "albania/army":               FIXED("Army Day",10,7),
+   "albania/independence":       FIXED("Independence Day",28,11),
+   "albania/liberation":         FIXED("Liberation Day",29,11),
+   "albania/proclamation of the republic":
+                                FIXED("Proclamation of the Republic Day",11,1),
+
+   "algeria/independence":       FIXED("Independence Day",3,7),
+   "algeria/national":           FIXED("National Day",19,6),
+   "algeria/revolution":         FIXED("Revolution Day",1,11),
+
+   "american baptist/roger williams":FIXED("Roger Williams Day",5,2),
+
+   "american samoa/flag":        FIXED("Flag Day",17,4),
+
+   "andorra/national feast":     FIXED("National Feast Day",8,9),
+
+   "anglican church/name of jesus":FIXED("Feast of the Name of Jesus",7,8),
+
+   "angola/armed forces":     	 FIXED("Armed Forces Day",1,8),
+   "angola/independence":     	 FIXED("Independence Day",11,11),
+   "angola/mpla foundation":  	 FIXED("MPLA Foundation Day",10,12),
+   "angola/national heros":   	 FIXED("National Hero's Day",17,9),
+   "angola/national holiday": 	 FIXED("National Holiday",4,2),
+   "angola/pioneers":         	 FIXED("Pioneers' Day",1,12),
+   "angola/victory":          	 FIXED("Victory Day",27,3),
+   "angola/workers":          	 FIXED("Workers' Day",1,5),
+   "angola/youth":            	 FIXED("Youth Day",14,4),
+
+   "anguilla/anguilla":          FIXED("Anguilla Day",1,6),
+
+   "antigua and barbuda/independence":FIXED("Independence Day",1,11),
+
+   "armenia/christmas":          FIXED("Christmas",6,1),
+   "armenia/martyrs":            FIXED("Martyrs' Day",24,4),
+   "armenia/republic":           FIXED("Republic Day",28,5),
+
+   "aruba/aruba flag":           FIXED("Aruba Flag Day",18,3),
+
+   "australia/australia":        FIXED("Australia Day",26,1),
+   "australia/eight hour":       FIXED("Eight Hour Day",11,10),
+   "australia/foundation":       FIXED("Foundation Day",7,6),
+   "australia/hobert regatta":   FIXED("Hobert Regatta Day",9,2),
+   "australia/proclamation":     FIXED("Proclamation Day",28,12),
+   "australia/recreation":       FIXED("Recreation Day",1,11),
+   "australia/second new years": FIXED("Second New Year's Day",2,1),
+   "australia/show":             DWDRI("Show Day",1,11,2,1),
+   "australia/summer bank holiday":DWDRI("Bank Holiday",1,8,1,4), // ?
+   "australia/spring bank holiday":DWDRI("Bank Holiday",1,3,1,4), // ?
+
+   "austria/national":           FIXED("National Day",15,5),
+   "austria/national holiday":   FIXED("National Holiday",26,10),
+   "austria/national holiday of austria":
+                                 FIXED("National Holiday of Austria",26,10),
+   "austria/republic":           FIXED("Republic Day",12,11),
+   "austria/second republic":    FIXED("Second Republic Day",27,4),
+
+   "bahamas/fox hill":           DWDRI("Fox Hill Day",1,8,2,2),
+   "bahamas/independence":       FIXED("Independence Day",10,7),
+   "bahamas/labor":              DWDRI("Labour Day",1,6,5,1),
+
+   "bahrain/national of bahrain":FIXED("National Day of Bahrain",16,12),
+
+   "bangladesh/bengali new year":FIXED("Bengali New Year",14,4),
+   "bangladesh/independence":    FIXED("Independence Day",26,3),
+   "bangladesh/national mourning":FIXED("National Mourning Day",21,2),
+   "bangladesh/revolution":      FIXED("Revolution Day",7,11),
+   "bangladesh/victory":         FIXED("Victory Day",16,12),
+
+   "barbados/errol barrow":      FIXED("Errol Barrow Day",21,1),
+   "barbados/independence":      FIXED("Independence Day",30,11),
+   "barbados/united nations":    FIXED("United Nations Day",7,10),
+
+   "belgium/dynasty":            FIXED("Dynasty Day",15,11),
+   "belgium/independence":       FIX_M("Independence Day",21,7,2),
+   "belgium/kings":              FIXED("King's Birthday",15,11),
+
+   "belize/baron bliss":         FIXED("Baron Bliss Day",9,3),
+   "belize/commonwealth":        FIXED("Commonwealth Day",24,5),
+   "belize/garifuna":            FIXED("Garifuna Day",19,11),
+   "belize/independence":        FIXED("Independence Day",21,9),
+   "belize/national":            FIXED("National Day",10,9),
+   "belize/pan american":        FIXED("Pan American Day",12,10),
+   "belize/saint georges cay":   FIXED("St. George's Cay Day",10,9),
+
+   "benin/armed forces":         FIXED("Armed Forces Day",26,10),
+   "benin/harvest":              FIXED("Harvest Day",31,12),
+   "benin/martyrs":              FIXED("Martyrs' Day",16,1),
+   "benin/national":             FIXED("National Day",30,11),
+   "benin/workers":              FIXED("Workers' Day",1,5),
+   "benin/youth":                FIXED("Youth Day",1,4),
+
+   "bermuda/bermuda":            FIXED("Bermuda Day",24,5),
+   "bermuda/peppercorn":         FIXED("Peppercorn Day",23,4),
+   "bermuda/remembrance":        FIXED("Remembrance Day",11,11),
+   "bermuda/somers":             FIXED("Somers Day",28,7),
+
+   "bhutan/kings":               FIXED("King's Birthday",11,11),
+   "bhutan/national of bhutan":  FIXED("National Day of Bhutan",17,12),
+
+// "bolivia/alacitas":           occurs in January,
+   "bolivia/independence":       FIXED("Independence Day",6,8),
+   "bolivia/la paz":             FIXED("La Paz Day",16,7),
+   "bolivia/martyrs":            FIXED("Martyrs' Day",21,7),
+   "bolivia/memorial":           FIXED("Memorial Day",23,3),
+   "bolivia/national":           FIXED("National Day",9,4),
+
+   "bosnia and herzegovina/labors":FIX_M("Labor Days",1,5,2),
+
+   "botswana/botswana":          FIXED("Botswana Day",30,9),
+   "botswana/presidents":        FIXED("President's Day",24,5),
+
+   "brazil/brasilia":            FIXED("Brasilia Day",21,4),
+   "brazil/discovery":           FIXED("Discovery Day",22,4),
+   "brazil/independence":        FIXED("Independence Day",7,9),
+   "brazil/proclamation of the republic":
+                               FIXED("Proclamation of the Republic Day",15,11),
+   "brazil/republic":            FIXED("Republic Day",15,11),
+   "brazil/sao paulo":           FIXED("Sao Paulo Anniversary",25,1),
+   "brazil/tiradentes":          FIXED("Tiradentes Day",21,4),
+
+// "british virgin islands/sovereigns observance":occurs in June,
+   "british virgin islands/territory":FIXED("Territory Day",1,7),
+
+   "brunei/national":            FIXED("National Day",23,2),
+   "brunei/royal brunei armed forces":
+                                 FIXED("Royal Brunei Armed Forces Day",1,6),
+   "brunei/sultans":             FIXED("Sultan's Birthday",15,7),
+
+   "bulgaria/babin den":         FIXED("Babin Den",20,1),
+   "bulgaria/botev":             FIXED("Botev Day",20,5),
+   "bulgaria/education":         FIXED("Education Day",24,5),
+   "bulgaria/liberation":        FIXED("Liberation Day",3,3),
+   "bulgaria/national":          FIXED("National Day",3,3),
+   "bulgaria/national holiday":  FIX_M("National Holiday",9,9,2),
+   "bulgaria/viticulturists":    FIXED("Viticulturists' Day",14,2),
+
+   "burkina faso/anniversary of 1966 coup":
+                                 FIXED("Anniversary of 1966 Coup",3,1),
+   "burkina faso/labor":         FIXED("Labour Day",1,5),
+   "burkina faso/national":      FIXED("National Day",4,8),
+   "burkina faso/republic":      FIXED("Republic Day",11,12),
+   "burkina faso/youth":         FIXED("Youth Day",30,11),
+
+   "burundi/anniversary of the revolution":
+                                 FIXED("Anniversary of the Revolution",30,11),
+   "burundi/independence":       FIXED("Independence Day",1,7),
+   "burundi/murder of the hero": FIXED("Murder of the Hero Day",13,10),
+   "burundi/victory of uprona":  FIXED("Victory of Uprona Day",18,9),
+
+   "cambodia/ancestors":         FIXED("Feast of the Ancestors",22,9),
+// "cambodia/chaul chhnam":      occurs in April,
+   "cambodia/day of hatred":     FIXED("Day of Hatred",20,5),
+   "cambodia/independence":      FIXED("Independence Day",17,4),
+   "cambodia/khmer republic constitution":
+                                 FIXED("Khmer Republic Constitution Day",12,5),
+   "cambodia/memorial":          FIXED("Memorial Day",28,6),
+   "cambodia/national":          FIXED("National Day",7,1),
+// "cambodia/visak bauchea":     Vesak Day,
+
+   "cameroon/commemoration of national institutions":
+                      FIXED("Commemoration of National Institutions Day",10,5),
+   "cameroon/constitution":      FIXED("Constitution Day",20,5),
+   "cameroon/human rights":      FIXED("Human Rights Day",10,12),
+   "cameroon/independence":      FIXED("Independence Day",1,1),
+   "cameroon/unification":       FIXED("Unification Day",1,10),
+   "cameroon/youth":             FIXED("Youth Day",11,2),
+
+   "canada/civic holiday":       DWDRI("Civic Holiday",1,8,1,1),
+   "canada/discovery":           DWDRI("Discovery Day",24,6,1,0),
+   "canada/dominion":            FIXED("Dominion Day",1,7),
+   "canada/klondike gold discovery":
+    			         DWDR("Klondike Gold Discovery Day",18,8,5,-1),
+   "canada/labor":               DWDRI("Labor Day",1,9,1,1),
+   "canada/remembrance":         FIXED("Remembrance Day",11,11),
+// "canada/thanksgiving":
+//             usually in early October, and determined by annual proclamation,
+   "canada/victoria":            FIXED("Victoria Day",24,5),
+
+   "cape verde/independence":    FIXED("Independence Day",5,7),
+   "cape verde/national":        FIXED("National Day",12,9),
+   "cape verde/national heroes": FIXED("National Heroes' Day",20,1),
+
+   "caribbean/caricom":          DWDRI("CARICOM Day",1,7,1,1),
+   "caribbean/emancipation":     DWDRI("Emancipation Day",1,8,1,1),
+   "caribbean/schoelcher":       FIXED("Schoelcher Day",21,7),
+
+   "central african republic/first government":
+                                 FIXED("anniversary of first government",15,5),
+   "central african republic/republic":
+                 FIXED("Anniversary of the Proclamation of the Republic",1,12),
+   "central african republic/day after republic":
+                 FIXED("Day after Republic Day",2,12),
+   "central african republic/boganda":FIXED("Boganda Day",29,3),
+   "central african republic/independence":FIXED("Independence Day",13,8),
+   "central african republic/national holiday":FIXED("national holiday",11,11),
+   "central african republic/the after republic":
+                                 FIXED("the day after Republic Day",2,12),
+
+   "central america/independence":FIXED("Independence Day",15,9),
+
+   "chad/creation of the union of central african states":
+              FIXED("Creation of the Union of Central African States Day",2,4),
+   "chad/independence":          FIXED("Independence Day",11,8),
+   "chad/national":              FIXED("National Day",11,1),
+   "chad/republic":              FIXED("Republic Day",28,11),
+   "chad/traditional independence []":
+                                 FIXED("Traditional Independence Day []",11,8),
+
+   "chile/armed forces":         FIXED("Armed Forces Day",19,9),
+   "chile/independence":         FIXED("Independence Day",18,9),
+   "chile/independence2":        FIX_M("Independence Day",18,9,2),
+   "chile/national holiday":     FIXED("National Holiday",11,9),
+   "chile/navy":                 FIXED("Navy Day",21,5),
+
+// "china/army":
+//                 or <i>National Liberation Army Festival,</i> August 1, 1927,
+   "china/ccps":                 FIXED("The CCP's Birthday",1,7),
+   "china/childrens":            FIXED("Children's Day",1,6),
+   "china/national":             FIXED("National Day",1,10),
+   "china/teachers":             FIXED("Teacher's Day",1,9),
+   "china/tree planting":        FIXED("Tree Planting Day",1,4),
+   "china/youth":                FIXED("Youth Day",4,5),
+
+   "columbia/battle of boyaca":  FIXED("Battle of Boyaca Day",7,8),
+   "columbia/cartagena independence":FIXED("Cartagena Independence Day",11,11),
+   "columbia/independence":      FIXED("Independence Day",20,7),
+   "columbia/thanksgiving":      FIXED("Thanksgiving Day",5,6),
+
+   "comoros/anniversary of president abdallahs assassination":
+              FIXED("Anniversary of President Abdallah's Assassination",27,11),
+   "comoros/independence":       FIXED("Independence Day",6,7),
+
+   "congo/day before army":      FIXED("day before Army Day",16,11),
+   "congo/day before independence":FIXED("day before Independence Day",29,6),
+   "congo/day before national":  FIXED("day before national day",23,11),
+   "congo/independence":         FIXED("Independence Day",15,8),
+   "congo/martyr of independence":FIXED("Martyr of Independence Day",4,1),
+
+   "corsica/napoleons":          FIXED("Napoleon's Day",15,8),
+
+   "costa rica/battle of rivas": FIXED("Battle of Rivas Day",11,4),
+// "costa rica/guanacaste":      ,
+   "costa rica/independence":    FIXED("Independence Day",15,9),
+
+   "croatia/national holiday":   FIXED("National Holiday",22,6),
+   "croatia/republic":           FIXED("Republic Day",30,5),
+
+// "cuba/beginning of independence wars":commemorates Fidel Castro's guerrilla,
+   "cuba/independence":          FIXED("Independence Day",20,5),
+   "cuba/liberation":            FIXED("Liberation Day",1,1),
+   "cuba/revolution":            FIXED("Revolution Day",26,7),
+   "cuba/wars of independence":  FIXED("Wars of Independence Day",10,10),
+
+   "cyprus/green monday":        EASTER_REL("Green Monday",-41),
+   "cyprus/kataklysmos":         FIXED("Kataklysmos",7,6),
+   "cyprus/peace and freedom":   FIXED("Peace and Freedom Day",20,7),
+   "cyprus/submersion of the holy cross":
+                        FIXED("Feast of the Submersion of the Holy Cross",6,1),
+   "cyprus/communal resistance": FIXED("Communal Resistance Day",1,8),
+   "cyprus/greek national":      FIXED("Greek National Day",28,10),
+   "cyprus/name day":            FIXED("Name Day",19,1),
+
+   "czech republic/death of jan hus":FIXED("Death of Jan Hus",6,7),
+   "czech republic/introduction of christianity":
+                                 FIXED("Introduction of Christianity",5,7),
+
+   "czechoslovakia/resistance movement":FIXED("Resistance Movement Day",11,4),
+// "czechoslovakia/teachers":    ,
+
+   "denmark/birthday of queen margrethe ii":
+                                 FIXED("Birthday of Queen Margrethe II",16,4),
+   "denmark/common prayer":      EASTER_REL("Common Prayer Day",26),
+   "denmark/constitution":       FIXED("Constitution Day",5,6),
+   "denmark/fjortende februar":  FIXED("Fjortende Februar",14,2),
+   "denmark/liberation":         FIXED("Liberation Day",5,5),
+// "denmark/public holidays":    ,
+   "denmark/valdemars":          FIXED("Valdemar's Day",15,6),
+
+   "djibouti/independence feast":FIXED("Independence Feast Day",27,6),
+   "djibouti/workers":           FIXED("Workers' Day",1,5),
+
+   "dominica/community service": FIXED("Community Service Day",4,11),
+   "dominica/emancipation":      DWDRI("Emancipation Day",1,8,1,1),
+   "dominica/independence":      FIXED("Independence Day",3,11),
+
+   "ecuador/battle of pichincha ":FIXED("Battle of Pichincha  Day",24,5),
+// "ecuador/cuenca independence":
+//                            commemorates the declaration of independence for,
+   "ecuador/guayaquils independence":
+                                 FIXED("Guayaquil's Independence Day",9,10),
+// "ecuador/independence":       : August 10, 1809,
+   "ecuador/simon bolivars":     FIXED("Simon Bolivar's Birthday",24,7),
+
+   "egypt/armed forces":         FIXED("Armed Forces Day",6,10),
+   "egypt/evacuation":           FIXED("Evacuation Day",18,6),
+   "egypt/leylet en-nuktah":     FIXED("Leylet en-Nuktah",17,6),
+   "egypt/revolution":           FIXED("Revolution Day",23,7),
+   "egypt/sham al-naseem":       FIXED("Sham al-Naseem",21,3),
+   "egypt/sinai liberation":     FIXED("Sinai Liberation Day",25,4),
+   "egypt/suez":                 FIXED("Suez Day",24,10),
+   "egypt/victory":              FIXED("Victory Day",23,12),
+
+   "el salvador/first call for independence":
+                                 FIXED("First Call for Independence Day",5,11),
+   "el salvador/independence":   FIXED("Independence Day",15,9),
+   "el salvador/san salvador festival":FIX_M("San Salvador Festival",4,8,3),
+   "el salvador/schoolteachers": FIXED("Schoolteachers Day",22,6),
+
+   "equatorial guinea/armed forces":FIXED("Armed Forces Day",3,8),
+   "equatorial guinea/constitution":FIXED("Constitution Day",15,8),
+   "equatorial guinea/independence":FIXED("Independence Day",12,10),
+   "equatorial guinea/oau":      FIXED("OAU DAy",25,5),
+   "equatorial guinea/presidents":FIXED("President's Birthday",5,6),
+
+   "estonia/midsummer": 	 FIXED("Midsummer Day",24,6),
+   "estonia/victory":            FIXED("Victory Day",23,6),
+
+   "ethiopia/battle of aduwa":   FIXED("Battle of Aduwa Day",2,3),
+   "ethiopia/buhe":              FIXED("Buhe",19,8),
+   "ethiopia/epiphany":          FIXED("Epiphany",19,1),
+   "ethiopia/ethiopian new year":FIXED("Ethiopian New Year",11,9),
+   "ethiopia/genna":             FIXED("Genna",7,1),
+   "ethiopia/liberation":        FIXED("Liberation Day",5,5),
+   "ethiopia/martyrs":           FIXED("Martyrs' Day",19,2),
+   "ethiopia/meskel":            FIXED("Meskel",28,9),
+   "ethiopia/patriots victory":  FIXED("Patriots' Victory Day",6,4),
+   "ethiopia/popular revolution commemoration":
+                            FIXED("Popular Revolution Commemoration Day",12,9),
+   "ethiopia/revolution":        FIXED("Revolution Day",12,9),
+   "ethiopia/victory of adowa":  FIXED("Victory of Adowa",2,3),
+
+   "falkland islands/anniversary of the battle of the falkland islands":
+               FIXED("Anniversary of the Battle of the Falkland Islands",8,12),
+   "falkland islands/liberation":FIXED("Liberation Day",14,6),
+
+   "fiji/bank holiday":          DWDRI("Bank Holiday",1,8,1,1),
+// "fiji/deed of cession":       occurs near October 7,
+// "fiji/fiji2"                  on or near October 10,
+   "fiji/fiji":                  DWDRI("Fiji Day",1,8,1,2),
+   "fiji/prince charles":        DWDRI("Prince Charles Day",1,11,1,3),
+   "fiji/queens":                DWDRI("Queen's Birthday",1,6,1,2),
+
+   "finland/alexis kivi":        FIXED("Alexis Kivi Day",10,10),
+   "finland/flag":               FIXED("Flag Day",4,6),
+   "finland/flag of the army":   FIXED("Flag Day of the Army",19,5),
+// "finland/helsinki":           ,
+   "finland/independence":       FIXED("Independence Day",6,12),
+   "finland/kalevala":           FIXED("Kalevala Day",28,2),
+// "finland/midsummers eve":     WDREL("Midsummer's Eve","midsummers",5,-1),
+   "finland/runebergs":          FIXED("Runeberg's Day",5,2),
+   "finland/snellman":           FIXED("Snellman Day",12,5),
+   "finland/vappu":              FIXED("Vappu Day",1,5),
+   "finland/all saints":         DWDRI("All Saints Day",1,11,6,1),
+   "finland/midsummers eve":     DWDRI("Midsummer's Eve",24,6,5,0),
+   "finland/midsummer":          DWDRI("Midsummer's Day",25,6,6,0),
+
+   "france/ascension":           FIXED("Ascension Day",12,5),
+   "france/bastille":            FIXED("Bastille Day",14,7),
+   "france/d-day observance":    FIXED("D-Day Observance",6,6),
+   "france/fathers":             DWDRI("Father's Day",1,6,7,2),
+   "france/fete des saintes-maries":FIXED("F\352te des Saintes-Maries",24,5),
+   "france/fete nationale":      FIXED("F\352te Nationale",22,9),
+   "france/liberation":          FIXED("Liberation Day",8,5),
+   "france/marseillaise":        FIXED("Marseillaise Day",30,7),
+   "france/night watch":         FIXED("Night Watch",13,7),
+
+
+   "french polynesia/armistice": FIXED("Armistice Day",8,5),
+   "french polynesia/chinese new year":FIXED("Chinese New Year",6,2),
+   "french polynesia/missionaries arrival commemoration":
+                               FIXED("Missionaries Arrival Commemoration",5,3),
+
+   "gabon/constitution":         FIXED("Constitution Day",19,2),
+   "gabon/independence":         FIXED("Independence Day",17,8),
+   "gabon/renovation":           FIXED("Renovation Day",12,3),
+
+   "germany/day of repentance":  FIXED("Day of Repentance",18,11),
+   "germany/day of the workers": FIXED("Day of the Workers",1,5),
+   "germany/foundation":         FIXED("Foundation Day",7,10),
+   "germany/national":           FIXED("National Day",23,5),
+// "germany/oktoberfest":        occurs in Munich in September/October,
+   "germany/unity":              FIXED("Unity Day",3,10),
+   "germany/waldchestag":        EASTER_REL("Waldchestag",53),
+
+// "ghana/aboakyer":             occurs in April or May,
+   "ghana/homowo":               FIXED("Homowo",1,8),
+   "ghana/independence":         FIXED("Independence Day",6,3),
+   "ghana/liberation":           FIXED("Liberation Day",24,2),
+   "ghana/republic":             FIXED("Republic Day",1,7),
+   "ghana/revolution":           FIXED("Revolution Day",31,12),
+   "ghana/third republic":       FIXED("Third Republic Day",24,9),
+   "ghana/uprising":             FIXED("Uprising Day",4,6),
+
+   "gibraltar/commonwealth":     FIXED("Commonwealth Day",13,3),
+// "gibraltar/late summer bank holiday":occurs in the end of August,
+   "gibraltar/spring bank holiday":FIXED("Spring Bank Holiday",25,6),
+
+   "greece/clean monday":        EASTER_REL("Clean Monday",-41),
+// "greece/dumb week":           the week preceding Holy Week,
+   "greece/independence":        FIXED("Independence Day",25,3),
+   "greece/flower festival":
+                                 FIXED("Flower Festival",1,5),
+   "greece/midwifes":            FIXED("Midwife's Day",8,1),
+   "greece/ochi":                FIXED("Ochi Day",28,10),
+   "greece/saint basils":        FIXED("Saint Basil's Day",1,1),
+   "greece/dodecanese accession":FIXED("Dodecanese Accession Day",7,3),
+   "greece/liberation of xanthi":FIXED("Liberation of Xanthi",4,10),
+
+   "gregorian calendar /gregorian calendar":
+                                 FIXED("Gregorian Calendar Day",24,2),
+
+   "grenada/independence":       FIXED("Independence Day",7,2),
+   "grenada/national holiday":   FIXED("National Holiday",13,3),
+   "grenada/thanksgiving":       FIXED("Thanksgiving Day",25,10),
+
+   "guadeloupe/ascension":       FIXED("Ascension Day",12,5),
+
+   "guam/discovery":             FIXED("Discovery Day",6,3),
+   "guam/guam discovery":        DWDRI("Guam Discovery Day",1,3,1,1),
+   "guam/liberation":            FIXED("Liberation Day",21,7),
+
+   "guatemala/army":             FIXED("Army Day",30,6),
+   "guatemala/bank employees":   FIXED("Bank Employees' Day",1,7),
+   "guatemala/independence":     FIXED("Independence Day",15,9),
+   "guatemala/revolution":       FIXED("Revolution Day",30,6),
+
+   "guinea/anniversary of cmrn": FIXED("Anniversary of CMRN",3,4),
+   "guinea/anniversary of womens revolt":
+                                 FIXED("Anniversary of Women's Revolt",27,8),
+   "guinea/day of 1970 invasion":FIXED("Day of 1970 Invasion",22,11),
+   "guinea/independence":        FIXED("Independence Day",2,10),
+   "guinea/referendum":          FIXED("Referendum Day",28,9),
+
+   "guinea-bissau/colonization martyrs":FIXED("Colonization Martyr's Day",3,8),
+   "guinea-bissau/independence": FIXED("Independence Day",24,9),
+   "guinea-bissau/mocidade":     FIXED("Mocidade Day",1,12),
+   "guinea-bissau/national":     FIXED("National Day",12,9),
+   "guinea-bissau/national heroes":FIXED("National Heroes Day",20,1),
+   "guinea-bissau/readjustment movement":
+                                 FIXED("Readjustment Movement Day",14,11),
+
+   "guyana/freedom":             FIXED("Freedom Day",1,8),
+   "guyana/independence":        FIXED("Independence Day",26,5),
+   "guyana/republic":            FIXED("Republic Day",23,2),
+
+   "haiti/discovery":            FIXED("Discovery Day",5,12),
+   "haiti/vertieres":            FIXED("Verti\350res Day",18,11),
+
+   "honduras/armed forces":      FIXED("Armed Forces Day",21,10),
+   "honduras/independence":      FIXED("Independence Day",15,9),
+   "honduras/morazan":           FIXED("Moraz\341n Day",3,10),
+   "honduras/pan american":      FIXED("Pan American Day",14,4),
+   "honduras/thanksgiving":      FIXED("Thanksgiving Day",15,3),
+
+   "hong kong/birthday of confucious":FIXED("Birthday of Confucious",22,9),
+   "hong kong/birthday of pak tai":FIXED("Birthday of Pak Tai",3,4),
+// "hong kong/chung yeung festival":[9th day of 9th month],
+   "hong kong/half-year":        FIXED("Half-Year Day",1,7),
+   "hong kong/liberation":       DWDR("Liberation Day",1,9,1,-1),
+
+   "hungary/constitution":       FIXED("Constitution Day",20,8),
+   "hungary/revolution1848":     FIXED("1848 Revolution Day",15,3),
+   "hungary/revolution56":       FIXED("'56 Revolution Day",23,10),
+   "hungary/labor":              FIXED("Holiday of Labor",1,5),
+
+   "iceland/independence":       FIXED("Independence Day",17,6),
+
+   "india/indian independence":  FIXED("Indian Independence Day",15,8),
+   "india/mahatma gandhi jayanti":FIXED("Mahatma Gandhi Jayanti",2,10),
+   "india/mahatma gandhi martyrdom":FIXED("Mahatma Gandhi Martyrdom Day",30,1),
+   "india/republic":             FIXED("Republic Day",26,1),
+
+// "indonesia/balinese new year":held every 210 days,
+   "indonesia/independence":     FIXED("Independence Day",17,8),
+   "indonesia/kartini":          FIXED("Kartini Day",21,4),
+
+   "iran/constitution":          FIXED("Constitution Day",5,8),
+   "iran/islamic republic":      FIXED("Islamic Republic Day",1,4),
+   "iran/martyrdom of imam ali": FIXED("Martyrdom of Imam Ali",14,7),
+   "iran/no ruz":                FIXED("No Ruz",21,3),
+   "iran/oil nationalization":   FIXED("Oil Nationalization Day",20,3),
+   "iran/revolution":            FIXED("Revolution Day",11,2),
+   "iran/revolution2":           FIXED("Revolution Day",2,4),
+
+   "iraq/14 ramadan revolution": FIXED("14 Ramadan Revolution Day",8,2),
+   "iraq/army":                  FIXED("Army Day",6,1),
+   "iraq/july revolution":       FIXED("July Revolution Day",17,7),
+   "iraq/republic":              FIXED("Republic Day",14,7),
+
+   "ireland/sheelahs":           FIXED("Sheelah's Day",18,3),
+
+   "israel/balfour declaration": FIXED("Balfour Declaration Day",2,11),
+// "israel/hebrew university":   occurs near April 1,
+// "israel/holocaust memorial":  Nisan 27,
+// "israel/independence":        Iyar 5,
+   "israel/jerusalem reunification":FIXED("Jerusalem Reunification Day",12,5),
+// "israel/national":            occurs in May,
+
+   "italy/anniversary of the republic":
+                                 FIXED("Anniversary of the Republic",2,6),
+   "italy/befana":               FIXED("Befana Day",6,1),
+   "italy/day of conciliation":  FIXED("Day of Conciliation",11,2),
+   "italy/festa del redentore":  DWDRI("Festa del Redentore",1,7,7,3),
+   "italy/joust of the quintana":DWDRI("Joust of the Quintana",1,8,7,1),
+   "italy/liberation":           FIXED("Liberation Day",25,4),
+   "italy/natale di roma":       FIXED("Natale di Roma",21,4),
+   "italy/palio del golfo":      DWDRI("Palio Del Golfo",1,8,7,2),
+// "italy/saint marks":          occurs in April,
+   "italy/santo stefano":        FIXED("Santo Stefano",26,12),
+
+   "ivory coast/independence":   FIXED("Independence Day",7,12),
+   "ivory coast/national holiday of the ivory coast":
+                             FIXED("National Holiday of the Ivory Coast",7,12),
+
+// "jainism/jain payushan":      began on 9/2/94 and 8/23/95,
+// "jainism/mahavir jayanti":    Vaisakha 13,
+
+   "jamaica/heroes":             DWDRI("Heroes' Day",1,10,1,3),
+   "jamaica/independence":       DWDRI("Independence Day",1,8,1,1),
+   "jamaica/labor":              FIXED("Labour Day",23,5),
+
+   "japan/adults":               FIXED("Adults Day",15,1),
+// "japan/autumnal equinox":     [sep 22nd or 23rd],
+   "japan/bean-throwing festival":FIXED("Bean-Throwing Festival",4,2),
+// "japan/black ship":           near July 15,
+// "japan/bon":                  occurs between July 13 and 15,
+   "japan/childrens":            FIXED("Children's Day",5,5),
+   "japan/childrens protection": FIXED("Children's Protection Day",17,4),
+   "japan/constitution":         FIXED("Constitution Day",3,5),
+   "japan/culture":              FIXED("Culture Day",3,11),
+   "japan/emperors":             FIXED("Emperor's Birthday",23,12),
+   "japan/empire":               FIXED("Empire Day",11,2),
+   "japan/gion matsuri":         FIX_M("Gion Matsuri",16,2,9),
+   "japan/greenery":             FIXED("Greenery Day",29,4),
+// "japan/health":               <i>Sports Day,</i> October 10,
+   "japan/hina matsuri":         FIXED("Hina Matsuri",3,3),
+   "japan/hiroshima peace festival":FIXED("Hiroshima Peace Festival",6,8),
+   "japan/hollyhock festival":   FIXED("Hollyhock Festival",15,5),
+   "japan/jidai matsuri":        FIXED("Jidai Matsuri",22,10),
+   "japan/kakizome":             FIXED("Kakizome",2,1),
+   "japan/kambutsue":            FIXED("Kambutsue",8,4),
+   "japan/kite battles of hamamatsu":FIX_M("Kite Battles of Hamamatsu",3,5,3),
+   "japan/labor thanksgiving":   FIXED("Labor Thanksgiving Day",23,11),
+   "japan/martyr":               FIXED("Martyr Day",5,2),
+// "japan/memorial":             ,
+   "japan/memorial to broken dolls":FIXED("Memorial to Broken Dolls Day",3,6),
+   "japan/national foundation":  FIXED("National Foundation Day",11,2),
+// "japan/peoples holiday":      [near may 4?],
+   "japan/respect for the aged": FIXED("Respect for the Aged Day",15,9),
+   "japan/sanno matsuri":        FIXED("Sanno Matsuri",15,6),
+// "japan/shichigosan":          The name means "seven-five-three",
+   "japan/shigoto hajime":       FIXED("Shigoto Hajime",2,1),
+   "japan/tanabata":             FIXED("Tanabata",7,7),
+   "japan/tango-no-sekku":       FIXED("Tango-no-sekku",5,5),
+// "japan/vernal equinox":       [mar 20 or mar 21st],
+
+   "jordan/arbor":               FIXED("Arbor Day",15,1),
+   "jordan/coronation":          FIXED("Coronation Day",11,8),
+   "jordan/independence":        FIXED("Independence Day",25,5),
+   "jordan/king hussein":        FIXED("King Hussein Day",14,11),
+
+   "kenya/independence":         FIXED("Independence Day",12,12),
+   "kenya/kenyatta":             FIXED("Kenyatta Day",20,10),
+   "kenya/madaraka":             FIXED("Madaraka Day",1,6),
+
+   "kiribati/independence":      FIXED("Independence Day",12,7),
+   "kiribati/youth":             FIXED("Youth Day",4,8),
+
+   "korea/independence movement":FIXED("Independence Movement Day",1,3),
+
+   "kuwait/independence":        FIXED("Independence Day",19,6),
+   "kuwait/national":            FIXED("National Day",25,2),
+
+// "laos/army":                  occurs around March 24,
+   "laos/constitution":          FIXED("Constitution Day",11,5),
+   "laos/independence":          FIXED("Independence Day",19,7),
+   "laos/memorial":              FIXED("Memorial Day",15,8),
+   "laos/pathet lao":            FIXED("Pathet Lao Day",6,1),
+   "laos/republic":              FIXED("Republic Day",2,12),
+
+   "latvia/independence":        FIXED("Independence Day",18,11),
+   "latvia/midsummer festival":  FIX_M("Midsummer Festival",23,6,2),
+
+   "lebanon/evacuation":         FIXED("Evacuation Day",31,12),
+   "lebanon/independence":       FIXED("Independence Day",22,11),
+   "lebanon/martyrs":            FIXED("Martyrs' Day",6,5),
+   "lebanon/saint maron":        FIXED("Saint Maron Day",9,2),
+
+   "lesotho/family":             DWDRI("Family Day",1,7,1,1),
+   "lesotho/independence":       FIXED("Independence Day",4,10),
+   "lesotho/kings":              FIXED("King's Birthday",2,5),
+   "lesotho/moshoeshoes":        FIXED("Moshoeshoe's Day",12,3),
+   "lesotho/national holiday":   FIXED("National Holiday",28,1),
+   "lesotho/national sports":    FIXED("National Sports Day",6,10),
+   "lesotho/national tree planting":FIXED("National Tree Planting Day",21,3),
+
+   "liberia/armed forces":       FIXED("Armed Forces Day",11,2),
+   "liberia/decoration":         FIXED("Decoration Day",13,3),
+   "liberia/fast and prayer":    FIXED("Fast and Prayer Day",11,4),
+   "liberia/flag":               FIXED("Flag Day",24,8),
+   "liberia/independence":       FIXED("Independence Day",26,7),
+   "liberia/j j roberts":        FIXED("J. J. Robert's Birthday",15,3),
+   "liberia/literacy":           FIXED("Literacy Day",14,2),
+   "liberia/matilda newport":    FIXED("Matilda Newport Day",1,12),
+   "liberia/memorial":           FIXED("Memorial Day",12,11),
+   "liberia/national redemption":FIXED("National Redemption Day",12,4),
+   "liberia/pioneers":           FIXED("Pioneers' Day",7,1),
+   "liberia/president tubmans":  FIXED("President Tubman's Birthday",29,11),
+   "liberia/thanksgiving":       DWDRI("Thanksgiving Day",1,11,4,1),
+   "liberia/unification and integration":
+                                 FIXED("Unification and Integration Day",14,5),
+
+   "libya/evacuation":           FIXED("Evacuation Day",28,3),
+   "libya/expulsion of the fascist settlers":
+                           FIXED("Expulsion of the Fascist Settlers Day",7,10),
+   "libya/kings":                FIXED("King's Birthday",12,3),
+   "libya/national":             FIXED("National Day",1,9),
+   "libya/revolution":           FIXED("Revolution Day",1,9),
+   "libya/sanusi army":          FIXED("Sanusi Army Day",9,8),
+// "libya/troop withdrawal":     near June 30,
+
+   "liechtenstein/birthday of prince franz-josef ii":
+                               FIXED("Birthday of Prince Franz-Josef II",16,8),
+   "liechtenstein/national":     FIXED("National Day",15,8),
+
+   "lithuania/coronation":       FIXED("Coronation Day",6,7),
+   "lithuania/independence":     FIXED("Independence Day",16,2),
+   "lithuania/mourning":         FIXED("Mourning",1,11),
+
+   "luxembourg/burgsonndeg":     FIXED("Burgsonndeg",28,2),
+   "luxembourg/grand duchess":   FIXED("Grand Duchess' Birthday",23,1),
+   "luxembourg/liberation":      FIXED("Liberation Day",9,9),
+   "luxembourg/national":        FIXED("National Day",23,6),
+
+   "macao/anniversary of the portugese revolution":
+                         FIXED("Anniversary of the Portugese Revolution",25,4),
+   "macao/battle of july 13":    FIXED("Feast of the Battle of July 13",13,7),
+// "macao/hungry ghosts":        occurs in August,
+   "macao/procession of our lady of fatima":
+                                FIXED("Procession of Our Lady of Fatima",13,5),
+   "macao/republic":             FIXED("Republic Day",5,10),
+
+   "madagascar/commemoration":   FIXED("Commemoration Day",29,3),
+   "madagascar/independence":    FIXED("Independence Day",26,6),
+   "madagascar/republic":        FIXED("Republic Day",30,12),
+
+   "malawi/august holiday":      FIXED("August Holiday",6,8),
+   "malawi/kamuzu":              FIXED("Kamuzu Day",14,5),
+   "malawi/martyrs":             FIXED("Martyrs' Day",3,3),
+   "malawi/mothers":             FIXED("Mother's Day",17,10),
+   "malawi/national tree-planting":FIXED("National Tree-Planting Day",21,12),
+   "malawi/republic":            FIXED("Republic Day",6,7),
+
+// "malaysia/additional public holiday in kuala lumpur":City Day (Feb 1),
+   "malaysia/kings":             FIXED("King's Birthday",3,6),
+   "malaysia/malaysia":          FIXED("Malaysia Day",31,8),
+
+   "maldives/fisheries":         FIXED("Fisheries Day",10,12),
+   "maldives/independence":      FIXED("Independence Day",26,7),
+   "maldives/national":          FIXED("National Day",7,1),
+   "maldives/republic":          FIXED("Republic Day",11,11),
+   "maldives/victory":           FIXED("Victory Day",3,11),
+
+   "mali/army":                  FIXED("Army Day",20,1),
+   "mali/independence":          FIXED("Independence Day",22,9),
+   "mali/liberation":            FIXED("Liberation Day",19,11),
+
+   "malta/freedom":              FIXED("Freedom Day",31,3),
+   "malta/independence":         FIXED("Independence Day",21,9),
+   "malta/memorial of 1919 riot":FIXED("Memorial of 1919 riot",7,6),
+   "malta/republic":             FIXED("Republic Day",13,12),
+
+   "marshall islands/proclamation of the republic of marshall islands":
+                 FIXED("Proclamation of the Republic of Marshall Islands",1,5),
+
+   "martinique/ascension":       FIXED("Ascension Day",12,5),
+
+   "mauritania/independence":    FIXED("Independence Day",28,11),
+
+   "mauritius/independence":     FIXED("Independence Day",12,3),
+
+   "mexico/birthday of benito juarez":
+                                 FIXED("Birthday of Benito Ju\341rez",21,3),
+   "mexico/cinco de mayo":       FIXED("Cinco de Mayo",5,5),
+   "mexico/constitution":        FIXED("Constitution Day",5,2),
+   "mexico/day of mourning":     FIXED("Day of Mourning",17,7),
+   "mexico/dia de la raza":      FIXED("Dia de la Raza",12,10),
+   "mexico/holy cross":          FIXED("Holy Cross Day",3,5),
+   "mexico/independence":        FIXED("Independence Day",16,9),
+   "mexico/night of the radishes":FIXED("Night of the Radishes",23,12),
+   "mexico/our lady of guadalupe":
+                                 FIXED("Feast of Our Lady of Guadalupe",12,12),
+   "mexico/posadass":            FIX_M("Posadas Days",16,12,9),
+   "mexico/presidential message":FIXED("Presidential Message Day",1,9),
+   "mexico/revolution":          FIXED("Revolution Day",20,11),
+   "mexico/san marc\363s":       FIXED("San Marc\363s Day",25,4),
+
+// "micronesia/national holiday":,
+
+   "monaco/monaco national festival":FIXED("Monaco National Festival",19,11),
+
+   "mongolia/national":          FIXED("National Day",11,7),
+   "mongolia/republic":          FIXED("Republic Day",26,11),
+
+   "montserrat/festival":        FIXED("Festival Day",31,12),
+   "montserrat/liberation":      FIXED("Liberation Day",23,11),
+
+   "mormonism/founding of the mormon church":
+                                 FIXED("Founding of the Mormon Church",6,4),
+
+   "morocco/green march":        FIXED("Green March",6,11),
+   "morocco/independence":       FIXED("Independence Day",2,3),
+   "morocco/oued ed-dahab":      FIXED("Oued ed-Dahab Day",14,8),
+   "morocco/throne":             FIXED("Throne Day",3,3),
+
+   "mozambique/armed forces":    FIXED("Armed Forces Day",25,9),
+   "mozambique/heroes":          FIXED("Heroes' Day",3,2),
+   "mozambique/independence":    FIXED("Independence Day",25,6),
+   "mozambique/lusaka agreement":FIXED("Lusaka Agreement Day",7,9),
+   "mozambique/universal fraternity":FIXED("Universal Fraternity Day",1,1),
+   "mozambique/womens":          FIXED("Women's Day",7,4),
+   "mozambique/workers":         FIXED("Workers' Day",1,5),
+
+   "myanmar/armed forces":       FIXED("Armed Forces Day",27,3),
+// "myanmar/burmese new year":   near April 17,
+   "myanmar/independence":       FIXED("Independence Day",4,1),
+   "myanmar/martyrs":            FIXED("Martyrs' Day",19,7),
+   "myanmar/national":           FIXED("National Day",10,12),
+   "myanmar/peasants":           FIXED("Peasants' Day",2,3),
+   "myanmar/resistance":         FIXED("Resistance Day",27,3),
+   "myanmar/union":              FIXED("Union Day",12,2),
+
+   "namibia/casinga":            FIXED("Casinga Day",4,5),
+   "namibia/day of goodwill":    FIXED("Day of Goodwill",7,10),
+   "namibia/family":             FIXED("Family Day",26,12),
+   "namibia/heroes":             FIXED("Heroes' Day",26,8),
+   "namibia/independence":       FIXED("Independence Day",21,3),
+   "namibia/workers":            FIXED("Workers' Day",1,5),
+
+   "nauru/angam":                FIXED("Angam Day",27,10),
+   "nauru/independence":         FIXED("Independence Day",31,1),
+
+   "nepal/birthday of king birendra":FIXED("Birthday of King Birendra",28,12),
+// "nepal/buddha jayanti":       occurs in May,
+   "nepal/constitution":         FIXED("Constitution Day",16,12),
+   "nepal/democracy":            FIXED("Democracy Day",18,2),
+   "nepal/independence":         FIXED("Independence Day",21,12),
+   "nepal/kings":                FIXED("King's Birthday",28,12),
+   "nepal/national unity":       FIXED("National Unity Day",11,1),
+   "nepal/queens":               FIXED("Queen's Birthday",8,11),
+   "nepal/tij":                  FIXED("Tij Day",8,8),
+
+   "netherlands/beggars":        FIXED("Beggar's Day",11,11),
+   "netherlands/independence":   FIXED("Independence Day",25,7),
+   "netherlands/liberation":     FIXED("Liberation Day",5,5),
+   "netherlands/queens":         FIXED("Queen's Day",30,4),
+   "netherlands/sinterklaas":    FIXED("Sinterklaas",6,12),
+
+   "netherlands antilles/bonaire":FIXED("Bonaire Day",6,9),
+   "netherlands antilles/cura\347ao":FIXED("Cura\347ao Day",2,7),
+   "netherlands antilles/queens":FIXED("Queen's Birthday",30,4),
+   "netherlands antilles/saba":  FIXED("Saba Day",6,12),
+   "netherlands antilles/saint eustatius":FIXED("St Eustatius Day",16,11),
+   "netherlands antilles/saint maarten":FIXED("St Maarten Day",11,11),
+
+   "new zealand/labor":          DWDR("Labor Day",1,11,1,-1),
+   "new zealand/queens":         FIXED("Queen's Birthday",4,6),
+   "new zealand/waitangi":       FIXED("Waitangi Day",6,2),
+
+   "nicaragua/air force":        FIXED("Air Force Day",1,2),
+   "nicaragua/army":             FIXED("Army Day",27,5),
+   "nicaragua/fiesta":           FIXED("Fiesta Day",1,8),
+   "nicaragua/independence":     FIXED("Independence Day",15,9),
+   "nicaragua/revolution":       FIXED("Revolution Day",19,7),
+   "nicaragua/san jacinto":      FIXED("San Jacinto Day",14,9),
+
+   "niger/independence":         FIXED("Independence Day",3,8),
+   "niger/national":             FIXED("National Day",15,4),
+   "niger/republic":             FIXED("Republic Day",18,12),
+
+   "nigeria/childrens":          FIXED("Children's Day",27,5),
+   "nigeria/harvest festival":   FIXED("Harvest Festival",12,10),
+   "nigeria/national":           FIXED("National Day",1,10),
+// "nigeria/odum titun":         occurs in the winter,
+// "nigeria/odun kekere":        occurs at the end of Ramadan,
+
+   "northern mariana islands/commonwealth":FIXED("Commonwealth Day",3,1),
+   "northern mariana islands/presidents":FIXED("Presidents Day",13,2),
+
+   "norway/constitution":        FIXED("Constitution Day",17,5),
+   "norway/olsok eve festival":  FIXED("Olsok Eve Festival",29,7),
+   "norway/tyvendedagen":        FIXED("Tyvendedagen",13,1),
+
+   "oman/national":              FIXED("National Day",23,7),
+   "oman/national of oman":      FIXED("National Day of Oman",18,11),
+   "oman/national2":             FIXED("National Day",18,11),
+   "oman/sultans":               FIXED("Sultan's Birthday",19,11),
+
+   "pakistan/birthday of quaid-i-azam":FIXED("Birthday of Quaid-i-Azam",25,12),
+   "pakistan/defense":           FIXED("Defense Day",6,9),
+   "pakistan/independence":      FIXED("Independence Day",14,8),
+   "pakistan/iqbal":             FIXED("Iqbal Day",9,11),
+   "pakistan/jinnah":            FIXED("Jinnah Day",11,9),
+   "pakistan/pakistan":          FIXED("Pakistan Day",23,3),
+
+   "panama/constitution":        FIXED("Constitution Day",1,3),
+   "panama/day of mourning":     FIXED("Day of Mourning",9,1),
+   "panama/festival of the black christ":
+                                 FIXED("Festival of the Black Christ",21,10),
+   "panama/flag":                FIXED("Flag Day",4,11),
+   "panama/foundation of panama city":FIXED("Foundation of Panama City",15,8),
+   "panama/independence":        FIXED("Independence Day",3,11),
+   "panama/independence from spain":FIXED("Independence from Spain",28,11),
+   "panama/mothers":             FIXED("Mothers' Day",8,12),
+   "panama/national anthem":     FIXED("National Anthem Day",1,11),
+   "panama/revolution":          FIXED("Revolution Anniversary Day",11,10),
+   "panama/uprising of los santos":FIXED("Uprising of Los Santos",10,11),
+
+   "papua new guinea/independence":FIXED("Independence Day",16,9),
+   "papua new guinea/remembrance":FIXED("Remembrance Day",23,7),
+
+   "paraguay/battle of boquer\363n":FIXED("Battle of Boquer\363n Day",29,9),
+   "paraguay/constitution":      FIXED("Constitution Day",25,8),
+   "paraguay/day of the race":   FIXED("Day of the Race",12,10),
+   "paraguay/founding of the city of asunci\363n":
+                             FIXED("Founding of the City of Asunci\363n",15,8),
+   "paraguay/heroes":            FIXED("Heroes' Day",1,3),
+   "paraguay/independence":      FIX_M("Independence Day",14,5,2),
+   "paraguay/peace of chaco":    FIXED("Peace of Chaco Day",12,6),
+   "paraguay/virgin of caacupe": FIXED("Virgin of Caacupe",8,12),
+
+   "peru/combat of angamos":     FIXED("Combat of Angamos",8,10),
+   "peru/independence":          FIX_M("Independence Day",28,7,2),
+   "peru/inti raymi fiesta":     FIXED("Inti Raymi Fiesta",24,6),
+   "peru/santa rosa de lima":    FIXED("Santa Rosa de Lima",30,8),
+
+   "philippines/araw ng kagitingan":FIXED("Araw ng Kagitingan",6,5),
+   "philippines/barangay":       FIXED("Barangay Day",11,9),
+   "philippines/bataan":         FIXED("Bataan Day",9,4),
+   "philippines/bonifacio":      FIXED("Bonifacio Day",30,11),
+   "philippines/christ the king":FIXED("Feast of Christ the King",24,10),
+   "philippines/constitution":   FIXED("Constitution Day",17,1),
+   "philippines/freedom":        FIXED("Freedom Day",25,2),
+   "philippines/independence":   FIXED("Independence Day",12,6),
+   "philippines/misa de gallo":  FIX_M("Misa de Gallo",16,12,9),
+   "philippines/national heroes":FIXED("National Heroes' Day",27,8),
+   "philippines/philippine-american friendship":
+                               FIXED("Philippine-American Friendship Day",4,7),
+   "philippines/rizal":          FIXED("Rizal Day",30,12),
+   "philippines/thanksgiving":   FIXED("Thanksgiving Day",21,9),
+
+   "portugal/cam\365es memorial":FIXED("Cam\365es Memorial Day",10,6),
+   "portugal/christmas lisbon also observes the st anthony":
+         FIXED("Christmas. Lisbon also observes the feast of St Anthony",13,6),
+   "portugal/day of the dead":   FIXED("Day of the Dead",2,11),
+   "portugal/liberty":           FIXED("Liberty Day",25,4),
+   "portugal/portugal":          FIXED("Portugal Day",10,6),
+   "portugal/republic":          FIXED("Republic Day",5,10),
+   "portugal/restoration of the independence":
+                                 FIXED("Restoration of the Independence",1,12),
+
+   "puerto rico/barbosa":        FIXED("Barbosa Day",27,7),
+   "puerto rico/birthday of eugenio maria de hostos":
+                             FIXED("Birthday of Eugenio Maria de Hostos",11,1),
+   "puerto rico/constitution":   FIXED("Constitution Day",25,7),
+   "puerto rico/de diego":       FIXED("De Diego Day",16,4),
+   "puerto rico/discovery":      FIXED("Discovery Day",19,11),
+   "puerto rico/emancipation":   FIXED("Emancipation Day",22,3),
+   "puerto rico/memorial":       FIXED("Memorial Day",28,5),
+   "puerto rico/mu\361oz rivera":FIXED("Mu\361oz Rivera Day",17,7),
+   "puerto rico/ponce de leon":  FIXED("Ponce de Leon Day",12,8),
+   "puerto rico/saint johns":    FIXED("St John's Day",24,6),
+   "puerto rico/san juan":       FIXED("San Juan Day",24,6),
+
+   "qatar/anniversary of the amirs accession":
+                             FIXED("Anniversary of the Amir's Accession",22,2),
+   "qatar/independence":         FIXED("Independence Day",3,9),
+
+   "romania/liberation":         FIXED("Liberation Day",23,8),
+   "romania/national":           FIXED("National Day",1,12),
+   "romania/public holiday":     FIX_M("Public Holiday",23,8,2),
+
+   "rwanda/armed forces":        FIXED("Armed Forces Day",26,10),
+   "rwanda/democracy":           FIXED("Democracy Day",28,1),
+   "rwanda/independence":        FIXED("Independence Day",1,7),
+   "rwanda/kamarampaka":         FIXED("Kamarampaka Day",25,9),
+   "rwanda/peace and unity":     FIXED("Peace and Unity Day",5,7),
+
+   "saint kitts and nevis/carnival":FIXED("Carnival",31,12),
+   "saint kitts and nevis/independence":FIXED("Independence Day",19,9),
+   "saint kitts and nevis/prince of wales":
+                                 FIXED("Prince of Wales' Birthday",14,11),
+
+   "saint lucia/discovery":      FIXED("Discovery Day",13,12),
+   "saint lucia/independence":   FIXED("Independence Day",22,2),
+   "saint lucia/thanksgiving":   DWDRI("Thanksgiving Day",1,10,1,1),
+
+   "saint vincent and the grenadines/independence":
+                                 FIXED("Independence Day",27,10),
+   "saint vincent and the grenadines/saint vincent and the grenadines":
+                            FIXED("Saint Vincent and the Grenadines Day",22,1),
+
+   "san marino/anniversary of the arengo":
+                                 FIXED("Anniversary of the Arengo",25,3),
+   "san marino/fall of fascism": FIXED("Fall of Fascism Day",28,7),
+   "san marino/investiture of the new captains regent":
+                           FIXED("Investiture of the New Captains Regent",1,4),
+   "san marino/investiture of the new captains-regent":
+                          FIXED("Investiture of the New Captains-Regent",1,10),
+   "san marino/liberation":      FIXED("Liberation Day",5,2),
+   "san marino/national":        FIXED("National Day",1,4),
+   "san marino/san marino":      FIXED("San Marino Day",3,9),
+
+   "sao tome and principe/farmers":FIXED("Farmers' Day",30,9),
+   "sao tome and principe/independence":FIXED("Independence Day",12,7),
+   "sao tome and principe/martyrs":FIXED("Martyrs' Day",4,2),
+   "sao tome and principe/transitional government":
+                                 FIXED("Transitional Government Day",21,12),
+
+   "saudi arabia/national":      FIXED("National Day",12,9),
+   "saudi arabia/national of saudi arabia":
+                                 FIXED("National Day of Saudi Arabia",23,9),
+
+   "senegal/african community":  FIXED("African Community Day",14,7),
+   "senegal/independence":       FIXED("Independence Day",4,4),
+
+   "seychelles/independence":    FIXED("Independence Day",29,6),
+   "seychelles/liberation":      FIXED("Liberation Day",5,6),
+
+   "sierra leone/independence":  FIXED("Independence Day",27,4),
+   "sierra leone/republic":      FIXED("Republic Day",19,4),
+
+// "singapore/birthday of the monkey god":
+//                               occurs in February and September/October,
+// "singapore/birthday of the saint of the poor":occurs in March,
+   "singapore/independence":     FIXED("Independence Day",16,9),
+   "singapore/labor":            FIXED("Labour Day",1,5),
+// "singapore/mooncake festival":occurs in September,
+   "singapore/national holiday": FIXED("National Holiday",9,8),
+// "singapore/vesak":            occurs in May,
+
+   "slovakia/day of the slav apostles":FIXED("Day of the Slav Apostles",5,7),
+   "slovakia/liberation":        FIXED("Liberation Day",8,5),
+   "slovakia/reconciliation":    FIXED("Reconciliation Day",1,11),
+   "slovakia/slovak national uprising":
+                                 FIXED("Slovak National Uprising Day",29,8),
+
+   "solomon islands/independence":FIXED("Independence Day",7,7),
+
+   "somalia/foundation of the republic":
+                                 FIXED("Foundation of the Republic Day",1,7),
+   "somalia/independence":       FIXED("Independence Day",26,6),
+   "somalia/revolution":         FIX_M("Revolution Anniversary",21,10,2),
+
+   "south africa/day of the vow":FIXED("Day of the Vow",16,12),
+   "south africa/family":        DWDRI("Family Day",1,7,1,2),
+   "south africa/kruger":        FIXED("Kruger Day",10,10),
+   "south africa/republic":      FIXED("Republic Day",31,5),
+   "south africa/settlers":      DWDRI("Settlers' Day",1,9,1,1),
+   "south africa/van riebeeck":  FIXED("Van Riebeeck Day",6,4),
+   "south africa/workers":       FIXED("Workers' Day",1,5),
+
+   "soviet union/anniversary of the october socialist revolution":
+               FIX_M("Anniversary of the October Socialist Revolution",7,11,2),
+   "soviet union/victory":       FIXED("Victory Day",9,5),
+
+   "spain/constitution":         FIXED("Constitution Day",6,12),
+   "spain/fiesta de san fermin": FIXED("Fiesta de San Fermin",7,7),
+   "spain/fiesta del arbol":     FIXED("Fiesta del Arbol",26,3),
+   "spain/grenada":              FIXED("Grenada Day",2,1),
+   "spain/hispanidad":           FIXED("Hispanidad Day",12,10),
+   "spain/king juan carlos saints":FIXED("King Juan Carlos' Saint's Day",24,6),
+   "spain/labor":                FIXED("Labor Day",18,7),
+   "spain/national":             FIXED("National Day",12,10),
+   "spain/national holiday of spain":FIXED("National Holiday of Spain",12,10),
+   "spain/queen isabella":       FIXED("Queen Isabella Day",22,4),
+   "spain/saint james":          FIXED("St James Day",25,7),
+   "spain/saint joseph the workman":FIXED("St Joseph the Workman",1,5),
+// "spain/tomatina":             late August,
+
+// "sri lanka/bandaranaike memorial":[9/26/96],
+// "sri lanka/hadji festival":   [4/29/96],
+   "sri lanka/independence":     FIXED("Independence Day",4,2),
+// "sri lanka/kandy perahera":   occurs on a new moon in July,
+   "sri lanka/national heroes":  FIXED("National Heroes Day",22,5),
+   "sri lanka/republic":         FIXED("Republic Day",22,5),
+   "sri lanka/sinhala and tamil new year":
+                                 FIXED("Sinhala and Tamil New Year",14,4),
+// "sri lanka/thai pongal":      occurs in January,
+// "sri lanka/vesak festival":   occurs in May,
+
+   "sudan/decentralization":     FIXED("Decentralization Day",1,7),
+   "sudan/independence":         FIXED("Independence Day",1,1),
+   "sudan/national":             FIXED("National Day",25,5),
+   "sudan/unity":                FIXED("Unity Day",3,3),
+   "sudan/uprising":             FIXED("Uprising Day",6,4),
+
+   "suriname/independence":      FIXED("Independence Day",25,11),
+   "suriname/national union":    FIXED("National Union Day",1,7),
+   "suriname/revolution":        FIXED("Revolution Day",25,2),
+
+   "swaziland/commonwealth":     DWDRI("Commonwealth Day",1,3,1,2),
+   "swaziland/flag":             FIXED("Flag Day",25,4),
+// "swaziland/incwala":          December or January,
+   "swaziland/kings":            FIXED("King's Birthday",22,7),
+   "swaziland/reed dance":       DWDRI("Reed Dance Day",1,7,1,2),
+   "swaziland/somhlolo":         FIXED("Somhlolo Day",6,9),
+
+   "switzerland/berchtolds":     FIXED("Berchtold's Day",2,1),
+   "switzerland/glarus festival":DWDRI("Glarus Festival",1,4,4,1),
+   "switzerland/homstrom":       DWDRI("Homstrom",1,2,7,1),
+   "switzerland/independence":   FIXED("Independence Day",1,8),
+   "switzerland/may eve":        FIXED("May Day Eve",30,4),
+
+   "syria/beginning of october war":FIXED("Beginning of October War",6,10),
+   "syria/evacuation":           FIXED("Evacuation Day",17,4),
+   "syria/national":             FIXED("National Day",16,11),
+   "syria/revolution":           FIXED("Revolution Day",8,3),
+   "syria/union":                FIXED("Union Day",1,9),
+
+   "taiwan/birthday of confucious":FIXED("Birthday of Confucious",28,9),
+// "taiwan/birthday of matsu":   occurs in April or May,
+   "taiwan/buddha bathing festival":FIXED("Buddha Bathing Festival",8,4),
+   "taiwan/chiang kai-shek":     FIXED("Chiang Kai-shek Day",1,11),
+   "taiwan/childrens":           FIXED("Children's Day",4,4),
+   "taiwan/constitution":        FIXED("Constitution Day",25,12),
+   "taiwan/dragon boat festival":FIXED("Dragon Boat Festival",8,6),
+   "taiwan/founding of the republic of china":
+                              FIX_M("Founding of the Republic of China",1,1,2),
+// "taiwan/lantern festival":    occurs on the fifteenth day of the first moon,
+   "taiwan/martyrs":             FIXED("Martyrs' Day",29,3),
+   "taiwan/national":            FIXED("National Day",10,10),
+   "taiwan/restoration":         FIXED("Restoration Day",25,10),
+   "taiwan/sun yat-sen":         FIXED("Sun Yat-sen Day",12,11),
+   "taiwan/youth":               FIXED("Youth Day",29,3),
+
+   "tanzania/chama cha mapinduzi":FIXED("Chama Cha Mapinduzi Day",5,2),
+   "tanzania/heroes":            FIXED("Heroes' Day",1,9),
+   "tanzania/independence":      FIXED("Independence Day",9,12),
+   "tanzania/naming":            FIXED("Naming Day",29,10),
+   "tanzania/saba saba":         FIXED("Saba Saba Day",7,7),
+   "tanzania/sultans":           FIXED("Sultan's Birthday",26,8),
+   "tanzania/union":             FIXED("Union Day",26,4),
+   "tanzania/zanzibar revolution":FIXED("Zanzibar Revolution Day",12,1),
+
+   "thailand/asalapha bupha":    FIXED("Asalapha Bupha Day",28,7),
+   "thailand/chakri":            FIXED("Chakri Day",6,4),
+   "thailand/chulalongkorn":     FIXED("Chulalongkorn Day",23,10),
+   "thailand/constitution":      FIXED("Constitution Day",10,12),
+   "thailand/coronation":        FIXED("Coronation Day",5,5),
+   "thailand/harvest festival":  FIXED("Harvest Festival Day",11,5),
+   "thailand/kings":             FIXED("King's Birthday",5,12),
+// "thailand/loy krathong festival":occurs in November,
+// "thailand/makha bucha":       full moon in first lunar month,
+   "thailand/queens":            FIXED("Queen's Birthday",12,8),
+   "thailand/songkran":          FIX_M("Songkran",13,4,3),
+// "thailand/state ploughing ceremony":occurs in May [7th?],
+// "thailand/visakha bucha":     full moon of the sixth lunar month,
+
+   "gambia/independence":        FIXED("Independence Day",18,2),
+   "gambia/moslem new year":     FIXED("Moslem New Year",7,10),
+
+   "togo/anniversary of the failed attack on lome":
+                     FIXED("Anniversary of the failed attack on Lom\351",24,9),
+   "togo/economic liberation":   FIXED("Economic Liberation Day",24,1),
+   "togo/independence":          FIXED("Independence Day",27,4),
+   "togo/liberation":            FIXED("Liberation Day",13,1),
+   "togo/martyrs of pya":        FIXED("Martyrs of Pya",21,6),
+   "togo/victory":               FIXED("Victory Day",24,4),
+
+   "tonga/constitution":         FIXED("Constitution Day",4,11),
+   "tonga/emancipation":         FIXED("Emancipation Day",4,6),
+   "tonga/king tupou":           FIXED("King Tupou Day",4,12),
+   "tonga/kings":                FIXED("King's Birthday",4,7),
+   "tonga/princes":              FIXED("Prince's Birthday",4,5),
+
+   "trinidad and tobago/discovery":FIXED("Discovery Day",1,8),
+   "trinidad and tobago/emancipation":FIXED("Emancipation Day",1,8),
+   "trinidad and tobago/independence":FIXED("Independence Day",31,8),
+   "trinidad and tobago/labor":  FIXED("Labor Day",19,6),
+   "trinidad and tobago/republic":FIXED("Republic Day",24,9),
+
+   "tunisia/accession":          FIXED("Accession Day",7,11),
+   "tunisia/bourguibas":         FIXED("Bourguiba's Day",3,8),
+   "tunisia/evacuation":         FIXED("Evacuation Day",15,10),
+   "tunisia/independence":       FIXED("Independence Day",20,3),
+   "tunisia/independence recognition":
+                                 FIXED("Independence Recognition Day",20,7),
+   "tunisia/martyrs":            FIXED("Martyrs' Day",9,4),
+   "tunisia/memorial":           FIXED("Memorial Day",3,9),
+   "tunisia/national holiday of tunisia":
+                                 FIXED("National Holiday of Tunisia",1,6),
+   "tunisia/national revolution":FIXED("National Revolution Day",18,1),
+   "tunisia/republic":           FIXED("Republic Day",25,7),
+   "tunisia/tree festival":      FIXED("Tree Festival Day",9,11),
+   "tunisia/womens":             FIXED("Women's Day",13,8),
+   "tunisia/youth":              FIXED("Youth Day",21,3),
+
+   "turkey/freedom and constitution":
+                                 FIXED("Freedom and Constitution Day",27,5),
+   "turkey/hidrellez":           FIXED("Hidrellez",6,5),
+   "turkey/independence":        FIXED("Independence Day",29,10),
+   "turkey/youth and sports":    FIXED("Youth and Sports Day",19,5),
+   "turkey/ataturk commemoration": FIXED("Atatürk Commemoration",19,5), // ?
+   "turkey/national sovereignty":FIXED("National Sovereignty",23,4),
+   "turkey/childrens":           FIXED("Children's day",23,4),
+   "turkey/navy and merchant marine":FIXED("Navy and Merchant Marine Day",1,7),
+   "turkey/rumis":               FIXED("Rumi's Birthday",17,12),
+   "turkey/spring":              FIXED("Spring Day",1,5),
+   "turkey/victory":             FIXED("Victory Day",30,8),
+
+   "turks and caicos islands/columbus":FIXED("Columbus Day",10,10),
+   "turks and caicos islands/emancipation":FIXED("Emancipation Day",1,8),
+   "turks and caicos islands/human rights":
+                                 FIXED("International Human Rights Day",24,10),
+   "turks and caicos islands/jags mccartney memorial":
+                                 FIXED("J.A.G.S. McCartney Memorial Day",6,6),
+
+   "tuvalu/tuvalu":              FIX_M("Tuvalu Day",1,10,2),
+
+   "uganda/heroes":              FIXED("Heroes Day",9,6),
+   "uganda/independence":        FIXED("Independence Day",9,10),
+   "uganda/martyrs":             FIXED("Martyr's Day",3,6),
+   "uganda/nrm/nra victorys":    FIXED("NRM/NRA Victory Celebrations",26,1),
+   "uganda/republic":            FIXED("Republic Day",8,9),
+
+   "ukraine/taras shevchenko":   FIXED("Taras Shevchenko Day",9,3),
+   "ukraine/ukrainian":          FIXED("Ukrainian Day",22,1),
+   "ukraine/ukrainian independence":FIXED("Ukrainian Independence Day",24,8),
+   "ukraine/victory":            FIXED("Victory Day",9,3),
+
+   "united arab emirates/accession of the ruler of abu dhabi":
+                              FIXED("Accession of the Ruler of Abu Dhabi",6,8),
+   "united arab emirates/national":FIXED("National Day",2,12),
+
+   "uruguay/artigas":            FIXED("Artigas Day",19,6),
+   "uruguay/battle of las piedras":FIXED("Battle of Las Piedras",18,5),
+   "uruguay/blessing of the waters":FIXED("Blessing of the Waters",8,12),
+   "uruguay/constitution":       FIXED("Constitution Day",18,7),
+   "uruguay/independence":       FIXED("Independence Day",25,8),
+   "uruguay/landing of the 33 patriots":
+                                 FIXED("Landing of the 33 Patriots Day",19,4),
+
+   "united kingdom/bannockburn": FIXED("Bannockburn Day",24,6),
+   "united kingdom/battle of britain":FIXED("Battle of Britain Day",15,9),
+   "united kingdom/burns":       FIXED("Burns Day",25,1),
+   "united kingdom/day after":   FIXED("The Day After",2,1),
+   "united kingdom/guy fawkes":  FIXED("Guy Fawkes Day",5,11),
+   "united kingdom/handsel monday":DWDRI("Handsel Monday",1,1,1,1),
+   "united kingdom/highland games":DWDR("Highland Games",1,10,6,-1),
+   "united kingdom/lammas":      FIXED("Lammas Day",1,8),
+   "united kingdom/lord mayors": FIXED("Lord Mayor's Day",9,11),
+   "united kingdom/mothering sunday":EASTER_REL("Mothering Sunday",-21), // ?
+   "united kingdom/new year":    FIX_M("New Year's Day",1,1,2),
+   "united kingdom/oak apple":   FIXED("Oak Apple Day",29,5),
+   "united kingdom/orangemans":  FIXED("Orangeman's Day",12,7),
+   "united kingdom/pancake tuesday": EASTER_REL("Fat Tuesday",-47),
+   "united kingdom/queens":      DWDRI("Queen's Birthday",1,6,4,2),
+   "united kingdom/woman peerage":FIXED("Woman Peerage Day",30,1),
+   "united kingdom/spring bank holiday":DWDRI("Spring Bank Holiday",1,5,1,4),
+   "united kingdom/late summer bank holiday":
+                                 DWDRI("Late Summer Bank Holiday",1,8,1,4),
+   "united kingdom/orangeman":   FIXED("Orangeman's Day",12,7),
+   "united kingdom/scottish new year":FIXED("Scottish New Year",2,1),
+   "united kingdom/victoria":DWDRI("Victoria Day",1,5,1,3),
+   "united kingdom/autumn holiday":DWDRI("Autumn Holiday",1,9,1,3),
+
+
+   "us/appomattox":              FIXED("Appomattox Day",9,4),
+   "us/armed forces":            DWDRI("Armed Forces Day",1,5,6,3),
+   "us/bill of rights":          FIXED("Bill of Rights Day",15,12),
+   "us/carnation":               FIXED("Carnation Day",29,1),
+   "us/citizenship":             FIXED("Citizenship Day",17,9),
+   "us/columbus":                DWDRI("Columbus Day",1,10,1,2),
+   "us/election":                DWDRI("Election Day",1,11,1,1),
+   "us/flag":                    FIXED("Flag Day",14,6),
+   "us/forefathers":             FIXED("Forefathers' Day",21,12),
+   "us/inauguration":            FIXED("Inauguration Day",20,1),
+   "us/independence":            FIXED("Independence Day",4,7),
+   "us/iwo jima":                FIXED("Iwo Jima Day",23,2),
+   "us/jefferson davis":         FIXED("Jefferson Davis Day",3,6),
+   "us/kosciuszko":              FIXED("Kosciuszko Day",4,2),
+   "us/labor":                   DWDRI("Labor Day",1,9,1,1),
+   "us/lincolns":                FIXED("Lincoln's Birthday",12,2),
+   "us/martin luther king":      FIXED("Martin Luther King Day",15,1),
+   "us/memorial":                DWDRI("Memorial Day",30,5,1,-1),
+   "us/national freedom":        FIXED("National Freedom Day",1,2),
+   "us/navy":                    FIXED("Navy Day",27,10),
+   "us/patriots":                DWDRI("Patriot's Day",1,4,1,3),
+   "us/robert e lee":            FIXED("Robert E. Lee Day",19,1),
+   "us/thomas jeffersons":       FIXED("Thomas Jefferson's Birthday",13,4),
+   "us/veterans":                FIXED("Veteran's Day",11,11),
+   "us/vietnam":                 FIXED("Vietnam Day",27,1),
+   "us/washingtons":             DWDRI("Washington's Birthday",1,2,1,3),
+   "us/washington":              DWDRI("Washington Day",1,2,1,3),
+   "us/washington-lincoln":      DWDRI("Washington-Lincoln Day",1,2,1,3),
+   "us/presidents":              DWDRI("Presidents Day",1,2,1,3),
+   "us/womens equality":         FIXED("Women's Equality Day",26,8),
+   "us/thanksgiving":            DWDRI("Thanksgiving Day",1,11,4,4),
+   "us/day after thanksgiving":  DWDRI("Day after Thanksgiving Day",2,11,5,4),
+
+   "us/alabama/alabama admission":  FIXED("Alabama Admission Day",14,12),
+   "us/alabama/confederate memorial":DWDR("Confederate Memorial Day",1,5,1,-1),
+   "us/alabama/jefferson davis":    DWDRI("Jefferson Davis Day",1,6,1,1),
+   "us/alabama/robert e lee":       DWDRI("Robert E. Lee Day",1,1,1,3),
+
+   "us/alaska/alaska":              DWDRI("Alaska Day",1,10,1,3),
+   "us/alaska/alaska admission":    FIXED("Alaska Admission Day",3,1),
+   "us/alaska/flag":                FIXED("Flag Day",4,7),
+   "us/alaska/sewards":             FIXED("Seward's Day",30,3),
+
+   "us/arizona/american family":    DWDRI("American Family Day",1,8,7,1),
+   "us/arizona/arborn":             FIXED("Arbor Day (northern Arizona)",1,1),
+   "us/arizona/arbors":          DWDR ("Arbor Day (southern Arizona)",1,2,5,1),
+   "us/arizona/arizona admission":  FIXED("Arizona Admission Day",14,2),
+   "us/arizona/lincoln":            DWDRI("Lincoln Day",1,2,1,2),
+
+   "us/arkansas/arkansas admission":FIXED("Arkansas Admission Day",15,6),
+   "us/arkansas/general douglas macarthur":
+                                 FIXED("General Douglas MacArthur Day",26,1),
+// "us/arkansas/jefferson davis":   ,
+   "us/arkansas/world war ii memorial":FIXED("World War II Memorial Day",14,8),
+
+   "us/california/arbor":           FIXED("Arbor Day",7,3),
+   "us/california/california admission":FIXED("California Admission Day",9,9),
+
+   "us/colorado/arbor":             DWDRI("Arbor Day",1,4,5,3),
+   "us/colorado/colorado":          DWDRI("Colorado Day",1,8,1,1),
+
+   "us/connecticut/connecticut ratification":
+                                 FIXED("Connecticut Ratification Day",9,1),
+   "us/delaware/arbor":             FIXED("Arbor Day",22,4),
+   "us/delaware/delaware":          FIXED("Delaware Day",7,12),
+   "us/delaware/lincolns":          DWDRI("Lincoln's Birthday",1,2,1,1),
+   "us/delaware/memorial":          FIXED("Memorial Day",30,5),
+   "us/delaware/separation":        FIXED("Separation Day",15,6),
+   "us/delaware/swedish colonial":  FIXED("Swedish Colonial Day",29,3),
+
+   "us/florida/arbor":              DWDRI("Arbor Day",1,1,5,3),
+   "us/florida/confederate memorial":FIXED("Confederate Memorial Day",26,4),
+   "us/florida/farmers":            DWDRI("Farmer's Day",1,10,1,2),
+   "us/florida/florida admission":  FIXED("Florida Admission Day",3,3),
+   "us/florida/pascua florida":     FIXED("Pascua Florida Day",2,4),
+   "us/florida/susan b anthony":    FIXED("Susan B. Anthony Day",15,2),
+
+   "us/georgia/confederate memorial":FIXED("Confederate Memorial Day",26,4),
+   "us/georgia/georgia":            FIXED("Georgia Day",12,2),
+
+   "us/hawaii/flag":                FIXED("Flag Day",4,7),
+   "us/hawaii/hawaii statehood":    DWDRI("Hawaii Statehood Day",1,8,5,3),
+   "us/hawaii/kamehameha":          FIXED("Kamehameha Day",11,6),
+   "us/hawaii/kuhio":               FIXED("Kuhio Day",26,3),
+   "us/hawaii/lei":                 FIXED("Lei Day",1,5),
+   "us/hawaii/wesak flower festival":DWDRI("Wesak Flower Festival",1,4,7,1),
+
+   "us/idaho/idaho admission":      FIXED("Idaho Admission Day",3,7),
+   "us/idaho/idaho pioneer":        FIXED("Idaho Pioneer Day",15,6),
+
+   "us/illinois/illinois admission":FIXED("Illinois Admission Day",3,12),
+   "us/illinois/memorial":          FIXED("Memorial Day",30,5),
+
+   "us/indiana/indiana admission":  FIXED("Indiana Admission Day",11,12),
+   "us/indiana/primary election":   DWDRI("Primary Election Day",2,5,2,1),
+   "us/indiana/vincennes":          FIXED("Vincennes Day",24,2),
+
+   "us/iowa/bird":                  FIXED("Bird Day",21,3),
+   "us/iowa/independence sunday":   DWDR ("Independence Sunday",4,7,7,-1),
+   "us/iowa/iowa admission":        FIXED("Iowa Admission Day",28,12),
+
+   "us/kansas/kansas":              FIXED("Kansas Day",29,1),
+
+   "us/kentucky/franklin d roosevelt":FIXED("Franklin D. Roosevelt Day",30,1),
+   "us/kentucky/kentucky statehood":FIXED("Kentucky Statehood Day",1,6),
+
+   "us/louisiana/huey p long":      FIXED("Huey P. Long Day",30,8),
+   "us/louisiana/jackson":          FIXED("Jackson Day",8,1),
+   "us/louisiana/louisiana admission":FIXED("Louisiana Admission Day",30,4),
+
+   "us/maine/battleship":           FIXED("Battleship Day",15,2),
+   "us/maine/maine admission":      FIXED("Maine Admission Day",3,3),
+
+   "us/maryland/defenders":         FIXED("Defenders' Day",12,9),
+   "us/maryland/john hanson":       FIXED("John Hanson Day",14,4),
+   "us/maryland/maryland":          FIXED("Maryland Day",25,3),
+   "us/maryland/maryland admission":FIXED("Maryland Admission Day",28,4),
+   "us/maryland/maryland ratification":FIXED("Maryland Ratification Day",14,1),
+   "us/maryland/memorial":          FIXED("Memorial Day",30,5),
+   "us/maryland/national anthem":   FIXED("National Anthem Day",14,9),
+   "us/maryland/repudiation":       FIXED("Repudiation Day",23,11),
+
+   "us/massachusetts/bunker hill":  FIXED("Bunker Hill Day",17,6),
+   "us/massachusetts/childrens":    DWDRI("Children's Day",1,6,7,2),
+   "us/massachusetts/evacuation":   FIXED("Evacuation Day",17,3),
+   "us/massachusetts/john f kennedy":DWDR("John F. Kennedy Day",1,12,7,-1),
+   "us/massachusetts/lafayette":    FIXED("Lafayette Day",20,5),
+   "us/massachusetts/liberty tree": FIXED("Liberty Tree Day",14,8),
+   "us/massachusetts/massachusetts ratification":
+                                 FIXED("Massachusetts Ratification Day",6,2),
+   "us/massachusetts/spanish-american war memorial":
+                               FIXED("Spanish-American War Memorial Day",15,2),
+   "us/massachusetts/student government":DWDRI("Student Government Day",1,4,5,1),
+   "us/massachusetts/susan b anthony":FIXED("Susan B. Anthony Day",26,8),
+   "us/massachusetts/teachers":     DWDRI("Teacher's Day",1,6,7,1),
+
+   "us/michigan/memorial":          DWDRI("Memorial Day",1,5,1,3),
+   "us/michigan/michigan":          FIXED("Michigan Day",26,1),
+
+   "us/minnesota/american family":  DWDRI("American Family Day",1,8,7,1),
+   "us/minnesota/minnesota":        FIXED("Minnesota Day",11,5),
+
+   "us/mississippi/confederate memorial":
+                       DWDRI("Confederate Memorial Day",30,4,1,-1),
+   "us/mississippi/jefferson davis":DWDRI("Jefferson Davis Day",1,6,1,1),
+   "us/mississippi/robert elee":    DWDRI("Robert E.Lee Day",1,1,1,3),
+
+   "us/missouri/missouri admission":FIXED("Missouri Admission Day",10,8),
+   "us/missouri/truman":            FIXED("Truman Day",8,5),
+
+   "us/montana/election":           DWDRI("Election Day",1,11,2,1),
+
+   "us/nebraska/arbor":             FIXED("Arbor Day",22,4),
+   "us/nebraska/nebraska state":    FIXED("Nebraska State Day",1,3),
+
+   "us/nevada/nevada":              FIXED("Nevada Day",31,10),
+
+   "us/new hampshire/fast":         DWDRI("Fast Day",1,4,1,4),
+   "us/new hampshire/memorial":     FIXED("Memorial Day",30,5),
+   "us/new hampshire/new hampshire admission":
+                                    FIXED("New Hampshire Admission Day",21,6),
+
+   "us/new jersey/new jersey admission":
+	                            FIXED("New Jersey Admission Day",18,12),
+
+   "us/new mexico/arbor":           DWDRI("Arbor Day",1,3,5,2),
+   "us/new mexico/memorial":        FIXED("Memorial Day",25,5),
+
+   "us/new york/audubon":           DWDRI("Audubon Day",1,4,5,2),
+   "us/new york/flag":              DWDRI("Flag Day",1,6,7,2),
+   "us/new york/martin luther king":DWDRI("Martin Luther King Day",1,1,7,3),
+   "us/new york/new york ratification":FIXED("New York Ratification Day",26,7),
+   "us/new york/verrazano":         FIXED("Verrazano Day",17,4),
+
+   "us/north carolina/confederate memorial":
+                                 FIXED("Confederate Memorial Day",10,5),
+   "us/north carolina/halifax resolutions":
+                                 FIXED("Halifax Resolutions Day",12,4),
+   "us/north carolina/mecklenburg": FIXED("Mecklenburg Day",20,5),
+
+   "us/north dakota/north dakota admission":
+                                 FIXED("North Dakota Admission Day",2,11),
+
+   "us/ohio/martin luther king":    DWDRI("Martin Luther King Day",1,1,1,3),
+   "us/ohio/ohio admission":        FIXED("Ohio Admission Day",1,3),
+
+   "us/oklahoma/bird":              FIXED("Bird Day",1,5),
+   "us/oklahoma/cherokee strip":    FIXED("Cherokee Strip Day",16,9),
+   "us/oklahoma/indian":            FIXED("Indian Day",12,8),
+   "us/oklahoma/oklahoma":          FIXED("Oklahoma Day",22,4),
+// "oklahoma/oklahoma heritage week":week of November 16,
+   "us/oklahoma/oklahoma historical":FIXED("Oklahoma Historical Day",10,10),
+   "us/oklahoma/oklahoma statehood":FIXED("Oklahoma Statehood Day",16,11),
+   "us/oklahoma/senior citizens":   FIXED("Senior Citizens Day",9,6),
+   "us/oklahoma/will rogers":       FIXED("Will Rogers Day",4,11),
+// "oklahoma/youth":                on first day of Spring,
+
+   "us/oregon/lincolns":            DWDRI("Lincoln's Birthday",1,2,1,1),
+   "us/oregon/oregon statehood":    FIXED("Oregon Statehood Day",14,2),
+
+   "us/pennsylvania/barry":         FIXED("Barry Day",13,9),
+   "us/pennsylvania/charter":       FIXED("Charter Day",4,3),
+   "us/pennsylvania/pennsylvania admission":
+                                 FIXED("Pennsylvania Admission Day",12,12),
+
+   "us/rhode island/arbor":         DWDRI("Arbor Day",1,5,5,2),
+   "us/rhode island/rhode island admission":
+                                 FIXED("Rhode Island Admission Day",29,5),
+   "us/rhode island/rhode island independence":
+                                 FIXED("Rhode Island Independence Day",4,5),
+   "us/rhode island/victory":       DWDRI("Victory Day",1,8,1,2),
+
+   "us/south carolina/confederate memorial":
+                                 FIXED("Confederate Memorial Day",10,5),
+   "us/south carolina/south carolina admission":
+                                 FIXED("South Carolina Admission Day",23,5),
+
+   "us/south dakota/memorial":      FIXED("Memorial Day",30,5),
+   "us/south dakota/pioneers":      DWDRI("Pioneers' Day",1,10,1,2),
+   "us/south dakota/south dakota admission":
+                                 FIXED("South Dakota Admission Day",2,11),
+
+   "us/tennessee/confederate memorial":FIXED("Confederate Memorial Day",3,6),
+   "us/tennessee/tennesse statehood":FIXED("Tennesse Statehood Day",1,6),
+
+   "us/texas/alamo":                FIXED("Alamo Day",6,3),
+   "us/texas/austin":               FIXED("Austin Day",3,11),
+   "us/texas/confederate heroes":   FIXED("Confederate Heroes Day",19,1),
+   "us/texas/juneteenth":           FIXED("Juneteenth",19,6),
+   "us/texas/lyndon b johnsons":    FIXED("Lyndon B. Johnson's Birthday",27,8),
+   "us/texas/san jacinto":          FIXED("San Jacinto Day",21,4),
+   "us/texas/texas admission":      FIXED("Texas Admission Day",29,12),
+   "us/texas/texas independence":   FIXED("Texas Independence Day",2,3),
+   "us/texas/texas pioneers":       FIXED("Texas Pioneers' Day",12,8),
+
+   "us/utah/arbor":                 DWDR("Arbor Day",1,5,5,-1),
+   "us/utah/pioneer":               FIXED("Pioneer Day",24,7),
+   "us/utah/utah admission":        FIXED("Utah Admission Day",4,1),
+
+   "us/vermont/bennington battle":  FIXED("Bennington Battle Day",16,8),
+   "us/vermont/memorial":           FIXED("Memorial Day",30,5),
+   "us/vermont/town meeting":       DWDRI("Town Meeting Day",1,3,2,1),
+   "us/vermont/vermont":            FIXED("Vermont Day",4,3),
+
+   "us/virginia/cape henry":        FIXED("Cape Henry Day",26,4),
+   "us/virginia/confederate memorial":FIXED("Confederate Memorial Day",30,5),
+   "us/virginia/crater":            FIXED("Crater Day",30,7),
+// "virginia/jack jouett":       occurs in June,
+   "us/virginia/jamestown":         FIXED("Jamestown Day",13,5),
+   "us/virginia/lee-jackson":       DWDRI("Lee-Jackson Day",1,1,1,3),
+   "us/virginia/royalist fast":     FIXED("Royalist Fast Day",30,1),
+   "us/virginia/virginia ratification":FIXED("Virginia Ratification Day",25,6),
+
+   "us/washington/washington admission":FIXED("Washington Admission Day",11,11),
+
+   "us/washington dc/arbor":        DWDRI("Arbor Day",1,4,5,3),
+
+   "us/west virginia/west virginia":FIXED("West Virginia Day",20,6),
+
+   "us/wisconsin/primary election": DWDRI("Primary Election Day",1,9,2,1),
+   "us/wisconsin/wisconsin":        FIXED("Wisconsin Day",29,5),
+
+   "us/wyoming/arbor":              DWDR("Arbor Day",1,5,1,-1),
+   "us/wyoming/primary election":   DWDRI("Primary Election Day",1,9,2,2),
+   "us/wyoming/wyoming":            FIXED("Wyoming Day",10,12),
+   "us/wyoming/wyoming statehood":  FIXED("Wyoming Statehood Day",10,7),
+
+   "vanuatu/constitution":       FIXED("Constitution Day",5,10),
+   "vanuatu/independence":       FIXED("Independence Day",30,7),
+
+   "vatican city/anniversary of the beginning of the john paul ii pontificate":
+   FIXED("Anniversary of the Beginning of the John Paul II Pontificate",22,10),
+   "vatican city/john paul ii namesday":FIXED("John Paul II Namesday",4,11),
+
+   "venezuela/battle of carabobo":FIXED("Battle of Carabobo Day",24,6),
+   "venezuela/bolivars":         FIXED("Bolivar's Birthday",24,7),
+   "venezuela/civil servants":   FIXED("Civil Servants' Day",4,9),
+   "venezuela/declaration of independence":
+                                 FIXED("Declaration of Independence",19,4),
+   "venezuela/independence":     FIXED("Independence Day",5,7),
+   "venezuela/teachers":         FIXED("Teacher's Day",15,1),
+
+   "vietnam/day of the nation":  FIXED("Day of the Nation",2,9),
+   "vietnam/emperor-founder hung vuongs":
+                                 FIXED("Emperor-Founder Hung Vuong's Day",7,4),
+   "vietnam/founding of the communist party":
+                                 FIXED("Founding of the Communist Party",3,2),
+   "vietnam/independence":       FIXED("Independence Day",14,6),
+   "vietnam/liberation of saigon":FIXED("Liberation of Saigon",30,4),
+// "vietnam/tet nguyen dan":     occurs in January of February,
+// "vietnam/thanh minh":         between April 5 and 20,
+
+   "virgin islands/danish west indies emancipation":
+                              FIXED("Danish West Indies Emancipation Day",3,7),
+   "virgin islands/hurricane supplication":
+                                 DWDRI("Hurricane Supplication Day",1,7,1,4),
+   "virgin islands/hurricane thanksgiving":
+                                 DWDRI("Hurricane Thanksgiving Day",1,10,1,3),
+   "virgin islands/liberty":     DWDRI("Liberty Day",1,11,1,1),
+   "virgin islands/nicole robin":FIXED("Nicole Robin Day",4,8),
+   "virgin islands/organic act": DWDRI("Organic Act Day",1,6,1,3),
+   "virgin islands/transfer":    DWDR("Transfer Day",1,4,1,-1),
+
+   "western samoa/arbor":        DWDRI("Arbor Day",1,11,5,1),
+   "western samoa/independence": FIXED("Independence Celebration Day",1,6),
+   "western samoa/independence2":FIX_M("Independence Celebration",1,6,3),
+   "western samoa/white sunday": DWDRI("White Sunday",1,10,7,2),
+
+   "yemen/corrective movement":  FIXED("Corrective Movement Anniversary",13,6),
+   "yemen/national":             FIXED("National Day",14,10),
+
+   "zaire/armed forces":         FIXED("Armed Forces Day",17,11),
+   "zaire/constitution":         FIXED("Constitution Day",24,6),
+   "zaire/day of the martyrs for independence":
+                              FIXED("Day of the Martyrs for Independence",4,1),
+   "zaire/independence":         FIXED("Independence Day",30,6),
+   "zaire/mpr":                  FIXED("MPR Day",20,5),
+   "zaire/naming":               FIXED("Naming Day",27,10),
+   "zaire/new regime":           FIXED("New Regime Day",24,11),
+   "zaire/parents":              FIXED("Parent's Day",1,8),
+   "zaire/presidents":           FIXED("President's Day",14,10),
+   "zaire/youth/presidents":     FIXED("Youth Day/President's Birthday",14,10),
+
+   "zambia/farmers":             DWDRI("Farmers' Day",1,8,1,1),
+   "zambia/heroes":              DWDRI("Heroes' Day",1,7,1,1),
+   "zambia/independence":        FIXED("Independence Day",24,10),
+   "zambia/unity":               DWDRI("Unity Day",1,7,2,1),
+   "zambia/youth":               DWDRI("Youth Day",1,8,1,2),
+   "zambia/youth2":              DWDRI("Youth Day",1,3,6,2),
+
+   "zimbabwe/heroess":           FIX_M("Heroes' Days",11,8,2),
+   "zimbabwe/independence":      FIXED("Independence Day",18,4),
+   "zimbabwe/workers":           FIXED("Workers' Day",1,5),
+
+// ----------------------------------------------------------------
+// namedays
+// ----------------------------------------------------------------
+
+   "namedays/sweden":({.Namedays.Sweden}),
+   "namedays/hungary":({.Namedays.Hungary}),
+]);
+
+// ----------------------------------------------------------------------
+// country information
+// ----------------------------------------------------------------------
+
+mapping country_events=
+([
+// ----------------------------------------------------------------------
+// verified
+// ----------------------------------------------------------------------
+
+   "sweden":
+   ({
+      "halloween",
+      "labor|hf",
+      "new years eve",
+      "new year|hf",
+      "un|f",
+      "womens",
+
+      "c/all saints",
+      "c/annunciation",
+      "c/ascension|h",
+      "c/christmas eve",
+      "c/christmas|hf",
+      "c/easter monday|h",
+      "c/easter eve",
+      "c/easter|hf",
+      "c/epiphany|h",
+      "c/fat tuesday",
+      "c/good friday|h",
+      "c/palm sunday|h",
+      "c/pentecost monday|h",
+      "c/pentecost eve",
+      "c/pentecost|hf",
+      "c/candlemas",
+      "c/advent 1|h",
+      "c/advent 2|h",
+      "c/advent 3|h",
+      "c/advent 4|h",
+   
+      "saints/stephen|h",  // annandag jul
+      "saints/john the baptist",
+      "saints/lucy",
+      "saints/valentine",
+
+      "sweden/all saints|h",
+      "sweden/crown princess birthtday|f",
+      "sweden/crown princess nameday|f",
+      "sweden/flag|f",
+      "sweden/nobel|f",
+      "sweden/kings birthday|f",
+      "sweden/kings nameday 2|f",
+      "sweden/kings nameday|f",
+      "sweden/midsummers eve",
+      "sweden/midsummer|hf",
+      "sweden/queens birthday|f",
+      "sweden/queens nameday|f",
+      "sweden/valborg eve",
+      "sweden/waffle",
+      "sweden/mothers",
+      "sweden/fathers",
+
+      "namedays/sweden",
+      "sunday|h",
+   }),
+
+// argentina
+// source: Julio César Gázquez
+
+   "argentina":
+ // "argentina/race" ?
+ // "carnival [shrove tuesday?]" ?
+ // "death of general san martin" ?
+   ({ 
+      "new year|h",
+      "labor|h",
+	 
+      "argentina/revolution|h",
+      "argentina/soberanys|h",	
+      "argentina/flag|h",		
+      "argentina/independence|h",    
+      "argentina/gral san martin|h", 
+      "argentina/race|h",            
+      "argentina/malvinas|h",         // ?
+	 
+      "c/epiphany",
+      "c/good friday|h",
+      "c/easter|h",
+      "c/christmas|h",
+      "c/immaculate conception|h",
+      "c/assumption",  
+      "c/all saints",       
+      "c/corpus christi",
+      "c/holy thursday",   
+      "c/holy saturday",   
+
+      "sunday|h",
+   }),
+
+// hungary
+// source: Csongor Fagyal <concept@conceptonline.hu>
+
+   "hungary":
+   ({
+      "new year|h",
+      "hungary/revolution1848|h",
+      "hungary/labor|h",
+      "hungary/constitution|h",
+      "hungary/revolution56|h",
+      "c/christmas2d|h",
+      "c/easter|h",
+      "c/easter monday|h",
+      "c/pentecost|h",
+      "c/pentecost monday|h",
+      "sunday|h",
+      "namedays/hungary",
+   }),
+
+// russia
+// source: Michael Schvryev
+
+   "russia":
+   ({ "orthodox/christmas|h",
+      "labor|h",
+      "new year|h",
+      "orthodox/easter|h",
+      "russia/state sovereignity|h",
+      "russia/victory|h",
+      "russia/valpurgis|h",
+      "russia/warriors|h",
+      "russia/teachers|h",
+      "womens|h" }),
+
+// ----------------------------------------------------------------------
+// not verified
+// ----------------------------------------------------------------------
+
+   "afghanistan":
+ // "afghanistan/jeshyn-afghans" ?
+ // "deliverance" ?
+ // "eid al-qorban" ?
+ // "first of ramadan the sabbath is on friday" ?
+ // "independence festival" ?
+ // "national holidays are eid al-fetr" ?
+ // "prophets" ?
+ // "pushtunistan" ?
+ // "sunday are normal works" ?
+ // "with work ceasing on noon thursday saturday" ?
+ // "yom ashura" ?
+   ({ "afghanistan/afghan new year",
+      "afghanistan/childrens",
+      "afghanistan/independence",
+      "afghanistan/mothers",
+      "afghanistan/national assembly",
+      "afghanistan/revolution",
+      "afghanistan/workers" }),
+
+   "albania":
+   ({ "albania/army",
+      "albania/independence",
+      "albania/liberation",
+      "albania/proclamation of the republic",
+      "new year",
+      "womens" }),
+
+   "algeria":
+ // "ashora" ?
+ // "first of ramadan" ?
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "leilat al-meiraj" ?
+ // "mouloud" ?
+   ({ "algeria/independence",
+      "algeria/national",
+      "algeria/revolution",
+      "labor",
+      "new year" }),
+
+   "american baptist":
+   ({ "american baptist/roger williams" }),
+
+   "american samoa":
+   ({ "+us",
+      "american samoa/flag",
+      "c/christmas",
+      "labor",
+      "new year" }),
+
+   "andorra":
+   ({ "andorra/national feast",
+      "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "new year" }),
+
+   "anglican church":
+   ({ "anglican church/name of jesus" }),
+
+   "angola":
+ // "yet are generally treated as public holidays these are youth" ?
+   ({ "angola/armed forces",
+      "angola/independence",
+      "angola/mpla foundation",
+      "angola/national heros",
+      "angola/national holiday",
+      "angola/pioneers",
+      "angola/victory",
+      "angola/workers",
+      "angola/youth",
+      "family",
+      "new year" }),
+
+   "anguilla":
+ // "august monday" ?
+ // "august thursday" ?
+ // "constitution" ?
+ // "queens official" ?
+ // "separation" ?
+ // "spring bank holiday" ?
+   ({ "anguilla/anguilla",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "labor",
+      "new year" }),
+
+   "antigua and barbuda":
+ // "carnival" ?
+   ({ "antigua and barbuda/independence",
+      "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "caribbean/caricom",
+      "labor",
+      "new year" }),
+
+   "armenia":
+ // "armenia/Easter (Orthodox)" ?
+   ({ "armenia/christmas",
+      "armenia/martyrs",
+      "armenia/republic" }),
+
+   "aruba":
+ // "lenten carnival" ?
+   ({ "aruba/aruba flag",
+      "british commonwealth/queens",
+      "c/ascension",
+      "c/christmas",
+      "c/easter",
+      "c/whitmonday",
+      "labor",
+      "new year" }),
+
+   "australia":
+   ({ "australia/australia|h",
+      "australia/eight hour",
+      "new year|h",
+      "c/good friday|h",
+      "c/easter monday|h",
+      "c/easter|h",
+      "anzac|h",
+      "united kingdom/queens|h",
+      "c/christmas|h",
+      "c/boxing|h" }),
+
+   "australia/new south wales":
+   ({ "+australia",
+      "australia/summer bank holiday|h"}),
+   "australia/northern territory":
+   ({ "+australia",
+      "labor|h" }),
+   "australia/queensland":
+   ({ "+australia",
+//    "australia/labor_oct|h", 
+      "australia/summer bank holiday|h"}),
+   "australia/south australia":
+   ({ "+australia",
+      "australia/proclamation|h",
+      "labor|h", }),
+   "australia/tasmania":
+   ({ "+australia",
+      "australia/recreation",
+      "australia/hobert regatta|h",
+//    "australia/labor_mar|h",
+      "australia/spring bank holiday|h" }),
+   "australia/victoria":
+   ({ "+australia",
+      "australia/show|h",
+      "australia/second new years",
+//    "australia/labor_mar|h",
+//    "australia/cup|h",
+      "australia/spring bank holiday|h"}),
+   "australia/western australia":
+   ({ "+australia",
+      "australia/foundation|h",
+      "australia/show|h",
+//    "australia/labor_mar|h",
+      "australia/spring bank holiday|h" }),
+
+   "austria":
+   ({ "c/all saints",
+      "austria/national",
+      "austria/national holiday",
+      "austria/national holiday of austria",
+      "austria/republic",
+      "austria/second republic",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/corpus christi",
+      "c/easter monday",
+      "c/immaculate conception",
+      "c/whitmonday",
+      "c/epiphany",
+      "labor",
+      "new year" }),
+
+   "bahamas":
+   ({ "bahamas/fox hill",
+      "bahamas/independence",
+      "bahamas/labor",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "caribbean/emancipation",
+      "columbus",
+      "labor",
+      "new year" }),
+
+   "bahrain":
+ // "ashoura" ?
+ // "first of muharram" ?
+ // "first of ramadan" ?
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "leilat al-meiraj" ?
+ // "mouloud" ?
+ // "national" ?
+   ({ "bahrain/national of bahrain",
+      "new year" }),
+
+   "bangladesh":
+ // "buddha purnima" ?
+ // "durga puja" ?
+ // "eid-ul-azha" ?
+ // "eid-ul-fitr" ?
+ // "jamaat-ul-bida" ?
+ // "janmastami" ?
+ // "martyrs" ?
+ // "shab-e-barat" ?
+ // "shab-e-qudr" ?
+ // "yom ashura" ?
+   ({ "bangladesh/bengali new year",
+      "bangladesh/independence",
+      "bangladesh/national mourning",
+      "bangladesh/revolution",
+      "bangladesh/victory",
+      "c/christmas",
+      "may day" }),
+
+   "barbados":
+ // "kadooment" ?
+   ({ "barbados/errol barrow",
+      "barbados/independence",
+      "barbados/united nations",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "labor",
+      "new year" }),
+   
+   "belgium":
+   ({ "c/all saints",
+      "armistice",
+      "belgium/dynasty",
+      "belgium/independence",
+      "belgium/kings",
+      "c/all souls",
+      "c/ascension",
+      "c/assumption",
+      "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/whitmonday",
+      "labor",
+      "new year" }),
+
+   "belize":
+   ({ "belize/baron bliss",
+      "belize/commonwealth",
+      "belize/garifuna",
+      "belize/independence",
+      "belize/national",
+      "belize/pan american",
+      "belize/saint georges cay",
+      "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/holy saturday",
+      "labor",
+      "new year" }),
+
+   "benin":
+ // "id al-adha" ?
+ // "id al-fitr" ?
+   ({ "c/all saints",
+      "benin/armed forces",
+      "benin/harvest",
+      "benin/martyrs",
+      "benin/national",
+      "benin/workers",
+      "benin/youth",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "new year" }),
+
+   "bermuda":
+ // "bermuda/Labor Day (Sep)" ?
+ // "cup match" ?
+ // "queens official" ?
+   ({ "bermuda/bermuda",
+      "bermuda/peppercorn",
+      "bermuda/remembrance",
+      "bermuda/somers",
+      "c/christmas",
+      "c/good friday",
+      "new year" }),
+
+   "bhutan":
+ // "buddhist holidays" ?
+ // "dussehra" ?
+   ({ "bhutan/kings",
+      "bhutan/national of bhutan" }),
+
+   "bolivia":
+ // "also regional public holidays" ?
+ // "bolivia/alacitas" ?
+ // "bolivia/la paz" ?
+ // "carnival " ?
+ // "christmas there" ?
+ // "shrove tue)" ?
+   ({ "bolivia/independence",
+      "bolivia/martyrs",
+      "bolivia/memorial",
+      "bolivia/national",
+      "c/all souls",
+      "c/corpus christi",
+      "c/good friday",
+      "labor",
+      "new year" }),
+
+   "bosnia and herzegovina":
+ // "july 27" ?
+ // "november 25" ?
+   ({ "bosnia and herzegovina/labors",
+      "new year" }),
+
+   "botswana":
+ // "christmas multiples" ?
+ // "given for most of these holidays" ?
+ // "national holidays" ?
+   ({ "botswana/botswana",
+      "botswana/presidents",
+      "c/ascension",
+      "c/easter",
+      "new year" }),
+
+   "brazil":
+ // "carnival" ?
+ // "christmas sao paulo has the additional regional public holiday sao paulo" ?
+ // "national holidays" ?
+ // "saint sebastians feast" ?
+   ({ "brazil/brasilia",
+      "brazil/discovery",
+      "brazil/independence",
+      "brazil/proclamation of the republic",
+      "brazil/republic",
+      "brazil/sao paulo",
+      "brazil/tiradentes",
+      "c/all souls",
+      "c/corpus christi",
+      "c/good friday",
+      "labor",
+      "new year" }),
+
+   "british virgin islands":
+ // "august holiday " ?
+ // "british virgin islands/sovereigns observance" ?
+ // "commonwealth" ?
+ // "queens official" ?
+ // "saint ursulas" ?
+ // "tue" ?
+ // "wed)" ?
+   ({ "british commonwealth/prince of wales",
+      "british virgin islands/territory",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "new year" }),
+
+   "brunei":
+ // "beginning of ramadan" ?
+ // "brunei/Hari Raya Haji (Feast of the Sacrifice)" ?
+ // "brunei/Hari Raya Puasa (end of Ramadan)" ?
+ // "brunei/Hizrah (Islamic New Year)" ?
+ // "brunei/Isra Mera (Leilat al-Meiraj)" ?
+ // "brunei/Memperingati Nuzul Al-Quran (Revelation of the Koran)" ?
+ // "chinese new year" ?
+ // "hari mouloud" ?
+   ({ "brunei/national",
+      "brunei/royal brunei armed forces",
+      "brunei/sultans",
+      "c/christmas",
+      "new year" }),
+
+   "bulgaria":
+ // "national holidays" ?
+   ({ "bulgaria/babin den",
+      "bulgaria/botev",
+      "bulgaria/education",
+      "bulgaria/liberation",
+      "bulgaria/national",
+      "bulgaria/national holiday",
+      "bulgaria/viticulturists",
+      "c/christmas",
+      "labor",
+      "new year" }),
+
+   "burkina faso":
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "mouloud" ?
+   ({ "c/all saints",
+      "burkina faso/anniversary of 1966 coup",
+      "burkina faso/labor",
+      "burkina faso/national",
+      "burkina faso/republic",
+      "burkina faso/youth",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "c/whitmonday",
+      "new year" }),
+
+   "burundi":
+ // "umugamuro" ?
+   ({ "c/all saints",
+      "burundi/anniversary of the revolution",
+      "burundi/independence",
+      "burundi/murder of the hero",
+      "burundi/victory of uprona",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "labor",
+      "new year" }),
+
+   "cambodia":
+ // "cambodia/chaul chhnam" ?
+ // "cambodia/visak bauchea" ?
+ // "chaul chhnam" ?
+   ({ "cambodia/ancestors",
+      "cambodia/day of hatred",
+      "cambodia/independence",
+      "cambodia/khmer republic constitution",
+      "cambodia/memorial",
+      "cambodia/national",
+      "labor" }),
+
+   "cameroon":
+   ({ "c/all saints",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/pentecost monday",
+      "cameroon/commemoration of national institutions",
+      "cameroon/constitution",
+      "cameroon/human rights",
+      "cameroon/independence",
+      "cameroon/unification",
+      "cameroon/youth",
+      "labor" }),
+
+   "canada":
+ // "also public holidays specific to each province" ?
+ // "canada/Labor Day (Sep.)" ?
+ // "canada/discovery" ?
+ // "canada/thanksgiving" ?
+ // "christmas there" ?
+ // "thanksgiving" ?
+   ({ "c/easter monday",
+      "c/good friday",
+      "canada/civic holiday",
+      "canada/dominion",
+      "canada/klondike gold discovery",
+      "canada/labor",
+      "canada/remembrance",
+      "canada/victoria",
+      "new year" }),
+
+   "cape verde":
+   ({ "c/all saints",
+      "c/assumption",
+      "c/christmas",
+      "cape verde/independence",
+      "cape verde/national",
+      "cape verde/national heroes",
+      "labor",
+      "new year" }),
+
+   "caribbean":
+   ({ "caribbean/caricom",
+      "caribbean/emancipation",
+      "caribbean/schoelcher" }),
+
+   "cayman islands":
+ // "constitution" ?
+ // "discovery" ?
+ // "queens official" ?
+ // "remembrance" ?
+   ({ "c/ash wednesday",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "new year" }),
+
+   "central african republic":
+ // "national holidays" ?
+   ({ "c/all saints",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "c/pentecost",
+      "central african republic/first government",
+      "central african republic/republic",
+      "central african republic/boganda",
+      "central african republic/day after republic",
+      "central african republic/independence",
+      "central african republic/national holiday",
+      "labor",
+      "new year" }),
+
+   "central america":
+   ({ "central america/independence" }),
+
+   "chad":
+ // "aid el kebir" ?
+ // "aid el sequir" ?
+ // "mouloud el nebi" ?
+   ({ "africa",
+      "c/all saints",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "c/pentecost",
+      "chad/creation of the union of central african states",
+      "chad/independence",
+      "chad/national",
+      "chad/republic",
+      "chad/traditional independence []",
+      "labor",
+      "new year" }),
+
+   "chile":
+   ({ "saints/paul",
+      "saints/peter",
+      "c/all saints",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/corpus christi",
+      "c/good friday",
+      "c/immaculate conception",
+      "chile/armed forces",
+      "chile/independence",
+      "chile/independence2",
+      "chile/national holiday",
+      "chile/navy",
+      "columbus",
+      "labor",
+      "new year" }),
+
+   "china":
+ // "army" ?
+ // "china/army" ?
+ // "chinese new year" ?
+ // "dragon boat festival" ?
+ // "lantern festival" ?
+ // "mid-autumn festival" ?
+ // "qing ming" ?
+ // "seventh eve" ?
+   ({ "china/ccps",
+      "china/childrens",
+      "china/national",
+      "china/teachers",
+      "china/tree planting",
+      "china/youth",
+      "labor",
+      "new year",
+      "womens" }),
+
+   "columbia":
+ // "battle of boyacaday" ?
+ // "national holidays" ?
+ // "sacred heart" ?
+ // "saint josephs" ?
+   ({ "saints/paul",
+      "saints/peter",
+      "c/all saints",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/corpus christi",
+      "c/good friday",
+      "c/holy thursday",
+      "c/immaculate conception",
+      "columbia/battle of boyaca",
+      "columbia/cartagena independence",
+      "columbia/independence",
+      "columbia/thanksgiving",
+      "columbus",
+      "c/epiphany",
+      "labor",
+      "new year" }),
+
+   "comoros":
+ // "ashoura" ?
+ // "beginning of ramadan" ?
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "leilat al-meiraj" ?
+ // "mouloud" ?
+   ({ "comoros/anniversary of president abdallahs assassination",
+      "comoros/independence" }),
+
+   "congo":
+ // "national holidays" ?
+   ({ "c/all saints",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "c/pentecost",
+      "congo/day before army",
+      "congo/day before independence",
+      "congo/day before national",
+      "congo/independence",
+      "congo/martyr of independence",
+      "new year" }),
+
+   "corsica":
+   ({ "corsica/napoleons" }),
+
+   "costa rica":
+ // "costa rica/guanacaste" ?
+   ({ "costa rica/battle of rivas",
+      "costa rica/independence" }),
+
+   "croatia":
+   ({ "c/assumption",
+      "c/christmas",
+      "croatia/national holiday",
+      "croatia/republic",
+      "c/epiphany",
+      "labor",
+      "new year" }),
+
+   "cuba":
+ // "cuba/beginning of independence wars" ?
+   ({ "cuba/independence",
+      "cuba/liberation",
+      "cuba/revolution",
+      "cuba/wars of independence",
+      "labor" }),
+
+   "cyprus/greece":
+   ({ "new year",
+      "c/epiphany",
+      "cyprus/name day",
+      "cyprus/green monday",
+      "greece/independence",
+      "c/good friday",
+      "c/holy saturday",
+      "c/easter monday",
+      "cyprus/greek national",
+      "c/christmas",
+      "c/boxing",
+      "cyprus/kataklysmos",
+      "cyprus/submersion of the holy cross" }),
+
+   "cyprus/turkey":
+//    "id al-fitr"
+//    "id al-adha"
+//    "birth of the prophet"
+   ({ "new year",
+      "turkey/national sovereignty",
+      "turkey/childrens",
+      "labor",
+      "turkey/youth and sports",
+      "cyprus/communal resistance",
+      "turkey/victory",
+      "turkey/independence",
+      "cyprus/kataklysmos",
+      "cyprus/peace and freedom",
+      "cyprus/submersion of the holy cross" }),
+
+   "czech republic":
+   ({ "c/christmas",
+      "saints/stephen",
+      "c/christmas eve",
+      "c/easter monday",
+      "czech republic/death of jan hus",
+      "czech republic/introduction of christianity",
+      "labor",
+      "new year" }),
+
+   "czechoslovakia":
+ // "czechoslovakia/teachers" ?
+   ({ "czechoslovakia/resistance movement" }),
+
+   "denmark":
+ // "denmark/public holidays" ?
+   ({ "denmark/birthday of queen margrethe ii",
+      "denmark/common prayer",
+      "denmark/constitution",
+      "denmark/fjortende februar",
+      "denmark/liberation",
+      "denmark/valdemars" }),
+
+   "djibouti":
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "independence" ?
+ // "mawloud" ?
+ // "muharram" ?
+   ({ "c/christmas",
+      "djibouti/independence feast",
+      "djibouti/workers",
+      "new year" }),
+
+   "dominica":
+ // "carnival" ?
+   ({ "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "dominica/community service",
+      "dominica/emancipation",
+      "dominica/independence",
+      "labor",
+      "new year" }),
+
+   "ecuador":
+ // "battle of pichincha" ?
+ // "carnival" ?
+ // "cuenca independence" ?
+ // "ecuador/cuenca independence" ?
+ // "ecuador/independence" ?
+ // "founding of quito" ?
+ // "guayaquil independence" ?
+ // "independence" ?
+ // "simsn bolmvars" ?
+   ({ "c/all saints",
+      "c/all souls",
+      "c/christmas",
+      "c/good friday",
+      "c/holy thursday",
+      "columbus",
+      "ecuador/battle of pichincha ",
+      "ecuador/guayaquils independence",
+      "ecuador/simon bolivars",
+      "c/epiphany",
+      "labor",
+      "new year" }),
+
+   "egypt":
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "leilat al-meiraj" ?
+ // "mouled al nabi" ?
+   ({ "egypt/armed forces",
+      "egypt/evacuation",
+      "egypt/leylet en-nuktah",
+      "egypt/revolution",
+      "egypt/sham al-naseem",
+      "egypt/sinai liberation",
+      "egypt/suez",
+      "egypt/victory",
+      "labor",
+      "new year",
+      "unity" }),
+
+   "el salvador":
+ // "el salvador/Discovery of America (Columbus Day)" ?
+   ({ "c/all souls",
+      "c/christmas",
+      "c/corpus christi",
+      "c/easter",
+      "el salvador/first call for independence",
+      "el salvador/independence",
+      "el salvador/san salvador festival",
+      "el salvador/schoolteachers",
+      "labor",
+      "new year" }),
+
+   "equatorial guinea":
+   ({ "c/christmas",
+      "c/easter",
+      "c/good friday",
+      "equatorial guinea/armed forces",
+      "equatorial guinea/constitution",
+      "equatorial guinea/independence",
+      "equatorial guinea/oau",
+      "equatorial guinea/presidents",
+      "labor",
+      "new year" }),
+
+   "estonia":
+ // "independence" ?
+   ({ "c/christmas",
+      "c/good friday",
+      "estonia/midsummer",
+      "estonia/victory",
+      "labor",
+      "new year" }),
+
+   "ethiopia":
+ // "birthday of mohammed" ?
+ // "id al-adha" ?
+ // "id al-fitr" ?
+   ({ "c/good friday",
+      "ethiopia/battle of aduwa",
+      "ethiopia/buhe",
+      "ethiopia/epiphany",
+      "ethiopia/ethiopian new year",
+      "ethiopia/genna",
+      "ethiopia/liberation",
+      "ethiopia/martyrs",
+      "ethiopia/meskel",
+      "ethiopia/patriots victory",
+      "ethiopia/popular revolution commemoration",
+      "ethiopia/revolution",
+      "ethiopia/victory of adowa",
+      "labor" }),
+
+   "falkland islands":
+ // "bank holiday" ?
+   ({ "british commonwealth/queens",
+      "c/christmas",
+      "c/good friday",
+      "falkland islands/anniversary of the battle of the falkland islands",
+      "falkland islands/liberation",
+      "new year" }),
+
+   "fiji":
+ // "diwali" ?
+ // "fiji/deed of cession" ?
+ // "fiji/fiji2" ?
+ // "prophets" ?
+   ({ "c/boxing",
+      "c/christmas",
+      "c/easter",
+      "c/easter eve",
+      "c/easter monday",
+      "c/good friday",
+      "fiji/bank holiday",
+      "fiji/fiji",
+      "fiji/prince charles",
+      "fiji/queens",
+      "new year" }),
+
+   "finland":
+ // "finland/helsinki" ?
+   ({ "c/boxing",
+      "c/christmas",
+      "c/christmas eve",
+      "c/easter monday",
+      "c/good friday",
+      "c/epiphany",
+      "c/pentecost eve",
+      "finland/alexis kivi",
+      "finland/flag",
+      "finland/flag of the army",
+      "finland/independence",
+      "finland/kalevala",
+      "finland/midsummers eve",
+      "finland/runebergs",
+      "finland/snellman",
+      "finland/vappu",
+      "finland/all saints",
+      "finland/midsummer",
+      "may day",
+      "new year" }),
+
+   "france":
+   ({ "c/all saints",
+      "armistice",
+      "c/all souls",
+      "c/ash wednesday",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/pentecost",
+      "france/ascension",
+      "france/bastille",
+      "france/d-day observance",
+      "france/fathers",
+      "france/fete des saintes-maries",
+      "france/fete nationale",
+      "france/liberation",
+      "france/marseillaise",
+      "france/night watch",
+      "new year" }),
+
+   "french guiana":
+ // "bastille" ?
+   ({ "c/all saints",
+      "armistice",
+      "c/all souls",
+      "c/ascension",
+      "c/ash wednesday",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/pentecost",
+      "new year" }),
+
+   "french polynesia":
+   ({ "french polynesia/armistice",
+      "french polynesia/chinese new year",
+      "french polynesia/missionaries arrival commemoration",
+      "may day" }),
+
+   "gabon":
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "mouloud" ?
+   ({ "c/all saints",
+      "c/christmas",
+      "c/easter monday",
+      "c/whitmonday",
+      "gabon/constitution",
+      "gabon/independence",
+      "gabon/renovation",
+      "labor",
+      "new year" }),
+
+   "gambia":
+ // "id al-fitr" ?
+ // "id al-kabir" ?
+ // "mouloud" ?
+   ({ "c/assumption",
+      "c/christmas",
+      "gambia/independence",
+      "gambia/moslem new year",
+      "labor",
+      "new year" }),
+
+   "germany":
+ // "christmas the following religious holidays" ?
+ // "germany/oktoberfest" ?
+ // "observed in certain l\344nder only epiphany" ?
+   ({ "c/all saints",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/corpus christi",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "germany/day of repentance",
+      "germany/day of the workers",
+      "germany/foundation",
+      "germany/national",
+      "germany/unity",
+      "germany/waldchestag",
+      "labor",
+      "new year",
+      "unity" }),
+
+   "ghana":
+ // "ghana/aboakyer" ?
+   ({ "c/boxing",
+      "c/easter eve",
+      "c/easter monday",
+      "c/good friday",
+      "ghana/homowo",
+      "ghana/independence",
+      "ghana/liberation",
+      "ghana/republic",
+      "ghana/revolution",
+      "ghana/third republic",
+      "ghana/uprising",
+      "labor",
+      "new year" }),
+
+   "gibraltar":
+ // "gibraltar/late summer bank holiday" ?
+ // "late summer bank holiday" ?
+ // "queens official" ?
+   ({ "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "gibraltar/commonwealth",
+      "gibraltar/spring bank holiday",
+      "may day",
+      "new year" }),
+
+   "greece":
+ // "greece/dumb week" ?
+   ({ "orthodox/assumption",
+      "orthodox/easter",
+      "orthodox/easter monday",
+      "orthodox/good friday",
+      "orthodox/holy saturday",
+      "orthodox/epiphany",
+      "orthodox/christmas",
+      "greece/clean monday",
+      "greece/independence",
+      "greece/flower festival",
+      "greece/midwifes",
+      "greece/ochi",       
+      "greece/dodecanese accession", // rhodes
+      "saints/demetrios",            // thessaloniki
+      "greece/liberation of xanthi", // xanthi
+      "saints/basil",      
+      "labor",
+      "new year" }),
+
+   "gregorian calendar ":
+   ({ "gregorian calendar /gregorian calendar" }),
+
+   "grenada":
+   ({ "c/boxing",
+      "c/christmas",
+      "c/corpus christi",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "caribbean/emancipation",
+      "grenada/independence",
+      "grenada/national holiday",
+      "grenada/thanksgiving",
+      "labor",
+      "new year" }),
+
+   "guadeloupe":
+ // "bastille" ?
+ // "schoelcher" ?
+   ({ "c/all saints",
+      "armistice",
+      "c/all souls",
+      "c/ash wednesday",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/pentecost",
+      "caribbean/schoelcher",
+      "guadeloupe/ascension",
+      "new year" }),
+
+   "guam":
+ // "george washingtons" ?
+ // "memorial" ?
+ // "thanksgiving" ?
+ // "us independence" ?
+   ({ "c/christmas",
+      "guam/discovery",
+      "guam/guam discovery",
+      "guam/liberation",
+      "labor",
+      "new year" }),
+
+   "guatemala":
+   ({ "c/all saints",
+      "c/assumption",
+      "c/christmas",
+      "c/holy friday",
+      "c/holy saturday",
+      "c/holy thursday",
+      "guatemala/army",
+      "guatemala/bank employees",
+      "guatemala/independence",
+      "guatemala/revolution",
+      "labor",
+      "new year" }),
+
+   "guinea":
+ // "id al-fitr" ?
+ // "mouloud" ?
+   ({ "c/all saints",
+      "c/christmas",
+      "c/easter",
+      "guinea/anniversary of cmrn",
+      "guinea/anniversary of womens revolt",
+      "guinea/day of 1970 invasion",
+      "guinea/independence",
+      "guinea/referendum",
+      "labor",
+      "new year" }),
+
+   "guinea-bissau":
+ // "guinea-bissau/Korit\351(Id al-Fitr)" ?
+ // "guinea-bissau/Tabaski (Id al-Adha)" ?
+   ({ "c/christmas",
+      "guinea-bissau/colonization martyrs",
+      "guinea-bissau/independence",
+      "guinea-bissau/mocidade",
+      "guinea-bissau/national",
+      "guinea-bissau/national heroes",
+      "guinea-bissau/readjustment movement",
+      "labor",
+      "new year" }),
+
+   "guyana":
+ // "diwali" ?
+ // "guyana/Carribean Day (June)" ?
+ // "guyana/Indian Heritage Day (May)" ?
+ // "guyana/Youman Nabi (Mouloud)" ?
+ // "holi" ?
+ // "id al-adha" ?
+ // "id al-fitr" ?
+   ({ "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "guyana/freedom",
+      "guyana/independence",
+      "guyana/republic",
+      "labor",
+      "new year" }),
+
+   "haiti":
+   ({ "haiti/discovery",
+      "haiti/vertieres" }),
+
+   "honduras":
+   ({ "c/christmas",
+      "c/good friday",
+      "c/holy thursday",
+      "columbus",
+      "honduras/armed forces",
+      "honduras/independence",
+      "honduras/morazan",
+      "honduras/thanksgiving",
+      "labor",
+      "new year",
+      "honduras/pan american" }),
+
+   "hong kong":
+ // "hong kong/chung yeung festival" ?
+   ({ "hong kong/birthday of confucious",
+      "hong kong/birthday of pak tai",
+      "hong kong/half-year",
+      "hong kong/liberation" }),
+
+   "iceland":
+   ({ "iceland/independence" }),
+
+   "india":
+   ({ "india/indian independence",
+      "india/mahatma gandhi jayanti",
+      "india/mahatma gandhi martyrdom",
+      "india/republic" }),
+
+   "indonesia":
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "indonesia/balinese new year" ?
+ // "islamic new year" ?
+ // "leilat al-meiraj" ?
+ // "mouloud" ?
+   ({ "c/ascension",
+      "c/christmas",
+      "c/good friday",
+      "indonesia/independence",
+      "indonesia/kartini",
+      "new year" }),
+
+   "iran":
+ // "ashoura" ?
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "leilat al-meiraj" ?
+ // "mouloud" ?
+   ({ "iran/constitution",
+      "iran/islamic republic",
+      "iran/martyrdom of imam ali",
+      "iran/no ruz",
+      "iran/oil nationalization",
+      "iran/revolution",
+      "iran/revolution2" }),
+
+   "iraq":
+ // "ashoura" ?
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "leilat al-meiraj" ?
+ // "mouloud" ?
+   ({ "iraq/14 ramadan revolution",
+      "iraq/army",
+      "iraq/july revolution",
+      "iraq/republic",
+      "new year" }),
+
+   "ireland":
+ // "august" ?
+ // "bank holidays on mondays in june" ?
+ // "october" ?
+ // "saint patricks" ?
+   ({ "c/christmas",
+      "saints/stephen",
+      "c/easter monday",
+      "c/good friday",
+      "ireland/sheelahs",
+      "new year" }),
+
+   "israel":
+ // "holocaust memorial" ?
+ // "independence" ?
+ // "israel/hebrew university" ?
+ // "israel/holocaust memorial" ?
+ // "israel/independence" ?
+ // "israel/national" ?
+ // "lasts)" ?
+ // "passover " ?
+ // "rosh hashanah" ?
+ // "shavuot" ?
+ // "simhat torah" ?
+ // "succot" ?
+ // "yom kippur" ?
+   ({ "israel/balfour declaration",
+      "israel/jerusalem reunification" }),
+
+   "italy":
+ // "italy/saint marks" ?
+   ({ "c/christmas",
+      "italy/anniversary of the republic",
+      "italy/befana",
+      "italy/day of conciliation",
+      "italy/festa del redentore",
+      "italy/joust of the quintana",
+      "italy/liberation",
+      "italy/natale di roma",
+      "italy/palio del golfo",
+      "italy/santo stefano" }),
+
+   "ivory coast":
+ // "id al-adha" ?
+ // "id al-fitr" ?
+   ({ "c/all saints",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "ivory coast/independence",
+      "ivory coast/national holiday of the ivory coast",
+      "labor",
+      "new year" }),
+
+   "jamaica":
+   ({ "c/ash wednesday",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "jamaica/heroes",
+      "jamaica/independence",
+      "jamaica/labor",
+      "labor",
+      "new year" }),
+
+   "japan":
+ // "autumn equinox" ?
+ // "health sports" ?
+ // "japan/autumnal equinox" ?
+ // "japan/black ship" ?
+ // "japan/bon" ?
+ // "japan/health" ?
+ // "japan/memorial" ?
+ // "japan/peoples holiday" ?
+ // "japan/shichigosan" ?
+ // "japan/vernal equinox" ?
+ // "vernal equinox" ?
+   ({ "japan/adults",
+      "japan/bean-throwing festival",
+      "japan/childrens",
+      "japan/childrens protection",
+      "japan/constitution",
+      "japan/culture",
+      "japan/emperors",
+      "japan/empire",
+      "japan/gion matsuri",
+      "japan/greenery",
+      "japan/hina matsuri",
+      "japan/hiroshima peace festival",
+      "japan/hollyhock festival",
+      "japan/jidai matsuri",
+      "japan/kakizome",
+      "japan/kambutsue",
+      "japan/kite battles of hamamatsu",
+      "japan/labor thanksgiving",
+      "japan/martyr",
+      "japan/memorial to broken dolls",
+      "japan/national foundation",
+      "japan/respect for the aged",
+      "japan/sanno matsuri",
+      "japan/shigoto hajime",
+      "japan/tanabata",
+      "japan/tango-no-sekku",
+      "new year" }),
+
+   "jordan":
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "leilat al-meiraj" ?
+ // "mouloud" ?
+   ({ "arab league",
+      "jordan/arbor",
+      "jordan/coronation",
+      "jordan/independence",
+      "jordan/king hussein" }),
+
+   "kenya":
+ // "id al-fitr" ?
+   ({ "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "kenya/independence",
+      "kenya/kenyatta",
+      "kenya/madaraka",
+      "labor",
+      "new year" }),
+
+   "kiribati":
+   ({ "c/christmas",
+      "c/easter",
+      "kiribati/independence",
+      "kiribati/youth",
+      "new year" }),
+
+   "korea":
+   ({ "korea/independence movement" }),
+
+   "kuwait":
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "leilat al-meiraj" ?
+ // "mouloud" ?
+ // "start of ramadan" ?
+   ({ "kuwait/independence",
+      "kuwait/national",
+      "new year" }),
+
+   "laos":
+ // "chinese new year" ?
+ // "laos/army" ?
+   ({ "labor",
+      "laos/constitution",
+      "laos/independence",
+      "laos/memorial",
+      "laos/pathet lao",
+      "laos/republic" }),
+
+   "latvia":
+ // "indpendence" ?
+   ({ "c/christmas",
+      "c/good friday",
+      "latvia/independence",
+      "latvia/midsummer festival",
+      "new year",
+      "new years eve" }),
+
+   "lebanon":
+ // "ashoura" ?
+ // "chrismas" ?
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "leilat al-meiraj" ?
+ // "mouloud" ?
+ // "orthodox easter" ?
+   ({ "c/all saints",
+      "arab league",
+      "c/ascension",
+      "c/assumption",
+      "c/easter",
+      "lebanon/evacuation",
+      "lebanon/independence",
+      "lebanon/martyrs",
+      "lebanon/saint maron",
+      "new year" }),
+
+   "lesotho":
+   ({ "c/ascension",
+      "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "family",
+      "lesotho/family",
+      "lesotho/independence",
+      "lesotho/kings",
+      "lesotho/moshoeshoes",
+      "lesotho/national holiday",
+      "lesotho/national sports",
+      "lesotho/national tree planting",
+      "new year" }),
+
+   "liberia":
+ // "fast" ?
+ // "integration" ?
+ // "prayer" ?
+ // "unification" ?
+   ({ "c/christmas",
+      "c/good friday",
+      "liberia/armed forces",
+      "liberia/decoration",
+      "liberia/fast and prayer",
+      "liberia/flag",
+      "liberia/independence",
+      "liberia/j j roberts",
+      "liberia/literacy",
+      "liberia/matilda newport",
+      "liberia/memorial",
+      "liberia/national redemption",
+      "liberia/pioneers",
+      "liberia/president tubmans",
+      "liberia/thanksgiving",
+      "liberia/unification and integration",
+      "new year" }),
+
+   "libya":
+ // "ashoura" ?
+ // "expulsion of fascist settlers" ?
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "leilat al-meiraj" ?
+ // "libya/troop withdrawal" ?
+ // "mouloud" ?
+   ({ "libya/evacuation",
+      "libya/expulsion of the fascist settlers",
+      "libya/kings",
+      "libya/national",
+      "libya/revolution",
+      "libya/sanusi army" }),
+
+   "liechtenstein":
+ // "saint josephs" ?
+   ({ "c/all saints",
+      "saints/stephen",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/corpus christi",
+      "c/easter",
+      "c/good friday",
+      "c/immaculate conception",
+      "c/nativity of mary",
+      "c/whitmonday",
+      "c/epiphany",
+      "labor",
+      "liechtenstein/birthday of prince franz-josef ii",
+      "liechtenstein/national",
+      "new year" }),
+
+   "lithuania":
+ // "national of hope" ?
+   ({ "c/christmas",
+      "lithuania/coronation",
+      "lithuania/independence",
+      "lithuania/mourning",
+      "new year" }),
+
+   "luxembourg":
+   ({ "c/all saints",
+      "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "luxembourg/burgsonndeg",
+      "luxembourg/grand duchess",
+      "luxembourg/liberation",
+      "luxembourg/national",
+      "new year" }),
+
+   "macao":
+ // "chinese mid-autumn festival" ?
+ // "chinese new year" ?
+ // "ching ming" ?
+ // "dragon boat festival" ?
+ // "festival of ancestors" ?
+ // "macao/hungry ghosts" ?
+ // "national of china" ?
+ // "portugal" ?
+ // "portuguese republic" ?
+ // "restoration of the independence" ?
+ // "saint johns" ?
+ // "winter solstice" ?
+   ({ "c/all souls",
+      "c/christmas",
+      "c/good friday",
+      "c/immaculate conception",
+      "labor",
+      "macao/anniversary of the portugese revolution",
+      "macao/battle of july 13",
+      "macao/procession of our lady of fatima",
+      "macao/republic",
+      "new year" }),
+
+   "madagascar":
+   ({ "c/all saints",
+      "c/ascension",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitsunday",
+      "labor",
+      "madagascar/commemoration",
+      "madagascar/independence",
+      "madagascar/republic",
+      "new year" }),
+
+   "malawi":
+ // "but usually jul 5-7)" ?
+   ({ "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "malawi/august holiday",
+      "malawi/kamuzu",
+      "malawi/martyrs",
+      "malawi/mothers",
+      "malawi/national tree-planting",
+      "malawi/republic",
+      "mothers",
+      "new year" }),
+
+   "malaysia":
+ // "chinese new year" ?
+ // "diwali " ?
+ // "each state has its own public holidays" ?
+ // "malaysia/Hari Raya Haji (Id al-Adha)" ?
+ // "malaysia/Hari Raya Puasa (Id al-Fitr)" ?
+ // "malaysia/additional public holiday in kuala lumpur" ?
+ // "mouloud in addition" ?
+ // "sarawak)" ?
+ // "vesak" ?
+   ({ "c/christmas",
+      "labor",
+      "malaysia/kings",
+      "malaysia/malaysia" }),
+
+   "maldives":
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "mouloud" ?
+   ({ "maldives/fisheries",
+      "maldives/independence",
+      "maldives/national",
+      "maldives/republic",
+      "maldives/victory" }),
+
+   "mali":
+ // "mali/Korit\351(Id al-Fitr)" ?
+ // "mali/Tabaski (Id al-Adha)" ?
+ // "mouloud" ?
+   ({ "africa",
+      "c/christmas",
+      "c/easter monday",
+      "labor",
+      "mali/army",
+      "mali/independence",
+      "mali/liberation",
+      "new year" }),
+
+   "malta":
+ // "malta/Feast of Our Lady of Victories (Nativity of Mary)" ?
+ // "saint josephs" ?
+ // "saint pauls shipwreck" ?
+   ({ "saints/paul",
+      "saints/peter",
+      "c/assumption",
+      "c/christmas",
+      "c/good friday",
+      "c/immaculate conception",
+      "labor",
+      "malta/freedom",
+      "malta/independence",
+      "malta/memorial of 1919 riot",
+      "malta/republic",
+      "new year" }),
+
+   "marshall islands":
+   ({ "marshall islands/proclamation of the republic of marshall islands" }),
+
+   "martinique":
+ // "bastille" ?
+ // "lundi-gras" ?
+ // "mardi-gras" ?
+   ({ "c/all saints",
+      "armistice",
+      "c/all souls",
+      "c/ash wednesday",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/pentecost",
+      "martinique/ascension",
+      "new year" }),
+
+   "mauritania":
+ // "islamic new year" ?
+ // "leilat al-meiraj" ?
+ // "mauritania/Korit\351(Id al-Fitr)" ?
+ // "mauritania/Tabaski (Id al-Adha)" ?
+ // "mouloud" ?
+   ({ "africa",
+      "labor",
+      "mauritania/independence",
+      "new year" }),
+
+   "mauritius":
+ // "diwali" ?
+ // "ganesh chaturi" ?
+ // "id al-fitr" ?
+ // "maha shivaratree" ?
+ // "mauritius/Chinese Spring Festival (Chinese New Year)" ?
+ // "mauritius/Ougadi (Hindu)" ?
+ // "thaipusam" ?
+   ({ "c/all saints",
+      "c/christmas",
+      "c/good friday",
+      "labor",
+      "mauritius/independence",
+      "new year" }),
+
+   "mexico":
+ // "birthday of benito juarez easter" ?
+ // "but not public holidays" ?
+ // "christmas in addition" ?
+ // "mexico/Day of the Dead (All Souls' Day)" ?
+ // "widely celebrated" ?
+   ({ "c/christmas",
+      "labor",
+      "mexico/birthday of benito juarez",
+      "mexico/cinco de mayo",
+      "mexico/constitution",
+      "mexico/day of mourning",
+      "mexico/dia de la raza",
+      "mexico/holy cross",
+      "mexico/independence",
+      "mexico/night of the radishes",
+      "mexico/our lady of guadalupe",
+      "mexico/posadass",
+      "mexico/presidential message",
+      "mexico/revolution",
+      "mexico/san marc\363s",
+      "new year" }),
+
+   "micronesia":
+ // "micronesia/national holiday" ?
+   ({  }),
+
+   "monaco":
+ // "monaco/F\352te du Travail (Labor Day)" ?
+   ({ "c/all saints",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "c/immaculate conception",
+      "c/whitmonday",
+      "monaco/monaco national festival",
+      "new year",
+      "saints/devote" }),
+
+   "mongolia":
+ // "mongolia/Tsagaan Sar (lunar new year)" ?
+   ({ "mongolia/national",
+      "mongolia/republic",
+      "new year",
+      "womens" }),
+
+   "montserrat":
+ // "august monday" ?
+ // "queens official" ?
+ // "saint patricks" ?
+   ({ "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "labor",
+      "montserrat/festival",
+      "montserrat/liberation",
+      "new year" }),
+
+   "mormonism":
+   ({ "mormonism/founding of the mormon church" }),
+
+   "morocco":
+ // "ashoura" ?
+ // "first of ramadan" ?
+ // "islamic new year" ?
+ // "morocco/Eid el Kebir (Id al-Adha)" ?
+ // "morocco/Eid el Seghir (Id al-Fitr)" ?
+ // "mouloud" ?
+   ({ "labor",
+      "morocco/green march",
+      "morocco/independence",
+      "morocco/oued ed-dahab",
+      "morocco/throne",
+      "new year" }),
+
+   "mozambique":
+   ({ "family",
+      "mozambique/armed forces",
+      "mozambique/heroes",
+      "mozambique/independence",
+      "mozambique/lusaka agreement",
+      "mozambique/universal fraternity",
+      "mozambique/womens",
+      "mozambique/workers",
+      "new year" }),
+
+   "myanmar":
+ // "burmese new year" ?
+ // "diwali" ?
+ // "full moon of kason" ?
+ // "full moon of tabaung" ?
+ // "full moon of thadingyut" ?
+ // "full moon of waso" ?
+ // "id al-adha" ?
+ // "karen new year" ?
+ // "myanmar/Water Festival (Maha Thingyan)" ?
+ // "myanmar/burmese new year" ?
+ // "tazaundaing festival" ?
+   ({ "c/christmas",
+      "labor",
+      "myanmar/armed forces",
+      "myanmar/independence",
+      "myanmar/martyrs",
+      "myanmar/national",
+      "myanmar/peasants",
+      "myanmar/resistance",
+      "myanmar/union" }),
+
+   "namibia":
+ // "human rights" ?
+   ({ "africa",
+      "c/ascension",
+      "c/christmas",
+      "c/easter",
+      "family",
+      "namibia/casinga",
+      "namibia/day of goodwill",
+      "namibia/family",
+      "namibia/heroes",
+      "namibia/independence",
+      "namibia/workers",
+      "new year" }),
+
+   "nauru":
+   ({ "c/christmas",
+      "c/easter",
+      "nauru/angam",
+      "nauru/independence",
+      "new year" }),
+
+   "nepal":
+ // "diwali" ?
+ // "holi" ?
+ // "indra jatra" ?
+ // "nepal/Baishakh Purnima (Buddha's birthday)" ?
+ // "nepal/Dasain (Durga Puja)" ?
+ // "nepal/Martyrs' Day (near Jan 30)" ?
+ // "nepal/Navabarsha (Baisakhi)" ?
+ // "nepal/buddha jayanti" ?
+ // "ramnavami" ?
+ // "shiva ratri" ?
+ // "united nations" ?
+   ({ "nepal/birthday of king birendra",
+      "nepal/constitution",
+      "nepal/democracy",
+      "nepal/independence",
+      "nepal/kings",
+      "nepal/national unity",
+      "nepal/queens",
+      "nepal/tij",
+      "womens" }),
+
+   "netherlands":
+   ({ "c/ascension",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "netherlands/beggars",
+      "netherlands/independence",
+      "netherlands/liberation",
+      "netherlands/queens",
+      "netherlands/sinterklaas",
+      "new year" }),
+
+   "netherlands antilles":
+ // "christmas additional public holidays: lenten carnival in cura\347ao" ?
+ // "whitmonday in st maarten" ?
+   ({ "c/ascension",
+      "c/easter monday",
+      "c/good friday",
+      "labor",
+      "netherlands antilles/bonaire",
+      "netherlands antilles/cura\347ao",
+      "netherlands antilles/queens",
+      "netherlands antilles/saba",
+      "netherlands antilles/saint eustatius",
+      "netherlands antilles/saint maarten",
+      "new year" }),
+
+   "new caledonia":
+ // "bastille" ?
+ // "liberation" ?
+   ({ "armistice",
+      "c/ascension",
+      "c/christmas",
+      "c/easter monday",
+      "c/whitmonday",
+      "labor",
+      "new year" }),
+
+   "new zealand":
+   ({ "anzac",
+      "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "labor",
+      "new year",
+      "new zealand/labor",
+      "new zealand/queens",
+      "new zealand/waitangi" }),
+
+   "nicaragua":
+   ({ "c/all souls",
+      "c/christmas",
+      "c/easter",
+      "c/holy friday",
+      "c/holy thursday",
+      "labor",
+      "new year",
+      "nicaragua/air force",
+      "nicaragua/army",
+      "nicaragua/fiesta",
+      "nicaragua/independence",
+      "nicaragua/revolution",
+      "nicaragua/san jacinto" }),
+
+   "niger":
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "mouloud" ?
+   ({ "c/christmas",
+      "c/easter monday",
+      "labor",
+      "new year",
+      "niger/independence",
+      "niger/national",
+      "niger/republic" }),
+
+   "nigeria":
+ // "id al-fitr" ?
+ // "mouloud" ?
+ // "nigeria/Id al-Kabir (Id al-Adha)" ?
+ // "nigeria/odum titun" ?
+ // "nigeria/odun kekere" ?
+   ({ "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "new year",
+      "nigeria/childrens",
+      "nigeria/harvest festival",
+      "nigeria/national" }),
+
+   "northern mariana islands":
+ // "memorial" ?
+ // "thanksgiving" ?
+ // "us independence" ?
+   ({ "c/christmas",
+      "labor",
+      "new year",
+      "northern mariana islands/commonwealth",
+      "northern mariana islands/presidents" }),
+
+   "norway":
+   ({ "c/ascension",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/holy thursday",
+      "c/whitmonday",
+      "may day",
+      "new year",
+      "norway/constitution",
+      "norway/olsok eve festival",
+      "norway/tyvendedagen" }),
+
+   "oman":
+ // "ashoura" ?
+ // "first of ramadan" ?
+ // "id al-adha" ?
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "islamic new year" ?
+ // "leilat al-meiraj" ?
+ // "mouloud" ?
+ // "prophets" ?
+   ({ "oman/national",
+      "oman/national of oman",
+      "oman/national2",
+      "oman/sultans" }),
+
+   "pakistan":
+ // "ashoura" ?
+ // "first of ramadan" ?
+ // "id al-adha optional holidays for christians" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "pakistan/Eid-i-Milad-un-Nabi (Mouloud)" ?
+   ({ "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "labor",
+      "pakistan/birthday of quaid-i-azam",
+      "pakistan/defense",
+      "pakistan/independence",
+      "pakistan/iqbal",
+      "pakistan/jinnah",
+      "pakistan/pakistan" }),
+
+   "panama":
+ // "christmas in panama city" ?
+ // "panama/Carnival (Shrove Tuesday)" ?
+   ({ "c/all souls",
+      "c/good friday",
+      "labor",
+      "mothers",
+      "new year",
+      "panama/constitution",
+      "panama/day of mourning",
+      "panama/festival of the black christ",
+      "panama/flag",
+      "panama/foundation of panama city",
+      "panama/independence",
+      "panama/independence from spain",
+      "panama/mothers",
+      "panama/national anthem",
+      "panama/revolution",
+      "panama/uprising of los santos" }),
+
+   "papua new guinea":
+   ({ "british commonwealth/queens",
+      "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "new year",
+      "papua new guinea/independence",
+      "papua new guinea/remembrance" }),
+
+   "paraguay":
+   ({ "c/all saints",
+      "c/ascension",
+      "c/christmas",
+      "c/corpus christi",
+      "c/good friday",
+      "c/holy thursday",
+      "labor",
+      "new year",
+      "paraguay/battle of boquer\363n",
+      "paraguay/constitution",
+      "paraguay/day of the race",
+      "paraguay/founding of the city of asunci\363n",
+      "paraguay/heroes",
+      "paraguay/independence",
+      "paraguay/peace of chaco",
+      "paraguay/virgin of caacupe",
+      "saints/blaise" }),
+
+   "peru":
+ // "peasants" ?
+   ({ "saints/paul",
+      "saints/peter",
+      "c/all saints",
+      "c/christmas",
+      "c/good friday",
+      "c/holy thursday",
+      "c/immaculate conception",
+      "labor",
+      "new year",
+      "peru/combat of angamos",
+      "peru/independence",
+      "peru/inti raymi fiesta",
+      "peru/santa rosa de lima" }),
+
+   "philippines":
+   ({ "c/all saints",
+      "c/christmas",
+      "c/good friday",
+      "c/maundy thursday",
+      "labor",
+      "new year",
+      "new years eve",
+      "philippines/araw ng kagitingan",
+      "philippines/barangay",
+      "philippines/bataan",
+      "philippines/bonifacio",
+      "philippines/christ the king",
+      "philippines/constitution",
+      "philippines/freedom",
+      "philippines/independence",
+      "philippines/misa de gallo",
+      "philippines/national heroes",
+      "philippines/philippine-american friendship",
+      "philippines/rizal",
+      "philippines/thanksgiving" }),
+
+   "portugal":
+ // "porto observes the st john the baptist" ?
+ // "portugal/Carnival (Shrove Tuesday)" ?
+   ({ "c/all saints",
+      "c/assumption",
+      "c/corpus christi",
+      "c/good friday",
+      "c/immaculate conception",
+      "labor",
+      "new year",
+      "portugal/cam\365es memorial",
+      "portugal/christmas lisbon also observes the st anthony",
+      "portugal/day of the dead",
+      "portugal/liberty",
+      "portugal/portugal",
+      "portugal/republic",
+      "portugal/restoration of the independence" }),
+
+   "puerto rico":
+ // "martin luther king" ?
+ // "us independence" ?
+ // "us thanksgiving" ?
+ // "veterans" ?
+ // "washington-lincoln" ?
+   ({ "c/christmas",
+      "c/good friday",
+      "columbus",
+      "c/epiphany",
+      "labor",
+      "new year",
+      "puerto rico/barbosa",
+      "puerto rico/birthday of eugenio maria de hostos",
+      "puerto rico/constitution",
+      "puerto rico/de diego",
+      "puerto rico/discovery",
+      "puerto rico/emancipation",
+      "puerto rico/memorial",
+      "puerto rico/mu\361oz rivera",
+      "puerto rico/ponce de leon",
+      "puerto rico/saint johns",
+      "puerto rico/san juan" }),
+
+   "qatar":
+ // "first of ramadan" ?
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "leilat al-meiraj" ?
+   ({ "qatar/anniversary of the amirs accession",
+      "qatar/independence" }),
+
+   "romania":
+   ({ "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "labor",
+      "new year",
+      "romania/liberation",
+      "romania/national",
+      "romania/public holiday" }),
+
+   "rwanda":
+ // "peace" ?
+   ({ "c/all saints",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "c/whitmonday",
+      "labor",
+      "new year",
+      "rwanda/armed forces",
+      "rwanda/democracy",
+      "rwanda/independence",
+      "rwanda/kamarampaka",
+      "rwanda/peace and unity",
+      "unity" }),
+
+   "saint kitts and nevis":
+ // "august monday" ?
+   ({ "british commonwealth/queens",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "labor",
+      "saint kitts and nevis/carnival",
+      "saint kitts and nevis/independence",
+      "saint kitts and nevis/prince of wales" }),
+
+   "saint lucia":
+ // "carnival" ?
+   ({ "british commonwealth/august bank holiday",
+      "british commonwealth/queens",
+      "c/boxing",
+      "c/christmas",
+      "c/corpus christi",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "labor",
+      "new year",
+      "saint lucia/discovery",
+      "saint lucia/independence",
+      "saint lucia/thanksgiving" }),
+
+   "saint vincent and the grenadines":
+ // "carnival" ?
+ // "grenadines" ?
+ // "saint vincent" ?
+   ({ "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "caribbean/caricom",
+      "caribbean/emancipation",
+      "labor",
+      "new year",
+      "saint vincent and the grenadines/independence",
+      "saint vincent and the grenadines/saint vincent and the grenadines" }),
+
+   "san marino":
+   ({ "c/all saints",
+      "saints/stephen",
+      "c/all souls",
+      "c/assumption",
+      "c/christmas",
+      "c/corpus christi",
+      "c/easter monday",
+      "c/immaculate conception",
+      "c/epiphany",
+      "labor",
+      "new year",
+      "san marino/anniversary of the arengo",
+      "san marino/fall of fascism",
+      "san marino/investiture of the new captains regent",
+      "san marino/investiture of the new captains-regent",
+      "san marino/liberation",
+      "san marino/national",
+      "san marino/san marino" }),
+
+   "sao tome and principe":
+ // "sao tomeand principe/Armed Forces Day (1st week in Sep)" ?
+   ({ "family",
+      "sao tome and principe/farmers",
+      "sao tome and principe/independence",
+      "sao tome and principe/martyrs",
+      "sao tome and principe/transitional government" }),
+
+   "saudi arabia":
+ // "ashoura" ?
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "leilat al-meirag" ?
+ // "mouloud" ?
+   ({ "saudi arabia/national",
+      "saudi arabia/national of saudi arabia" }),
+
+   "senegal":
+ // "mouloud" ?
+ // "senegal/Korit\351 (Id al-Fitr)" ?
+ // "senegal/Tabaski (Id al-Adha)" ?
+   ({ "c/all saints",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "labor",
+      "new year",
+      "senegal/african community",
+      "senegal/independence" }),
+
+   "seychelles":
+   ({ "c/all saints",
+      "c/assumption",
+      "c/christmas",
+      "c/corpus christi",
+      "c/easter",
+      "c/immaculate conception",
+      "labor",
+      "new year",
+      "seychelles/independence",
+      "seychelles/liberation" }),
+
+   "sierra leone":
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "mouloud" ?
+   ({ "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "new year",
+      "sierra leone/independence",
+      "sierra leone/republic" }),
+
+   "singapore":
+ // "chinese new year" ?
+ // "singapore/Deepavali (Diwali)" ?
+ // "singapore/Hari Raya Haji (Id al-Adha)" ?
+ // "singapore/Hari Raya Puasa (Id al-Fitr)" ?
+ // "singapore/birthday of the monkey god" ?
+ // "singapore/birthday of the saint of the poor" ?
+ // "singapore/mooncake festival" ?
+ // "singapore/vesak" ?
+ // "vesak" ?
+   ({ "c/christmas",
+      "c/good friday",
+      "new year",
+      "singapore/independence",
+      "singapore/labor",
+      "singapore/national holiday" }),
+
+   "slovakia":
+   ({ "c/christmas",
+      "c/easter monday",
+      "may day",
+      "new year",
+      "slovakia/day of the slav apostles",
+      "slovakia/liberation",
+      "slovakia/reconciliation",
+      "slovakia/slovak national uprising" }),
+
+   "slovenia":
+   ({  }),
+
+   "solomon islands":
+   ({ "british commonwealth/queens",
+      "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/holy saturday",
+      "c/whitmonday",
+      "new year",
+      "solomon islands/independence" }),
+
+   "somalia":
+ // "ashoura" ?
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "mouloud" ?
+   ({ "labor",
+      "new year",
+      "somalia/foundation of the republic",
+      "somalia/independence",
+      "somalia/revolution" }),
+
+   "south africa":
+   ({ "c/ascension",
+      "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "new year",
+      "south africa/day of the vow",
+      "south africa/family",
+      "south africa/kruger",
+      "south africa/republic",
+      "south africa/settlers",
+      "south africa/van riebeeck",
+      "south africa/workers" }),
+
+   "soviet union":
+   ({ "soviet union/anniversary of the october socialist revolution",
+      "soviet union/victory" }),
+
+
+   "spain":
+ // "also observed" ?
+ // "madrid only)" ?
+ // "palma de mallorca)" ?
+ // "palma de mallorca) local holidays" ?
+ // "saint isidros " ?
+ // "spain/tomatina" ?
+   ({ "c/all saints",
+      "c/assumption",
+      "c/boxing",
+      "c/christmas",
+      "c/corpus christi",
+      "c/easter monday",
+      "c/good friday",
+      "c/immaculate conception",
+      "c/maundy thursday",
+      "c/epiphany",
+      "new year",
+      "spain/constitution",
+      "spain/fiesta de san fermin",
+      "spain/fiesta del arbol",
+      "spain/grenada",
+      "spain/hispanidad",
+      "spain/king juan carlos saints",
+      "spain/labor",
+      "spain/national",
+      "spain/national holiday of spain",
+      "spain/queen isabella",
+      "spain/saint james",
+      "spain/saint joseph the workman" }),
+
+   "sri lanka":
+ // "there is a monthy full moon" ?
+ // "diwali" ?
+ // "holy prophets" ?
+ // "sinhala" ?
+ // "sri lanka/bandaranaike memorial" ?
+ // "sri lanka/hadji festival" ?
+ // "sri lanka/kandy perahera" ?
+ // "sri lanka/thai pongal" ?
+ // "sri lanka/vesak festival" ?
+ // "tamil new year" ?
+ // "tamil thai pongal" ?
+   ({ "c/good friday",
+      "c/christmas",	
+      "may day",
+      "new year",
+      "sri lanka/independence",
+      "sri lanka/national heroes",
+      "sri lanka/republic",
+      "sri lanka/sinhala and tamil new year" }),
+
+   "sudan":
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "mououd" ?
+ // "sudan/Sham an-Nassim (Coptic Easter Monday)" ?
+   ({ "c/christmas",
+      "new year",
+      "sudan/decentralization",
+      "sudan/independence",
+      "sudan/national",
+      "sudan/unity",
+      "sudan/uprising" }),
+
+   "suriname":
+ // "id al-fitr" ?
+ // "suriname/Phagwa (Holi)" ?
+   ({ "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "labor",
+      "new year",
+      "suriname/independence",
+      "suriname/national union",
+      "suriname/revolution" }),
+
+   "swaziland":
+ // "incwala" ?
+ // "national flag" ?
+ // "swaziland/incwala" ?
+ // "united nations" ?
+   ({ "c/ascension",
+      "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "new year",
+      "swaziland/commonwealth",
+      "swaziland/flag",
+      "swaziland/kings",
+      "swaziland/reed dance",
+      "swaziland/somhlolo" }),
+
+   "switzerland":
+   ({ "c/ascension",
+      "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "c/whitmonday",
+      "labor",
+      "new year",
+      "switzerland/berchtolds",
+      "switzerland/glarus festival",
+      "switzerland/homstrom",
+      "switzerland/independence",
+      "switzerland/may eve" }),
+
+   "syria":
+ // "egypts revolution" ?
+ // "greek orthodox easter" ?
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "leilat al-meiraj" ?
+ // "mouloud" ?
+   ({ "c/christmas",
+      "new year",
+      "syria/beginning of october war",
+      "syria/evacuation",
+      "syria/national",
+      "syria/revolution",
+      "syria/union",
+      "unity" }),
+
+   "taiwan":
+ // "chinese new year" ?
+ // "ching ming festival" ?
+ // "taiwan/birthday of matsu" ?
+ // "taiwan/lantern festival" ?
+   ({ "taiwan/birthday of confucious",
+      "taiwan/buddha bathing festival",
+      "taiwan/chiang kai-shek",
+      "taiwan/childrens",
+      "taiwan/constitution",
+      "taiwan/dragon boat festival",
+      "taiwan/founding of the republic of china",
+      "taiwan/martyrs",
+      "taiwan/national",
+      "taiwan/restoration",
+      "taiwan/sun yat-sen",
+      "taiwan/youth" }),
+
+   "tanzania":
+ // "id al-fitr" ?
+ // "mouloud" ?
+ // "tanzania/Id al-Hajj (Id al-Adha)" ?
+   ({ "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "labor",
+      "tanzania/chama cha mapinduzi",
+      "tanzania/heroes",
+      "tanzania/independence",
+      "tanzania/naming",
+      "tanzania/saba saba",
+      "tanzania/sultans",
+      "tanzania/union",
+      "tanzania/zanzibar revolution" }),
+
+   "thailand":
+ // "buddhist lent" ?
+ // "makha bucha" ?
+ // "thailand/loy krathong festival" ?
+ // "thailand/makha bucha" ?
+ // "thailand/state ploughing ceremony" ?
+ // "thailand/visakha bucha" ?
+ // "visakha bucha" ?
+   ({ "new year",
+      "new years eve",
+      "thailand/asalapha bupha",
+      "thailand/chakri",
+      "thailand/chulalongkorn",
+      "thailand/constitution",
+      "thailand/coronation",
+      "thailand/harvest festival",
+      "thailand/kings",
+      "thailand/queens",
+      "thailand/songkran" }),
+
+   "togo":
+ // "id al-fitr" ?
+ // "national liberation" ?
+ // "togo/Tabaski (Id al-Adha)" ?
+   ({ "c/all saints",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/easter monday",
+      "c/whitmonday",
+      "labor",
+      "new year",
+      "togo/anniversary of the failed attack on lome",
+      "togo/economic liberation",
+      "togo/independence",
+      "togo/liberation",
+      "togo/martyrs of pya",
+      "togo/victory" }),
+
+   "tonga":
+   ({ "anzac",
+      "c/boxing",
+      "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "new year",
+      "tonga/constitution",
+      "tonga/emancipation",
+      "tonga/king tupou",
+      "tonga/kings",
+      "tonga/princes" }),
+
+   "trinidad and tobago":
+ // "carnival" ?
+ // "diwali" ?
+   ({ "c/christmas",
+      "c/corpus christi",
+      "c/easter",
+      "c/whitmonday",
+      "new year",
+      "trinidad and tobago/discovery",
+      "trinidad and tobago/emancipation",
+      "trinidad and tobago/independence",
+      "trinidad and tobago/labor",
+      "trinidad and tobago/republic" }),
+
+   "tunisia":
+ // "evacuaton" ?
+ // "tunisia/Aid El Kebir (Id al-Adha)" ?
+ // "tunisia/Aid El Seghir (Id al-Fitr)" ?
+   ({ "labor",
+      "new year",
+      "tunisia/accession",
+      "tunisia/bourguibas",
+      "tunisia/evacuation",
+      "tunisia/independence",
+      "tunisia/independence recognition",
+      "tunisia/martyrs",
+      "tunisia/memorial",
+      "tunisia/national holiday of tunisia",
+      "tunisia/national revolution",
+      "tunisia/republic",
+      "tunisia/tree festival",
+      "tunisia/womens",
+      "tunisia/youth",
+      "womens" }),
+
+   "turkey":
+ // "ataturk memorial" ?
+ // "childrens" ?
+ // "national sovereignty" ?
+ // "turkey/Kurban Bayram (Id al-Adha)" ?
+ // "turkey/Seker Bayram (Id al-Fitr)" ?
+ // "youth & sports" ?
+   ({ "new year",
+      "turkey/ataturk commemoration",
+      "turkey/youth and sports",
+      "turkey/freedom and constitution",
+      "turkey/hidrellez",
+      "turkey/independence",
+      "turkey/childrens",
+      "turkey/national sovereignty",
+      "turkey/navy and merchant marine",
+      "turkey/rumis",
+      "turkey/spring",
+      "turkey/victory" }),
+
+   "turks and caicos islands":
+ // "commonwealth" ?
+ // "national heroes" ?
+ // "national youth" ?
+ // "queens official" ?
+   ({ "c/christmas",
+      "c/easter monday",
+      "c/good friday",
+      "new year",
+      "turks and caicos islands/columbus",
+      "turks and caicos islands/emancipation",
+      "turks and caicos islands/human rights",
+      "turks and caicos islands/jags mccartney memorial" }),
+
+   "tuvalu":
+ // "commonwealth" ?
+ // "national childrens" ?
+   ({ "british commonwealth/prince of wales",
+      "british commonwealth/queens",
+      "c/boxing",
+      "c/christmas",
+      "c/easter",
+      "new year",
+      "tuvalu/tuvalu" }),
+
+   "uganda":
+ // "id al-adha" ?
+ // "id al-fitr" ?
+   ({ "c/christmas",
+      "c/easter",
+      "c/good friday",
+      "labor",
+      "new year",
+      "uganda/heroes",
+      "uganda/independence",
+      "uganda/martyrs",
+      "uganda/nrm/nra victorys",
+      "uganda/republic" }),
+
+   "ukraine":
+   ({ "c/christmas",
+      "labor",
+      "new year",
+      "orthodox/christmas",
+      "ukraine/taras shevchenko",
+      "ukraine/ukrainian",
+      "ukraine/ukrainian independence",
+      "ukraine/victory",
+      "womens" }),
+
+   "united arab emirates":
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "islamic new year" ?
+ // "leilat al-meiraj" ?
+ // "mouloud" ?
+ // "ramadan 1" ?
+   ({ "c/christmas",
+      "new year",
+      "united arab emirates/accession of the ruler of abu dhabi",
+      "united arab emirates/national" }),
+
+   "uruguay":
+   ({ "c/all souls",
+      "c/christmas",
+      "columbus",
+      "c/epiphany",
+      "labor",
+      "new year",
+      "uruguay/artigas",
+      "uruguay/battle of las piedras",
+      "uruguay/blessing of the waters",
+      "uruguay/constitution",
+      "uruguay/independence",
+      "uruguay/landing of the 33 patriots" }),
+
+   "united kingdom":
+   ({ "new year|h",
+      "c/good friday|h",
+      "c/easter monday|h",
+      "c/christmas|h",
+      "c/boxing|h",
+      "may day|h",
+      "united kingdom/spring bank holiday|h",
+      "united kingdom/late summer bank holiday|h",
+      "united kingdom/lammas",
+      "united kingdom/queens",
+      "united kingdom/burns", }),
+
+   "united kingdom/england":
+   ({ "+united kingdom",
+      "united kingdom/guy fawkes",
+      "united kingdom/oak apple",
+      "united kingdom/battle of britain",
+      "united kingdom/lord mayors",
+      "united kingdom/mothering sunday",
+      "united kingdom/woman peerage",
+      "united kingdom/pancake tuesday" }),
+
+   "united kingdom/scotland":
+   ({ "+united kingdom",
+      "united kingdom/bannockburn",
+      "united kingdom/day after",
+      "united kingdom/handsel monday",
+      "united kingdom/highland games",
+      "united kingdom/scottish new year|h",
+      "united kingdom/victoria|h",
+      "united kingdom/autumn holiday|h" }),
+   
+   "united kingdom/wales":
+   ({ "+united kingdom",
+      "saints/david|h" }),
+
+   "united kingdom/northern ireland":
+   ({ "+united kingdom",
+      "united kingdom/orangeman|h",
+      "saints/patrick" }),
+
+   "us":
+   ({ "new year|h",
+      "c/christmas",
+      "us/columbus|h",
+      "mardi gras",
+      "us/appomattox",
+      "us/armed forces",
+      "us/bill of rights",
+      "us/carnation",
+      "us/citizenship",
+      "us/election",
+      "us/flag|f",
+      "us/forefathers",
+      "us/inauguration",
+      "us/independence|h",
+      "us/iwo jima",
+      "us/jefferson davis",
+      "us/kosciuszko",
+      "us/labor|h",
+      "us/lincolns",
+      "us/martin luther king",
+      "us/memorial",
+      "us/national freedom",
+      "us/navy",
+      "us/patriots",
+      "us/robert e lee",
+      "us/thanksgiving",
+      "us/thomas jeffersons",
+      "us/veterans|h",
+      "us/vietnam",
+      "us/washingtons|h",
+      "us/womens equality" }),
+
+   "us/alabama":
+   ({ "+us",
+      "us/alabama/alabama admission|h",
+      "us/alabama/confederate memorial|h",
+      "us/alabama/jefferson davis|h",
+      "us/alabama/robert e lee|h",
+      "columbus|h",
+      "mardi gras|h",
+      "us/thomas jeffersons|h" }),
+
+   "us/alaska":
+   ({ "+us",
+      "us/alaska/alaska|h",
+      "us/alaska/alaska admission|h",
+      "-us/independence",
+      "us/alaska/flag|fh",
+      "us/alaska/sewards|h",
+      "us/lincolns|h",
+      "us/memorial|h" }),
+
+   "us/arizona":
+   ({ "+us",
+      "us/arizona/american family|h",
+      "us/arizona/arbors|h",
+      "us/arizona/arborn|h",
+      "us/arizona/arizona admission|h",
+      "us/arizona/lincoln|h",
+      "us/columbus|h",
+      "fathers|h",
+      "mothers|h",
+      "us/memorial|h",
+      "-us/washingtons",
+      "us/washington|h" }),
+
+   "us/arkansas":
+   ({ "+us",
+      "us/arkansas/arkansas admission|h",
+      "us/arkansas/general douglas macarthur|h",
+      "us/arkansas/world war ii memorial|h",
+      "us/columbus|h",
+      "us/election|h",
+      "us/jefferson davis|h",
+      "us/memorial|h",
+      "us/robert e lee|h" }),
+
+   "us/california":
+   ({ "+us",
+      "us/california/california admission|h",
+      "us/columbus|h",
+      "us/california/arbor|h",
+      "us/election|h",
+      "us/lincolns|h",
+      "us/memorial|h", }),
+
+   "us/colorado":
+   ({ "+us",
+      "us/colorado/arbor|h",
+      "us/colorado/colorado|h",
+      "columbus|h",
+      "us/election|h",
+      "us/lincolns|h",
+      "us/memorial|h", }),
+
+   "us/connecticut":
+   ({ "+us",
+      "c/good friday|h",
+      "us/columbus|h",
+      "us/connecticut/connecticut ratification|h",
+      "us/lincolns|h",
+      "us/martin luther king|h",
+      "us/memorial|h", }),
+
+   "us/delaware":
+   ({ "+us",
+      "c/good friday|h",
+      "us/columbus|h",
+      "us/delaware/arbor|h",
+      "us/delaware/delaware|h",
+      "us/delaware/lincolns|h",
+      "us/delaware/memorial|h",
+      "us/delaware/separation|h",
+      "us/delaware/swedish colonial|h",
+      "us/election|h" }),
+
+   "us/florida":
+   ({ "+us",
+      "c/christmas|h",
+      "c/good friday|h",
+      "us/columbus|h",
+      "us/florida/arbor|h",
+      "us/florida/confederate memorial|h",
+      "us/florida/farmers|h",
+      "us/florida/florida admission|h",
+      "us/florida/pascua florida|h",
+      "us/florida/susan b anthony|h",
+      "us/election|h",
+      "us/jefferson davis|h",
+      "us/lincolns|h",
+      "us/martin luther king|h",
+      "us/memorial|h",
+      "us/robert e lee|h",}),
+
+   "us/georgia":
+ // "us/robert elee" ?
+   ({ "+us",
+      "us/columbus|h",
+      "us/georgia/confederate memorial|h",
+      "us/georgia/georgia|h",
+      "us/jefferson davis|h",
+      "us/memorial|h" }),
+
+   "us/hawaii":
+ // "us/hawaii/Discoverers' Day (Us/Columbus Day)" ?
+   ({ "+us",
+      "c/good friday|h",
+      "us/hawaii/flag|fh",
+      "us/hawaii/hawaii statehood|h",
+      "us/hawaii/kamehameha|h",
+      "us/hawaii/kuhio|h",
+      "us/hawaii/lei|h",
+      "us/hawaii/wesak flower festival|h",
+      "us/election|h",
+      "us/memorial|h",
+      "us/presidents|h" }),
+
+   "us/idaho":
+   ({ "+us",
+      "us/columbus|h",
+      "us/idaho/idaho admission|h",
+      "us/idaho/idaho pioneer|h",
+      "us/election|h",
+      "us/memorial|h" }),
+
+   "us/illinois":
+   ({ "+us",
+      "us/columbus|h",
+      "us/day after thanksgiving|h",
+      "us/illinois/illinois admission|h",
+      "us/illinois/memorial|h",
+      "us/election|h",
+      "us/lincolns|h",
+      "us/martin luther king|h" }),
+
+   "us/indiana":
+   ({ "+us",
+      "c/good friday|h",
+      "us/columbus|h",
+      "us/indiana/indiana admission|h",
+      "us/indiana/primary election|h",
+      "us/indiana/vincennes|h",
+      "us/election|h",
+      "us/lincolns|h",
+      "us/memorial|h" }),
+
+   "us/iowa":
+   ({ "+us",
+      "us/iowa/bird|h",
+      "us/iowa/independence sunday|h",
+      "us/iowa/iowa admission|h",
+      "us/lincolns|h",
+      "us/memorial|h" }),
+
+   "us/kansas":
+   ({ "+us",
+      "us/columbus|h",
+      "us/kansas/kansas|h",
+      "us/lincolns|h",
+      "us/memorial|h" }),
+
+   "us/kentucky":
+   ({ "+us",
+      "us/columbus|h",
+      "us/kentucky/franklin d roosevelt|h",
+      "us/kentucky/kentucky statehood|h",
+      "us/election|h",
+      "us/jefferson davis|h",
+      "us/lincolns|h",
+      "us/martin luther king|h",
+      "us/memorial|h",
+      "us/robert e lee|h" }),
+
+   "us/louisiana":
+   ({ "+us",
+      "c/all saints|h",
+      "c/good friday|h",
+      "us/columbus|h",
+      "us/louisiana/huey p long|h",
+      "us/louisiana/jackson|h",
+      "us/louisiana/louisiana admission|h",
+      "mardi gras|h",
+      "new year|h",
+      "us/election|h",
+      "us/jefferson davis|h",
+      "us/martin luther king|h",
+      "us/memorial|h",
+      "us/robert e lee|h" }),
+
+   "us/maine":
+   ({ "+us",
+      "us/columbus|h",
+      "us/maine/battleship|h",
+      "us/maine/maine admission|h",
+      "us/memorial|h",
+      "us/patriots|h" }),
+
+   "us/maryland":
+   ({ "+us",
+      "c/good friday|h",
+      "us/columbus|h",
+      "us/maryland/defenders|h",
+      "us/maryland/john hanson|h",
+      "us/maryland/maryland|h",
+      "us/maryland/maryland admission|h",
+      "us/maryland/maryland ratification|h",
+      "us/maryland/memorial|h",
+      "us/maryland/national anthem|h",
+      "us/maryland/repudiation|h",
+      "us/election|h",
+      "us/lincolns|h",
+      "us/martin luther king|h" }),
+
+   "us/massachusetts":
+   ({ "+us",
+      "us/columbus|h",
+      "us/massachusetts/bunker hill|h",
+      "us/massachusetts/childrens|h",
+      "us/massachusetts/evacuation|h",
+      "us/massachusetts/john f kennedy|h",
+      "us/massachusetts/lafayette|h",
+      "us/massachusetts/liberty tree|h",
+      "us/massachusetts/massachusetts ratification|h",
+      "us/massachusetts/spanish-american war memorial|h",
+      "us/massachusetts/student government|h",
+      "us/massachusetts/susan b anthony|h",
+      "us/massachusetts/teachers|h",
+      "us/martin luther king|h",
+      "us/memorial|h",
+      "us/patriots|h" }),
+
+   "us/michigan":
+   ({ "+us",
+      "us/michigan/memorial|h",
+      "us/michigan/michigan|h",
+      "us/martin luther king|h" }),
+
+   "us/minnesota":
+   ({ "+us",
+      "us/columbus|h",
+      "us/minnesota/american family|h",
+      "us/minnesota/minnesota|h",
+      "us/memorial|h" }),
+
+   "us/mississippi":
+   ({ "+us",
+      "us/mississippi/confederate memorial|h",
+      "us/mississippi/jefferson davis|h",
+      "us/mississippi/robert elee|h" }),
+
+   "us/missouri":
+   ({ "+us",
+      "us/columbus|h",
+      "us/missouri/missouri admission|h",
+      "us/missouri/truman|h",
+      "us/election|h",
+      "us/lincolns|h",
+      "us/memorial|h" }),
+
+   "us/montana":
+   ({ "+us",
+      "us/columbus|h",
+      "us/montana/election|h",
+      "us/lincolns|h",
+      "us/memorial|h" }),
+
+   "us/nebraska":
+   ({ "+us",
+      "us/columbus|h",
+      "us/day after thanksgiving|h",
+      "us/nebraska/arbor|h",
+      "us/nebraska/nebraska state|h",
+      "us/memorial|h",
+      "us/presidents|h" }),
+
+   "us/nevada":
+   ({ "+us",
+      "us/nevada/nevada|h",
+      "us/memorial|h" }),
+
+   "us/new hampshire":
+   ({ "+us",
+      "us/columbus|h",
+      "us/day after thanksgiving|h",
+      "us/new hampshire/fast|h",
+      "us/new hampshire/memorial|h",
+      "us/new hampshire/new hampshire admission|h",
+      "us/election|h" }),
+
+   "us/new jersey":
+   ({ "+us",
+      "c/good friday|h",
+      "us/columbus|h",
+      "us/new jersey/new jersey admission|h",
+      "us/election|h",
+      "us/lincolns|h",
+      "us/martin luther king|h",
+      "us/memorial|h" }),
+
+   "us/new mexico":
+   ({ "+us",
+      "us/columbus|h",
+      "us/new mexico/arbor|h",
+      "us/new mexico/memorial|h",
+      "us/lincolns|h" }),
+
+   "us/new york":
+   ({ "+us",
+      "us/columbus|h",
+      "us/new york/audubon|h",
+      "us/new york/flag|fh",
+      "us/new york/martin luther king|h",
+      "us/new york/new york ratification|h",
+      "us/new york/verrazano|h",
+      "us/election|h",
+      "us/lincolns|h",
+      "us/memorial|h" }),
+
+   "us/north carolina":
+   ({ "+us",
+      "c/easter monday|h",
+      "us/north carolina/confederate memorial|h",
+      "us/north carolina/halifax resolutions|h",
+      "us/north carolina/mecklenburg|h",
+      "us/memorial|h",
+      "us/robert e lee|h" }),
+
+   "us/north dakota":
+   ({ "+us",
+      "c/good friday|h",
+      "us/north dakota/north dakota admission|h",
+      "us/memorial|h" }),
+
+   "us/ohio":
+   ({ "+us",
+      "us/columbus|h",
+      "us/ohio/martin luther king|h",
+      "us/ohio/ohio admission|h",
+      "us/memorial|h",
+      "-us/washingtons",
+      "us/washington-lincoln|h" }),
+
+   "us/oklahoma":
+ // "us/oklahoma/oklahoma heritage week" ?
+ // "us/oklahoma/youth" ?
+   ({ "+us",
+      "us/columbus|h",
+      "mothers|h",
+      "us/oklahoma/bird|h",
+      "us/oklahoma/cherokee strip|h",
+      "us/oklahoma/indian|h",
+      "us/oklahoma/oklahoma|h",
+      "us/oklahoma/oklahoma historical|h",
+      "us/oklahoma/oklahoma statehood|h",
+      "us/oklahoma/senior citizens|h",
+      "us/oklahoma/will rogers|h",
+      "us/election|h",
+      "us/memorial|h",
+      "us/thomas jeffersons|h" }),
+
+   "us/oregon":
+   ({ "+us",
+      "us/oregon/lincolns|h",
+      "us/oregon/oregon statehood|h",
+      "us/memorial|h" }),
+
+   "us/pennsylvania":
+   ({ "+us",
+      "c/good friday|h",
+      "us/columbus|h",
+      "us/pennsylvania/barry|h",
+      "us/pennsylvania/charter|h",
+      "us/pennsylvania/pennsylvania admission|h",
+      "us/election|h",
+      "us/flag|fh",
+      "us/martin luther king|h",
+      "us/memorial|h",
+      "us/presidents|h" }),
+
+   "us/rhode island":
+   ({ "+us",
+      "us/columbus|h",
+      "us/rhode island/arbor|h",
+      "us/rhode island/rhode island admission|h",
+      "us/rhode island/rhode island independence|h",
+      "us/rhode island/victory|h",
+      "us/election|h",
+      "us/memorial|h" }),
+
+   "us/south carolina":
+   ({ "+us",
+      "us/south carolina/confederate memorial|h",
+      "us/south carolina/south carolina admission|h",
+      "us/election|h",
+      "us/jefferson davis|h",
+      "us/martin luther king|h",
+      "us/robert e lee|h" }),
+
+   "us/south dakota":
+   ({ "+us",
+      "us/south dakota/memorial|h",
+      "us/south dakota/pioneers|h",
+      "us/south dakota/south dakota admission|h",
+      "us/presidents|h" }),
+
+   "us/tennessee":
+   ({ "+us",
+      "c/good friday|h",
+      "us/columbus|h",
+      "us/tennessee/confederate memorial|h",
+      "us/tennessee/tennesse statehood|h",
+      "us/election|h",
+      "us/memorial|h" }),
+
+   "us/texas":
+   ({ "+us",
+      "us/columbus|h",
+      "us/texas/alamo|h",
+      "us/texas/austin|h",
+      "us/texas/confederate heroes|h",
+      "us/texas/juneteenth|h",
+      "us/texas/lyndon b johnsons|h",
+      "us/texas/san jacinto|h",
+      "us/texas/texas admission|h",
+      "us/texas/texas independence|h",
+      "us/texas/texas pioneers|h",
+      "us/election|h",
+      "us/memorial|h" }),
+
+   "us/utah":
+   ({ "+us",
+      "us/columbus|h",
+      "us/lincolns|h",
+      "us/memorial|h",
+      "us/utah/arbor|h",
+      "us/utah/pioneer|h",
+      "us/utah/utah admission|h" }),
+
+   "us/vermont":
+   ({ "+us",
+      "us/columbus|h",
+      "us/lincolns|h",
+      "us/vermont/bennington battle|h",
+      "us/vermont/memorial|h",
+      "us/vermont/town meeting|h",
+      "us/vermont/vermont|h" }),
+
+   "us/virginia":
+ // "us/virginia/jack jouett" ?
+   ({ "+us",
+      "us/columbus|h",
+      "us/election|h",
+      "us/memorial|h",
+      "us/virginia/cape henry|h",
+      "us/virginia/confederate memorial|h",
+      "us/virginia/crater|h",
+      "us/virginia/jamestown|h",
+      "us/virginia/lee-jackson|h",
+      "us/virginia/royalist fast|h",
+      "us/virginia/virginia ratification|h" }),
+
+   "us/washington":
+   ({ "+us",
+      "us/lincolns|h",
+      "us/memorial|h",
+      "us/washington/washington admission|h" }),
+
+// ?
+   "us/washington dc":
+   ({ "+us",
+      "us/columbus|h",
+      "us/election|h",
+      "us/memorial|h",
+      "us/washington dc/arbor|h" }),
+
+   "us/west virginia":
+   ({ "+us",
+      "us/columbus|h",
+      "us/election|h",
+      "us/lincolns|h",
+      "us/memorial|h",
+      "-us/washingtons",
+      "us/washington|h",
+      "us/west virginia/west virginia|h" }),
+
+   "us/wisconsin":
+   ({ "+us",
+      "c/good friday|h",
+      "us/columbus|h",
+      "us/election|h",
+      "us/memorial|h",
+      "-us/washingtons",
+      "us/washington-lincoln|h",
+      "us/wisconsin/primary election|h",
+      "us/wisconsin/wisconsin|h" }),
+
+   "us/wyoming":
+ // "us/nellie tayloe ross" ?
+   ({ "+us",
+      "us/columbus|h",
+      "us/election|h",
+      "us/memorial|h",
+      "-us/washingtons",
+      "us/washington-lincoln|h",
+      "us/wyoming/arbor|h",
+      "us/wyoming/primary election|h",
+      "us/wyoming/wyoming|h",
+      "us/wyoming/wyoming statehood" }),
+
+   "vanuatu":
+   ({ "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/easter",
+      "labor",
+      "new year",
+      "unity",
+      "vanuatu/constitution",
+      "vanuatu/independence" }),
+
+   "vatican city":
+   ({ "vatican city/anniversary of the beginning of the john paul ii pontificate",
+      "vatican city/john paul ii namesday" }),
+
+   "venezuela":
+ // "carnival" ?
+ // "additional bank holidays" ?
+ // "saint josephs" ?
+   ({ "saints/paul",
+      "saints/peter",
+      "c/all saints",
+      "c/ascension",
+      "c/assumption",
+      "c/christmas",
+      "c/easter",
+      "c/immaculate conception",
+      "columbus",
+      "c/epiphany",
+      "labor",
+      "new year",
+      "new years eve",
+      "venezuela/battle of carabobo",
+      "venezuela/bolivars",
+      "venezuela/civil servants",
+      "venezuela/declaration of independence",
+      "venezuela/independence",
+      "venezuela/teachers" }),
+
+   "vietnam":
+ // "tet nguyen dan" ?
+ // "vietnam/tet nguyen dan" ?
+ // "vietnam/thanh minh" ?
+   ({ "labor",
+      "new year",
+      "vietnam/day of the nation",
+      "vietnam/emperor-founder hung vuongs",
+      "vietnam/founding of the communist party",
+      "vietnam/independence",
+      "vietnam/liberation of saigon" }),
+
+   "virgin islands":
+ // "martin luther king" ?
+ // "memorial" ?
+ // "presidents" ?
+ // "three kings" ?
+ // "us independence" ?
+ // "us thanksgiving" ?
+ // "veterans" ?
+   ({ "c/christmas",
+      "c/easter",
+      "columbus",
+      "labor",
+      "new year",
+      "virgin islands/danish west indies emancipation",
+      "virgin islands/hurricane supplication",
+      "virgin islands/hurricane thanksgiving",
+      "virgin islands/liberty",
+      "virgin islands/nicole robin",
+      "virgin islands/organic act",
+      "virgin islands/transfer" }),
+
+   "western samoa":
+ // "national womens" ?
+   ({ "anzac",
+      "c/boxing",
+      "c/christmas",
+      "c/easter",
+      "c/whitmonday",
+      "new year",
+      "western samoa/arbor",
+      "western samoa/independence",
+      "western samoa/independence2",
+      "western samoa/white sunday" }),
+
+   "yemen":
+ // "ashoura" ?
+ // "first of ramadan" ?
+ // "id al-adha" ?
+ // "id al-fitr" ?
+ // "leilat al-meiraj" ?
+ // "mouloud" ?
+ // "muharram" ?
+   ({ "labor",
+      "new year",
+      "womens",
+      "yemen/corrective movement",
+      "yemen/national" }),
+
+   "zaire":
+   ({ "c/christmas",
+      "labor",
+      "new year",
+      "zaire/armed forces",
+      "zaire/constitution",
+      "zaire/day of the martyrs for independence",
+      "zaire/independence",
+      "zaire/mpr",
+      "zaire/naming",
+      "zaire/new regime",
+      "zaire/parents",
+      "zaire/presidents",
+      "zaire/youth/presidents" }),
+
+   "zambia":
+   ({ "africa",
+      "c/christmas",
+      "c/easter",
+      "labor",
+      "new year",
+      "unity",
+      "zambia/farmers",
+      "zambia/heroes",
+      "zambia/independence",
+      "zambia/unity",
+      "zambia/youth",
+      "zambia/youth2" }),
+
+   "zimbabwe":
+   ({ "africa",
+      "c/christmas",
+      "c/easter",
+      "new year",
+      "zimbabwe/heroess",
+      "zimbabwe/independence",
+      "zimbabwe/workers" }),
+]);
diff --git a/lib/modules/Calendar.pmod/FILES b/lib/modules/Calendar.pmod/FILES
new file mode 100644
index 0000000000000000000000000000000000000000..8275dd215f8a8e404128194f8934985a2ed01cb1
--- /dev/null
+++ b/lib/modules/Calendar.pmod/FILES
@@ -0,0 +1,152 @@
+CHANGES
+FILES
+
+Calendar.pike 	
+	This is the virtual base class for any Calendar.
+	It might be used as type for variables 
+	containing a random calendar object.
+
+TimeRanges.pmod	
+	This contains the base classes for timerange objects:
+	TimeRange	
+ 		The TimeRange is the virtual base class for any
+		timerange object. It defines everything that needs to
+		be possible to do with it, and has a lot of
+		non-virtual functions that calls back to the virtual
+		functions to ease implementations of new timerange
+		classes.
+	SuperTimeRange	
+		The SuperTimeRange is a class that is used to 
+		contain more then one timerange. This object
+		is created by methods and operators such as subtract,
+		`| or `^. 
+			
+Time.pmod
+	This contains the base classes for calendars that uses
+	time-of-day with hours, minutes and seconds:
+	Hour
+	Minute
+	Second
+		The normal time-of-day units. They are defined
+		to contain n*3600, n*60 and n seconds respectively,
+		and to start on those positions of the day.
+		They autopromote upwards (second->minute->hour).
+	Fraction
+		A fraction is a partial second. It can start
+		and end on non-even seconds - it has an integer
+		for nanosecond precision. It autopromotes upwards
+		to second (etc).
+	This module can not be used standalone, but must have
+	some virtual functions filled in.
+	It extends the TimeRanges module.
+
+YMD.pmod
+	This contains the base classes of any traditional calendar:
+	Year
+		The Year class, which contains the largest timerange
+		unit used.
+	Month
+		The month, which divides the year into non-equal
+		- most of the calendards, anyway - long day sequences,
+		and which is aligned to the year.
+	Week
+		The week, which is a equally long day sequence,
+		and isn't aligned to the year.
+	Day
+		The Day, which is the smallest unit before
+		time-of-day, and which is the base unit of time-of-day.
+	None of these four units autopromote.
+	The YMD module also extends the Time module,
+	so it contains those classes as well.
+		
+Gregorian.pmod
+	This is the base module for Julian style calendars;
+	despite the name. Most calendars of today are in sync
+	with the Gregorian calendar.
+ISO.pmod
+	This inherits the Gregorian calendar to tweak it to
+	conform to the ISO standards. Most affected are weeks, 
+	which starts on Monday in the ISO calendar.
+	This is also the default calendar.
+Discordian.pmod
+	The Discordian calendar as described in Principia Discordia
+	is in sync with the Gregorian calendar (although some claim
+	that it should be the Julian - I go with what I can read 
+	from my Principia Discordia). The module inherits and 
+	tweaks the Gregorian module.
+Coptic.pmod
+	The Coptic calendar is by some sources ("St. Marks'
+	Coptic Orthodox Church" web pages) is for now on in sync with
+	the Gregorian Calendar, so this module too inherits
+	and tweaks the Gregorian module. It needs to be 
+	adjusted for historical use.
+Julian.pmod
+	This is the Julian calendar, with the small changes
+	to the Gregorian calendar (leap years).
+
+Islamic.pmod
+	This is the Islamic calendar, using the 'Calendrical 
+	Calculations' rules for new moon. It is based
+	directly on the YMD module.
+Stardate.pmod
+	This is the (TNG) Stardate calendar, which consists
+	of one time unit only, the Tick (1000 Tick is one earth year). 
+	It is based directly on TimeRanges.
+
+Ruleset.pike
+	Each time unit keeps track of what rules are in affect now;
+	the rules contain two things for now, language to use and
+	timezone to use. It will be extended to contain geographical
+	position and possible other needed stuff later.
+	Any TimeRange object returning a new TimeRange object
+	will transfer the rules in the creation of the object.
+Language.pmod
+	This module keeps the base classes of languages.
+Timezone.pmod
+	This module keeps the base classes of timezones,
+	inheriting the DST rules and including the timezone
+	definitions that are created by the mkrules.pike 
+	program.
+TZrules.pmod
+	This module has the DST rules (127).
+TZs.h
+	This file keeps the Timezone definitions (440).
+TZnames.pmod
+	This is a convinience module that keeps the names
+	of all possible timezones in a convinient mapping.
+mkrules.pike
+	This is the program that take timezone definition
+	files (as used by most unix systems) and create the 
+	three files listed above. It is not a base class,
+	it's a complete program.
+
+Event.pmod
+	This module defines the base classes used for event
+	definitions:
+	Event
+		The virtual base class.
+	Date
+	Date_Weekday
+	Monthday_Weekday
+	Weekday
+		Open classes for self-created events.
+	Day_Event
+	Gregorian_Fixed
+	Easter
+	Easter_Relative
+	Monthday_Weekday_Relative
+		Classes for event definitions in Events.pmod.
+
+Namedays.pmod
+	This module defines the namedays used in some
+	countries and the saints days.
+Events.pmod
+	This module defines a number of events, used
+	all over the world. It also keeps tracks	
+	of holidays and events used in countries and
+	regions.
+
+module.pmod
+	This is only used to make "Calendar.Day" equal
+	"Calendar.ISO.Day" but still keep "Calendar.Stardate"
+	intact.
diff --git a/lib/modules/Calendar.pmod/Gregorian.pmod b/lib/modules/Calendar.pmod/Gregorian.pmod
index c4d170c5d23fd7cd6dbb59dca476abaa2b68b502..a26b244be0edea63c8494a298ae4aee6d7b70277 100644
--- a/lib/modules/Calendar.pmod/Gregorian.pmod
+++ b/lib/modules/Calendar.pmod/Gregorian.pmod
@@ -1,1543 +1,298 @@
-// 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"});
+//! 	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.
+//!
 
-/* calculated on need */
+import ".";
+inherit YMD:YMD;
 
-mapping week_day_mapping,month_mapping;
+string calendar_name() { return "Gregorian"; }
 
-class _TimeUnit
+private static mixed __initstuff=lambda()
 {
-   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;
+   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";
+
+   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";
+}();
+
+static int year_leap_year(int y) 
+{ 
+   return (!(((y)%4) || (!((y)%100) && ((y)%400))));
 }
 
-//== Year ====================================================================
-
-class Year
+// [y,yjd]
+static array year_from_julian_day(int jd)
 {
-//! class Year
-//! 	A <ref>Calendar.time_unit</ref>. 
-//!
-//!	Lesser units: <ref>Month</ref>, <ref>Week</ref>, <ref>Day</ref>
-//!	Greater units: none
-//!
-//!     
-   inherit _TimeUnit;
-
-//-- variables ------------------------------------------------------
+   int d=jd-1721426;
 
-   int y;
+   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;
 
-   array days_per_month;
-   array month_start_day;
+   return 
+   ({
+      century*100+century_year+1,
+      1721426+century_year*365+century_year/4+century_jd,
+   });
+}
 
-//-- standard methods -----------------------------------------------
+static int julian_day_from_year(int y)
+{
+   y--;
+   return 1721426+y*365+y/4-y/100+y/400;
+}
 
-   string is()
-   {
-      return "year";
-   }
+static int compat_week_day(int n)
+{
+   return n-1;
+}
 
-   array(string) lesser() 
-   { 
-      return ({"month","week","day"});
-   }
+static array(int) year_month_from_month(int y,int m)
+{
+// [y,m,ndays,myd]
 
-   array(string) greater()
-   {
-      return ({});
-   }
+   y+=(m-1)/12;
+   m=1+(m-1)%12;
 
-   void create(int ... arg)
+   switch (m)
    {
-      if (!sizeof(arg))
-      {
-	 object yp=vDay()->year();
-	 y=yp->y;
-      }
-      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];
+      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)});
    }
 
-   int `<(object x)
-   {
-      return y<(int)x;
-   }
+   error("month out of range\n");
+}
 
-   int `==(object x)
-   {
-      return 
-	 object_program(x)==object_program(this) &&
-	 (int)x==y;
-   }
+static array(int) month_from_yday(int y,int yd)
+{
+// [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)
+   {
+      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)});
+   }
+   error("yday out of range\n");
+}
 
-   int hash() { return y*113; }
+static array(int) week_from_julian_day(int jd)
+{
+// [year,week,day-of-week,ndays,week-julian-day]
 
-   int `>(object x)
-   {
-      return y>(int)x;
-   }
+   [int y,int yjd]=year_from_julian_day(jd);
+   int yday=jd-yjd+1;
 
-   object next()
-   {
-      return vYear(y+1);
-   }
+   int k=4+(yjd-4)%7;
+   int w=(yday+k)/7;
+   int wjd=jd-(jd+1)%7;
 
-   object prev()
+   if (!w) 
    {
-      return vYear(y-1);
+// 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) ) );
    }
-
-   object `+(int n)
+   else if (w==53 && k>=6-year_leap_year(y) && k<10-year_leap_year(y))
    {
-      return vYear(y+n);
+// handle the case that the week is in the next year
+      y++;
+      w=1;
    }
 
-   int|object `-(int|object n)
-   {
-      if (objectp(n) && object_program(n)==vYear)  return y-n->y;
-      return this+-n;
-   }
+   return ({y,w,1+(yjd+yday)%7,7,wjd});
+}
 
-//-- nonstandard methods --------------------------------------------
+static array(int) week_from_week(int y,int w)
+{
+// [year,week,1 (wd),ndays,week-julian-day]
 
-   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 yjd=julian_day_from_year(y);
+   int wjd=-5+yjd-(yjd+3)%7;
 
-   int leap()
-   {
-      if (!(y%400)) return 1;
-      if (!(y%100)) return 0;
-      return !(y%4);
-   }
+   if (w<1 || w>52) // may or may not be out of this year
+      return week_from_julian_day(wjd+w*7);
 
-   int leap_day()
-   {
-      return 31+24-1; // 24 Feb
-   }
+   return ({y,w,1,7,wjd+w*7});
+//   fixme
+}
 
-   int number_of_weeks()
-   {
-      int j=julian_day(0)%7;
+static int year_remaining_days(int y,int yday)
+{
+   return 365+year_leap_year(y)-yday;
+}
 
-      // 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;
-   }
+class cYear
+{
+   inherit YMD::cYear;
 
    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(object|string|int n)
-   {
-      if (objectp(n))
-	 if (object_program(n)==vMonth)
-	    n=n->number();
-
-      if (stringp(n))
+      switch (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);
-	 }
-	 n=month_mapping[lower_case(n)];
-	 if (!n) return 0;
+	 case 0: return 0;
+	 case 1: return 365+leap_year();
+	 default: 
+	    return julian_day_from_year(y+n)-yjd;
       }
-
-      if (n<0)
-	 return vMonth(y,13+n);
-      else
-	 return vMonth(y,n||1);
-   }
-
-   array(mixed) months()
-   {
-      return month_names;
    }
 
-   object week(object|int n)
+   int number_of_months()
    {
-      if (objectp(n))
-	 if (object_program(n)==vWeek)
-	 {
-	    n=n->number();
-	    if (n>number_of_weeks()) return 0; /* no such week */
-	 }
-
-      if (n<0)
-	 return vWeek(y,this->number_of_weeks()+n+1);
-      else
-	 return vWeek(y,n||1);
+      return 12*n;
    }
 
-   array(mixed) weeks()
+   int number_of_weeks()
    {
-       return indices(allocate(this->number_of_weeks()+1))[1..];
+      if (!n) return 1;
+      if (n==1) return 53+(yjd%7==5 && leap_year());
+      return 
+	 Week("julian",jd)
+	 ->range(Week("julian",julian_day_from_year(y+n)-1))
+	 ->number_of_weeks();
    }
 
-   object day(object|int n)
+   TimeRange place(TimeRange what,void|int force)
    {
-      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 (what->is_day)
+      {
+	 int yd=what->yd;
+	 if (yd>=55)
+	    switch (year_leap_year(what->y)*10+year_leap_year(y))
 	    {
-	       if (o->leap() && n>o->leap_day()) n--;
-	       if (this->leap() && n>=this->leap_day()) n++;
+	       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;
 	    }
-	    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()
-   {
-       return indices(allocate(this->number_of_days()));
-   }
-
-//-- 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;
+	 return Day("ymd_yd",rules,y,yjd,yjd+yd-1,yd,what->n);
       }
-      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);
+      return ::place(what);
    }
+}
 
-//-- internal -------------------------------------------------------
+class cDay
+{
+   inherit YMD::cDay;
 
-   int yday()
+   int number_of_months()
    {
-      return this->year()->month_start_day[m];
+      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;
    }
+}
 
-//-- nonstandard methods --------------------------------------------
-
-   int number_of_days()
-   {
-      return this->year()->days_per_month[m];
-   }
+class cMonth
+{
+   inherit YMD::cMonth;
 
-   int number()
-   {
-      return m;
-   }
+// a Gregorian Month can autopromote to a year
 
-   string name()
+   static int months_to_month(int y2,int m2)
    {
-      return month_names[this->number()-1];
+      return (y2-y)*12+(m2-m);
    }
 
-   mixed cast(string what)
+   TimeRange place(TimeRange what,int|void force)
    {
-      switch (what)
+      if (what->is_day)
       {
-	 case "int": return this->number(); 
-	 case "string":  return this->name();
-	 default:
-	    throw(({"can't cast to "+what+"\n",backtrace()}));
-      }
-   }
-
-//-- less -----------------------------------------------------------
-
-   object day(int|object n)
-   {
-      if (objectp(n))
-	 if (object_program(n)==vDay)
+	 int wmd=what->month_day();
+	 if (md==CALUNKNOWN) make_month();
+	 if (what->m==2 && m==2 && wmd>=24)
 	 {
-	    n=n->month_day();
-	    if (n>number_of_days()) return 0; /* no such day */
+	    int l1=year_leap_year(what->y);
+	    int l2=year_leap_year(y);
+	    if (l1||l2)
+	    {
+	       if (l1 && wmd==24) 
+		  if (l2) wmd=24;
+		  else { if (!force) return 0; }
+	       else
+	       {
+		  if (l1 && wmd>24) wmd--;
+		  if (l2 && wmd>24) wmd++;
+	       }
+	    }
 	 }
-
-      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
-{
-   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];
+	 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->w<w) || (x->y<y));
-   }
-
-   int `==(object x)
-   {
-      return 
-	 object_program(x)==object_program(this) &&
-	 x->y==y && x->w==w;
+      return ::place(what);
    }
+}
 
-   int hash() { return y*811+w; }
-
-   int `>(object x)
-   {
-      return 
-	 (object_program(x)==object_program(this) &&
-	  (x->y==y && x->w>w) || (x->y>y));
-   }
+class cWeek
+{
+   inherit YMD::cWeek;
 
-   object `+(int n)
+   string nice_print()
    {
-      int y2=y,nd;
-      int w2=w;
-      w2+=n;
-      
-      if (w2>0)
+      mixed err=catch
       {
-	 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);
+	 return 
+	    sprintf("%s %s",
+		    week_name(),
+		    year_name());
+      };
+      return "error";
    }
 
-//-- internal -------------------------------------------------------
-
-   int yday()
+   static int weeks_to_week(int y2,int w2)
    {
-      return 
-	 ({0,-1,-2,-3,3,2,1})[this->year()->julian_day(0)%7]
-         +7*(w-1);
+      [int y3,int w3,int wd2,int nd2,int jd2]=week_from_week(y2,w2);
+      return (jd2-jd)/7;
    }
 
-//-- 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|object n)
-   {
-      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];
-      }
-      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()
-   {
-       return ({0,1,2,3,4,5,6});
-   }
-
-//-- more -----------------------------------------------------------
-     
-   object year()
-   {
-      return vYear(y);
-   }
-};
-
-//
-//== Day =====================================================================
-
-class Day
-{
-   inherit _TimeUnit;
-
-//-- variables ------------------------------------------------------
-
-   int y;
-   int d;
-
-//-- standard methods -----------------------------------------------
-
-   string is()
-   {
-      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)());
-	 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");
-
-	 }
-	 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];
-      } 
-   }
-
-   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 7*n;
    }
-
-   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)
-   {
-      return 
-	 (object_program(x)==object_program(this) &&
-	  (x->y==y && x->d>d) || (x->y>y)) ||
-	 (x->julian_day()>julian_day());
-   }
-
-   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);
-   }
-
-//-- 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;
-   }
-};
-
-
-//
-//== Minute ===================================================================
-
-class Minute
-{
-   inherit _TimeUnit;
-
-//-- variables ------------------------------------------------------
-
-   object h;
-   int m;
-
-//-- standard methods -----------------------------------------------
-
-   string is()
-   {
-      return "minute";
-   }
-
-   array(string) greater()
-   {
-      return ({"hour"});
-   } 
-
-   array(string) lesser()
-   {
-      return ({"second"});
-   }
-
-   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);
 }
diff --git a/lib/modules/Calendar.pmod/ISO.pmod b/lib/modules/Calendar.pmod/ISO.pmod
index 214f6a709b30af38922540416953b0a83cceab53..d2a6d84058320c5e7ac3a647928f853b7dff77dc 100644
--- a/lib/modules/Calendar.pmod/ISO.pmod
+++ b/lib/modules/Calendar.pmod/ISO.pmod
@@ -1,247 +1,152 @@
-// IS-8601, international standard
-
-inherit Calendar.Gregorian:Gregorian;
-
-class Year
+//!
+//! module Calendar
+//! submodule ISO
+//!
+//! 	This is the standard western calendar,
+//!	which is a derivate of the Gregorian calendar,
+//!	but with weeks that starts on monday 
+//!	instead of sunday.
+//!
+//! inherits Gregorian
+//!
+
+import ".";
+inherit Gregorian:Gregorian;
+
+string calendar_name() { return "ISO"; }
+
+private static mixed __initstuff=lambda()
 {
-   inherit Gregorian::Year;
-
-   int leap_day()
-   {
-      if (y>1999) return 31+29-1; // 29 Feb
-      return 31+24-1; // 24 Feb
-   }
+   f_week_day_shortname_from_number="week_day_shortname_from_number";
+   f_week_day_name_from_number="week_day_name_from_number";
+   f_year_name_from_number="year_name_from_number";
+   f_week_day_number_from_name="week_day_number_from_name";
+}();
 
-   string name()
-   {
-      return (string)y;
-   }
-}
-
-class Month
+static int compat_week_day(int n)
 {
-   inherit Gregorian::Month;
-
-   string iso_name()
-   {
-      return sprintf("%04d-%02d",
-		     (int)this->year(),
-		     (int)this);
-   }
-  
-   string iso_short_name()
-   {
-      return name()-"-";
-   }
+   return n%7;
 }
-  
-class Week
-{
-   inherit Gregorian::Week;
 
-   int yday()
-   {
-      return 
-	 ({0,-1,-2,-3,3,2,1})[this->year()->julian_day(0)%7]
-         +7*(w-1);
-   }
-
-   array(mixed) days()
-   {
-       return ({1,2,3,4,5,6,7});
-   }
-  
-   string iso_name()
-   {
-      return sprintf("%04d-W%02d",
-		     (int)this->year(),
-		     (int)this);
-   }
-  
-   string iso_short_name()
-   {
-      return name()-"-";
-   }
-  
-   object day(int|string|object n)
-   {
-      if (stringp(n)) 
-      {
-	 if (!week_day_mapping)
-	    week_day_mapping=
-	       mkmapping(Array.map(week_day_names,lower_case),
-			 ({1,2,3,4,5,6,7}));
-	 n=week_day_mapping[n];
-      }
-      else if (objectp(n))
-	 if (object_program(n)==vDay)
-	    n=n->week_day();
-	 else return 0;
-
-      if (n<0) n=8+n;
-      else if (!n) n=1;
-      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);
-   }
+static string year_name_from_number(int y)
+{
+   if (y>0) return ""+y;
+   else return (1-y)+" BC";
 }
 
-class Day
+static array(int) week_from_julian_day(int jd)
 {
-   inherit Gregorian::Day;
+// [year,week,day-of-week,ndays,week-julian-day]
 
-   int week_day()
-   {
-      return julian_day()%7+1;
-   }
-
-   string week_day_name()
-   {
-//       werror("week_days: %O\n",week_day_names);
-      return week_day_names[(this->week_day()+6)%7];
-   }
-
-   string iso_name()
-   {
-      return sprintf("%04d-%02d-%02d",
-		     (int)this->year(),
-		     (int)this->month(),
-		     (int)this->month_day());
-   }
+   [int y,int yjd]=year_from_julian_day(jd);
+   int yday=jd-yjd+1;
 
-   string iso_short_name()
-   {
-      return iso_name()-"-";
-   }
+   int k=3+(yjd-3)%7;
+   int w=(yday+k-1)/7;
+   int wjd=jd-jd%7;
 
-   string iso_name_by_week()
-   {
-      return sprintf("%04d-W%02d-%d",
-		     (int)this->year(),
-		     (int)this->week(),
-		     (int)this->week_day());
-   }
-  
-   string iso_name_by_yearday()
-   {
-      return sprintf("%04d-%03d",
-		     (int)this->year(),
-		     (int)this->year_day());
-   }
-  
-   string iso_short_name_by_yearday()
+   if (!w) 
    {
-      return iso_name_by_yearday()-"-";
+// 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==3) || ( (k==4) && year_leap_year(y) ) );
    }
-  
-   object week()
+   else if (w==53 && k>=5-year_leap_year(y) && k<9-year_leap_year(y))
    {
-      int n;
-      object ye=this->year();
-      n=(-({0,-1,-2,-3,3,2,1})[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);
+// handle the case that the week is in the next year
+      y++;
+      w=1;
    }
-}
 
-static private class _Day
-{
-   // FIXME: Kludge because the day object does not exist in
-   // Minute and Second. This function will be shadowed in Hour.
-   object day()
-   {
-      return this_object()->hour()->day();
-   }
+   return ({y,w,1+(yjd+yday-1)%7,7,wjd});
 }
 
-static private class Name
+static array(int) week_from_week(int y,int w)
 {
-   object this = this_object();
+// [year,week,1 (wd),ndays,week-julian-day]
 
-   string iso_name()
-   {
-      return this->day()->iso_name()+this->_iso_name();
-   }
-  
-   string iso_short_name()
-   {
-      return this->day()->iso_short_name()+this->_iso_short_name();
-   }
-  
-   string iso_name_by_week()
-   {
-      return this->day()->iso_name_by_week()+this->_iso_name();
-   }
-  
-   string iso_name_by_yearday()
-   {
-      return this->day()->iso_name_by_yearday()+this->_iso_name();
-   }
-  
-   string iso_short_name_by_yearday()
-   {
-      return this->day()->iso_short_name_by_yearday()+this->_iso_short_name();
-   }
-}
+   int yjd=julian_day_from_year(y);
+   int wjd=-3+yjd-(yjd+4)%7;
 
-class Hour
-{
-   inherit Gregorian::Hour;
-   inherit Name;
+   if (w<1 || w>52) // may or may not be out of this year
+      return week_from_julian_day(wjd+w*7);
 
-   string _iso_name()
-   {
-      return sprintf("T%02d",
-		     (int)this);
-   }
-
-   string _iso_short_name()
-   {
-      return _iso_name();
-   }
+   return ({y,w,1,7,wjd+w*7});
+//   fixme
 }
 
-class Minute
+class cYear
 {
-   inherit _Day;
-   inherit Gregorian::Minute;
-   inherit Name;
-
-   string _iso_name()
+   inherit Gregorian::cYear;
+   TimeRange place(TimeRange what,void|int force)
    {
-      return sprintf("T%02d:%02d",
-		     (int)this->hour(),
-		     (int)this);
-   }
+      if (what->is_day)
+      {
+	 int wyd=what->yd;
+	 if (md==CALUNKNOWN) make_month();
+	 if (wyd>=55)
+	 {
+	    int l1=year_leap_year(what->y);
+	    int l2=year_leap_year(y);
+	    if (l1||l2)
+	    {
+	       int ld1=(what->y<2000)?55:60; // 24th or 29th february
+	       int ld2=(y<2000)?55:60; // 24th or 29th february
+
+	       if (l1 && wyd==ld1) 
+		  if (l2) wyd=ld2;
+		  else { if (!force) return 0; }
+	       else
+	       {
+		  if (l1 && wyd>ld1) wyd--;
+		  if (l2 && wyd>=ld2) wyd++;
+	       }
+	    }
+	 }
+	 if (!force && wyd>number_of_days()) return 0;
+
+	 return Day("ymd_yd",rules,y,yjd,yjd+wyd-1,wyd,what->n);
+      }
 
-   string _iso_short_name()
-   {
-      return _iso_name()-":";
+      return ::place(what);
    }
 }
 
-class Second
+class cMonth
 {
-   inherit _Day;
-   inherit Gregorian::Second;
-   inherit Name;
+   inherit Gregorian::cMonth;
 
-   string _iso_name()
+   TimeRange place(TimeRange what,int|void force)
    {
-      return sprintf("T%02d:%02d:%02d",
-		     (int)this->hour(),
-		     (int)this->minute(),
-		     (int)this);
-   }
+      if (what->is_day)
+      {
+	 int wmd=what->month_day();
+	 if (md==CALUNKNOWN) make_month();
+	 if (what->m==2 && m==2 && wmd>=24)
+	 {
+	    int l1=year_leap_year(what->y);
+	    int l2=year_leap_year(y);
+	    if (l1||l2)
+	    {
+	       int ld1=(what->y<2000)?24:29; // 24th or 29th february
+	       int ld2=(y<2000)?24:29; // 24th or 29th february
+
+	       if (l1 && wmd==ld1) 
+		  if (l2) wmd=ld2;
+		  else { if (!force) return 0; }
+	       else
+	       {
+		  if (l1 && wmd>ld1) wmd--;
+		  if (l2 && wmd>=ld2) wmd++;
+	       }
+	    }
+	 }
+	 if (!force && wmd>number_of_days()) return 0;
+	 return Day("ymd_yd",rules,y,yjd,jd+wmd-1,yd+wmd-1,what->n);
+      }
 
-   string _iso_short_name()
-   {
-      return _iso_name()-":";
+      return ::place(what);
    }
 }
-
diff --git a/lib/modules/Calendar.pmod/Islamic.pmod b/lib/modules/Calendar.pmod/Islamic.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..6b2ea40abdf6876008471a288a03f08947677e81
--- /dev/null
+++ b/lib/modules/Calendar.pmod/Islamic.pmod
@@ -0,0 +1,239 @@
+//!
+//! module Calendar
+//! submodule Gregorian
+//!
+//! 	This is the islamic calendar. Due to some sources,
+//!	they decide the first day of the new months on a 
+//!	month-to-month basis (sightings of the new moon),
+//!	so it's probably not <i>that</i> accurate. If
+//!	someone can confirm (or deny) accuracy better than that, 
+//!	please contact me so I can change this statement.
+//!
+//! 	It's vaugely based on rules presented in algorithms by
+//!	Dershowitz, Reingold and Clamen, 'Calendrical Calculations'.
+//!	It is the same that's used in Emacs calendar mode.
+//!
+//! known bugs:
+//!	I have currently no idea how the arabic countries
+//!	count the week. Follow the same rules as ISO
+//!	for now... The time is also suspicious; the *day*
+//!	really starts at sunrise (sunset?) and not midnight,
+//!	the hours of the day is not correct. Also don't know
+//!	what to call years before 1 - go for "BH"; positive
+//!	years are "AH", anno Hegirac.
+//!	
+
+import ".";
+inherit YMD:YMD;
+
+string calendar_name() { return "Islamic"; }
+
+private static mixed __initstuff=lambda()
+{
+   f_week_day_shortname_from_number="islamic_week_day_shortname_from_number";
+   f_week_day_name_from_number="islamic_week_day_name_from_number";
+   f_year_name_from_number="islamic_year_name_from_number";
+
+   f_month_day_name_from_number="month_day_name_from_number";
+   f_month_name_from_number="islamic_month_name_from_number";
+   f_month_shortname_from_number="islamic_month_shortname_from_number";
+   f_month_number_from_name="islamic_month_number_from_name";
+
+   f_week_day_number_from_name="gregorian_week_day_number_from_name";
+   f_week_name_from_number="week_name_from_number";
+}();
+
+int year_leap_year(int y)
+{
+   return (14+11*y)%30<11;
+}
+
+int julian_day_from_year(int y)
+{
+   return (y-1)*354 + (11*y+3)/30 + 1948440;
+}
+
+array(int) year_from_julian_day(int jd)
+{
+// [y,yjd]
+   jd-=1948440;
+   int tr=jd/10631; 
+   int td=jd-tr*10631;
+   int y=(14+td*30)/10631+tr*30+1;
+
+   return ({y,
+	    (y-1)*354 + (11*y+3)/30 + 1948440});
+}
+
+static array(int) year_month_from_month(int y,int m)
+{
+// [y,m,ndays,myd]
+
+   y+=(m-1)/12;
+   m=1+(m-1)%12;
+
+   switch (m)
+   {
+      case  1: return ({y,m,30,  1});
+      case  2: return ({y,m,29, 31});
+      case  3: return ({y,m,30, 60});
+      case  4: return ({y,m,29, 90});
+      case  5: return ({y,m,30,119});
+      case  6: return ({y,m,29,149});
+      case  7: return ({y,m,30,178});
+      case  8: return ({y,m,29,208});
+      case  9: return ({y,m,30,237});
+      case 10: return ({y,m,29,267});
+      case 11: return ({y,m,30,296});
+      case 12: return ({y,m,29+year_leap_year(y),326});
+   }			       
+
+   error("month out of range\n");
+}
+
+static array(int) month_from_yday(int y,int yd)
+{
+// [month,day-of-month,ndays,month-year-day]
+   int l=year_leap_year(y);
+
+   switch (yd)
+   {
+      case   1.. 30: return ({ 1,yd,    30,  1});
+      case  31.. 59: return ({ 2,yd- 30,29, 31});
+      case  60.. 89: return ({ 3,yd- 59,30, 60});
+      case  90..118: return ({ 4,yd- 89,29, 90});
+      case 119..148: return ({ 5,yd-118,30,119});
+      case 149..177: return ({ 6,yd-148,29,149});
+      case 178..207: return ({ 7,yd-177,30,178});
+      case 208..236: return ({ 8,yd-207,29,208});
+      case 237..266: return ({ 9,yd-236,30,237});
+      case 267..295: return ({10,yd-266,29,267});
+      case 296..325: return ({11,yd-295,30,296});
+      case 326..:    return ({12,yd-326,29+year_leap_year(y),326});
+   }			       
+
+   error("yday out of range\n");
+}
+
+static array(int) week_from_julian_day(int jd)
+{
+// [year,week,day-of-week,ndays,week-julian-day]
+
+   [int y,int yjd]=year_from_julian_day(jd);
+   int yday=jd-yjd+1;
+
+   int k=4+(yjd-4)%7;
+   int w=(yday+k)/7;
+   int wjd=jd-(jd+1)%7;
+
+// fixme: week number
+
+   return ({y,w,1+(yjd+yday)%7,7,wjd});
+}
+
+static array(int) week_from_week(int y,int w)
+{
+// [year,week,1 (wd),ndays,week-julian-day]
+
+   int yjd=julian_day_from_year(y);
+   int wjd=-5+yjd-(yjd+3)%7;
+
+//   fixme: week number
+
+   return ({y,w,1,7,wjd+w*7});
+}
+
+static int compat_week_day(int n)
+{
+   return n%7;
+}
+
+static int year_remaining_days(int y,int yday)
+{
+   return 354+year_leap_year(y)-yday;
+}
+
+class cYear
+{
+   inherit YMD::cYear;
+
+   int number_of_days()
+   {
+      switch (n)
+      {
+	 case 0: return 0;
+	 case 1: return 354+leap_year();
+	 default: 
+	    return julian_day_from_year(y+n)-yjd;
+      }
+   }
+
+   int number_of_months()
+   {
+      return 12*n;
+   }
+
+   int number_of_weeks()
+   {
+      if (!n) return 1;
+//        if (n==1) return 51;
+      return 
+	 Week("julian",jd)
+	 ->range(Week("julian",julian_day_from_year(y+n)-1))
+	 ->number_of_weeks();
+   }
+
+   TimeRange place(TimeRange what,void|int force)
+   {
+      if (what->is_day)
+      {
+	 int yd=what->yd;
+	 if (yd==355 && !year_leap_year(y))
+	    if (!force) return 0; // can't place
+	    else return Day("julian_r",julian_day_from_year(y+1),rules);
+	 return Day("ymd_yd",rules,y,yjd,yjd+yd-1,yd,what->n);
+      }
+
+      return ::place(what,force);
+   }
+}
+
+class cDay
+{
+   inherit YMD::cDay;
+
+   int number_of_months()
+   {
+      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;
+   }
+}
+
+class cMonth
+{
+   inherit YMD::cMonth;
+
+   static int months_to_month(int y2,int m2)
+   {
+      return (y2-y)*12+(m2-m);
+   }
+}
+
+class cWeek
+{
+   inherit YMD::cWeek;
+
+   static int weeks_to_week(int y2,int w2)
+   {
+      [int y3,int w3,int wd2,int nd2,int jd2]=week_from_week(y2,w2);
+      return (jd2-jd)/7;
+   }
+
+   int number_of_days()
+   {
+      return 7*n;
+   }
+}
diff --git a/lib/modules/Calendar.pmod/Julian.pmod b/lib/modules/Calendar.pmod/Julian.pmod
index 7c03a20b858cc0e31f5795e7de6f5f34fd9b1a64..1e2c90b05dbf713bd5a0a99b0b02aa14a5689e98 100644
--- a/lib/modules/Calendar.pmod/Julian.pmod
+++ b/lib/modules/Calendar.pmod/Julian.pmod
@@ -1,35 +1,47 @@
-inherit Calendar.Gregorian;
+//!
+//! module Calendar
+//! submodule Julian
+//! inherits YMD
+//!
+//! 	This is the Julian calendar, conjured up by
+//!	the old Romans when their calendar were just too
+//!	wierd. It was used by the christians as so far
+//!	as the 18th century in some parts of the world.
+//!	(Especially the protestantic and orthodox parts.)
+//!
+//! note:
+//!	Don't confuse the <i>julian day</i> with the Julian
+//!	calendar. The former is just a linear numbering of days,
+//!	used in the Calendar module as a common unit for
+//!	absolute time.
 
-class Year
-{
-  inherit Calendar.Gregorian.Year;
-
-  int julian_day(int d) // jd%7 gives weekday, mon=0, sun=6
-  {
-    return 1721424 + d + (36525*(y-1))/100;
-  }
+import ".";
+inherit Gregorian:Gregorian;
 
-  int leap()
-  {
-    return !(y%4);
-  }
+string calendar_name() { return "Julian"; }
 
+static int year_leap_year(int y) 
+{ 
+   return !((y)%4);
 }
 
-class Day
+// [y,yjd]
+static array year_from_julian_day(int jd)
 {
-  inherit Calendar.Gregorian.Day;
+   int d=jd-1721058;
 
-  void create(int ... arg)
-  {
-    if (!sizeof(arg))
-    {
-      int jd = Calendar.Gregorian.Day()->julian_day()-1721424;
-      y = jd*100/36525+1;
-      d = jd-(y-1)*36525/100;
-    }
-    else
-      ::create(@arg);
-  }
+   int quad=d/1461;
+   int quad_year=max( (d%1461-1)/365, 0);
 
+   return 
+   ({
+      quad*4+quad_year,
+      1721058+1461*quad+365*quad_year+!!quad_year
+   });
+}
+
+static int julian_day_from_year(int y)
+{
+   y--;
+   return 1721424+y*365+y/4;
 }
diff --git a/lib/modules/Calendar.pmod/Language.pmod b/lib/modules/Calendar.pmod/Language.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..0f24aa6d51881e7e581e7c8ffd12bfea763903ea
--- /dev/null
+++ b/lib/modules/Calendar.pmod/Language.pmod
@@ -0,0 +1,702 @@
+import ".";
+
+static string flat(string s)
+{
+   return replace(lower_case(s),
+		  "àáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ'- "/1,
+		  "aaaaaaeceeeeiiiidnoooooouuuuyty"/1+({""})*3);
+}
+
+static class _language_base
+{
+   inherit Ruleset.Language;
+
+   static mapping events_translate=0;
+
+   string translate_event(string name)
+   {
+      if (events_translate) return events_translate[name]||name;
+      return name;
+   }
+}
+
+static string roman_number(int m)
+{
+  string res="";
+  if (m<0) return "["+m+"]";
+  if (m==0) return "O";
+  if (m>100000) return "["+m+"]";
+  while (m>999) { res+="M"; m-=1000; }
+  if (m>899) { res+="CM"; m-=900; }
+  else if (m>499) { res+="D"; m-=500; }
+  else if (m>399) { res+="CD"; m-=400; }
+  while (m>99) { res+="C"; m-=100; }
+  if (m>89) { res+="XC"; m-=90; }
+  else if (m>49) { res+="L"; m-=50; }
+  else if (m>39) { res+="XL"; m-=40; }
+  while (m>9) { res+="X"; m-=10; }
+  if (m>8) return res+"IX";
+  else if (m>4) { res+="V"; m-=5; }
+  else if (m>3) return res+"IV";
+  while (m) { res+="I"; m--; }
+  return res;
+}
+
+static class _ymd_base
+{
+   inherit _language_base;
+
+   static mapping(int:string) month_n2s;
+   static mapping(int:string) month_n2ss;
+   static mapping(string:int) month_s2n;
+   static mapping(int:string) week_day_n2s;
+   static mapping(int:string) week_day_n2ss;
+   static mapping(string:int) week_day_s2n;
+
+   string month_name_from_number(int n)
+   {
+      return month_n2s[n];
+   }
+
+   string month_shortname_from_number(int n)
+   {
+      return month_n2ss[n];
+   }
+
+   int month_number_from_name(string name)
+   {
+      int j=(month_s2n[lower_case(name)]);
+      if (!j) error("no such month of year: %O\n",name);
+      return j;
+   }
+
+   string week_day_name_from_number(int n)
+   {
+      return week_day_n2s[n];
+   }
+
+   string week_day_shortname_from_number(int n)
+   {
+      return week_day_n2ss[n];
+   }
+
+   int week_day_number_from_name(string name)
+   {
+      int j=(week_day_s2n[lower_case(name)]);
+      if (!j) error("no such day of week: %O\n",name);
+      return j;
+   }
+
+   string week_name_from_number(int n)
+   {
+      return sprintf("w%d",n);
+   }
+
+   int week_number_from_name(string s)
+   {
+      int w;
+      if (sscanf(s,"w%d",w)) return w;
+      if (sscanf(s,"%d",w)) return w;
+      return 0;
+   }
+
+   string year_name_from_number(int y)
+   {
+      if (y<1) return sprintf("%d BC",1-y);
+      return (string)y;
+   }
+
+   int year_number_from_name(string name)
+   {
+      int y;
+      string x;
+      if (sscanf(name,"%d%s",y,x)==1 || 
+	  x=="") 
+	 return y>=0?y:y+1; // "-1" == integer year 0
+      switch (x)
+      {
+	 case "AD": case " AD": return y; 
+	 case "BC": case " BC": return -y+1;
+	 default:
+	    error("Can't understand year.\n");
+      }
+   }
+
+   string month_day_name_from_number(int d,int mnd)
+   {
+      return (string)d;
+   }
+
+// gregorian defaults
+
+   string gregorian_week_day_name_from_number(int n)
+   {
+      return week_day_n2s[(n+5)%7+1];
+   }
+
+   string gregorian_week_day_shortname_from_number(int n)
+   {
+      return week_day_n2ss[(n+5)%7+1];
+   }
+
+   int gregorian_week_day_number_from_name(string name)
+   {
+      int j=(week_day_s2n[lower_case(name)]);
+      if (!j) error("no such day of week: %O\n",name);
+      return j%7+1;
+   }
+
+   string gregorian_year_name_from_number(int y)
+   {
+      if (y<1) return sprintf("%d BC",1-y);
+      return sprintf("%d AD",y);
+   }
+
+
+// discordian defaults
+
+   string discordian_month_name_from_number(int n)
+   {
+      return ({0,"Chaos","Discord","Confusion","Bureaucracy","The Aftermath"})[n];
+   }
+
+   string discordian_month_shortname_from_number(int n)
+   {
+      return ({0,"Chs","Dsc","Cfn","Bcy","Afm"})[n];
+   }
+
+   int discordian_month_number_from_name(string name)
+   {
+      return (["chaos":1,"discord":2,"confusion":3,
+	       "bureaucracy":4,"the aftermath":5,
+	       "chs":1,"dsc":2,"cfn":3,"bcy":4,"afm":5])
+	 [lower_case(name)];
+   }
+
+   string discordian_week_day_shortname_from_number(int n)
+   {
+      return ({0,"SM","BT","PD","PP","SO","ST"})[n];
+   }
+
+   string discordian_week_day_name_from_number(int n)
+   {
+      return ({0,"Sweetmorn","Boomtime","Pungenday","Prickle-Prickle",
+	       "Setting Orange","St. Tib's day"})[n];
+   }
+
+   int discordian_week_day_number_from_name(string name)
+   {
+      return (["sweetmorn":1,"boomtime":2,"pungenday":3,"prickle-prickle":4,
+	       "setting orange":5,"st. tib's day":6,
+	       "prickleprickle":4,"setting":5,"orange":5,"tib":6,"tibs":6,
+	       "sttib":6,"sttibs":6,"saint tib's day":6,
+	       "sm":1,"bt":2,"pd":3,"pp":4,"so":5,"st":6])
+	 [lower_case(name)];
+   }
+
+   string discordian_week_name_from_number(int n)
+   {
+      return "w"+n;
+   }
+
+   string discordian_year_name_from_number(int y)
+   {
+      return (string)y;
+   }
+
+// coptic defaults
+
+   string coptic_month_name_from_number(int n)
+   {
+      return ({0,"Tout","Baba","Hator","Kiahk","Toba",
+	       "Amshir","Baramhat","Baramouda","Pakho",
+	       "Paona","Epep","Mesra","Nasie"})[n];
+   }
+
+   string coptic_month_shortname_from_number(int n)
+   {
+      return ({0,"Tou","Bab","Hat","Kia","Tob",
+	       "Ams","Bar","Bar","Pak",
+	       "Pao","Epe","Mes","Nas"})[n];
+   }
+
+   int coptic_month_number_from_name(string name)
+   {
+      return (["tout":1,"baba":2,"hator":3,"kiahk":4,"toba":5,
+	       "amshir":6,"baramhat":7,"baramouda":8,"pakho":9,
+	       "paona":10,"epep":11,"mesra":12,"nasie":13,
+	       "tou":1,"bab":2,"hat":3,"kia":4,"tob":5,
+	       "ams":6,"bar":7,"bar":8,"pak":9,
+	       "pao":10,"epe":11,"mes":12,"nas":13])
+	 [lower_case(name)];
+   }
+
+   string coptic_year_name_from_number(int y)
+   {
+      return (string)y;
+   }
+
+   int x;
+
+// islamic defaults
+
+   array(string) islamic_months=
+   ",Muharram,Safar,Rebîu'l-awwal,Rebîul-âchir,"
+   "Djumâda'l-ûla,Djumâda'l-âchira,Redjeb,Shaabân,Ramadân,"
+   "Schawwâl,Dhu'l-káada,Dhu'l-Hiddja"/",";
+   array(string) islamic_shortmonths= // help! :)
+   ",Muharram,Safar,Rebîu'l-awwal,Rebîul-âchir,"
+   "Djumâda'l-ûla,Djumâda'l-âchira,Redjeb,Shaabân,Ramadân,"
+   "Schawwâl,Dhu'l-káada,Dhu'l-Hiddja"/",";
+   mapping islamic_backmonth=0;
+   array(string) islamic_shortweekdays=
+   ",aha,ith,thu,arb,kha,dsc,sab"/",";
+   array(string) islamic_weekdays=
+   ",ahad,ithnain,thulâthâ,arbiâ,khamîs,dschuma,sabt"/",";
+   mapping islamic_backweekday=0;
+
+   string islamic_month_name_from_number(int n)
+   {
+      return islamic_months[n];
+   }
+
+   string islamic_month_shortname_from_number(int n)
+   {
+      return islamic_shortmonths[n];
+   }
+
+   int islamic_month_number_from_name(string name)
+   {
+      if (!islamic_backmonth)
+      {
+	 islamic_backmonth=
+	    mkmapping(map(islamic_months[1..],flat),
+		      enumerate(12,1,1))|
+	    mkmapping(map(islamic_months[1..],flat),
+		      enumerate(12,1,1))|
+	 (["rabi1":2,
+	   "rabi2":3,
+	   "djumada1":4,
+	   "djumada2":5]);
+      }
+      
+      return islamic_backmonth[`-(flat(name),"-","'"," ")];
+   }
+
+   string islamic_week_day_name_from_number(int n)
+   {
+      return "jaum el "+islamic_weekdays[n];
+   }
+
+   string islamic_week_day_shortname_from_number(int n)
+   {
+      return islamic_shortweekdays[n];
+   }
+
+   int islamic_week_day_number_from_name(string name)
+   {
+      if (!islamic_backweekday)
+      {
+	 islamic_backweekday=
+	    mkmapping(map(map(islamic_weekdays[1..],flat),`-,"'","-"),
+		      enumerate(7,1,1))|
+	    mkmapping(map(map(islamic_weekdays[1..],flat),`-,"'","-"),
+		      enumerate(7,1,1));
+      }
+      
+      sscanf(name,"jaum el %s",name);
+      return islamic_backweekday[`-(flat(name),"-","'")];
+   }
+
+
+   string islamic_week_name_from_number(int n)
+   {
+      return "w"+n;
+   }
+
+   string islamic_year_name_from_number(int y)
+   {
+      if (y<1) return sprintf("%d BH",1-y);
+      return sprintf("%d AH",y);
+   }
+}
+
+// ----------------------------------------------------------------
+
+// this sets up the mappings from the arrays
+
+#define SETUPSTUFF							\
+      month_n2s=mkmapping(enumerate(12,1,1),month_names);		\
+      month_n2ss= 							\
+	 mkmapping(enumerate(12,1,1),map(month_names,predef::`[],0,2));	\
+      month_s2n=							\
+	 mkmapping(map(map(month_names,predef::`[],0,2),flat),	\
+		   enumerate(12,1,1))					\
+	 | mkmapping(map(month_names,flat),enumerate(12,1,1));	\
+      week_day_n2s= mkmapping(enumerate(7,1,1),week_day_names);		\
+      week_day_n2ss= mkmapping(enumerate(7,1,1),			\
+			       map(week_day_names,predef::`[],0,2));	\
+      week_day_s2n= 							\
+	 mkmapping(map(map(week_day_names,predef::`[],0,2),flat),	\
+		   enumerate(7,1,1))					\
+	 | mkmapping(map(week_day_names,flat),enumerate(7,1,1))
+
+// ----------------------------------------------------------------
+// now the real classes:
+
+// this should probably be called UK_en or something:
+
+constant cENGLISH=cISO;
+class cISO
+{
+   inherit _ymd_base;
+   
+   constant month_names=
+   ({"January","February","March","April","May","June","July","August",
+     "September","October","November","December"});
+
+   constant week_day_names=
+   ({"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"});
+
+   void create()
+   {
+      SETUPSTUFF;
+   }
+
+   string week_name_from_number(int n)
+   {
+      return sprintf("w%d",n);
+   }
+
+   int week_number_from_name(string s)
+   {
+      int w;
+      if (sscanf(s,"w%d",w)) return w;
+      if (sscanf(s,"%d",w)) return w;
+      return 0;
+   }
+
+   string year_name_from_number(int y)
+   {
+      if (y<1) return sprintf("%d BC",1-y);
+      return (string)y;
+   }
+};
+
+// swedish (note: all name as cLANG where LANG is in caps)
+
+constant cSE_SV=cSWEDISH;
+class cSWEDISH
+{
+   inherit _ymd_base;
+
+   static private constant month_names=
+   ({"januari","februari","mars","april","maj","juni","juli","augusti",
+     "september","oktober","november","december"});
+
+   static private constant week_day_names=
+   ({"måndag","tisdag","onsdag","torsdag",
+     "fredag","lördag","söndag"});
+
+   static mapping events_translate=
+   ([
+      "New Year's Day":		"Nyårsdagen",
+      "Epiphany":		"Trettondag jul",
+      "King's Nameday":		"H K M Konungens namnsdag",
+      "Candlemas":		"Kyndelsmässodagen",
+      "St. Valentine":		"Alla hjärtans dag",
+      "Int. Women's Day":	"Internationella kvinnodagen",
+      "Crown Princess' Nameday":"H K M Kronprinsessans namnsdag",
+      "Waffle Day":		"Våffeldagen",
+      "Annunciation":		"Marie bebådelsedag",
+      "Labor Day":		"Första maj",
+      "Sweden's Flag Day":	"Svenska flaggans dag",
+      "St. John the Baptist":	"Johannes Döpares dag",
+      "Crown Princess' Birthday":"H K M Kronprinsessans födelsedag",
+      "Queen's Nameday":	"H K M Drottningens namnsdag",
+      "UN Day":			"FN-dagen",
+      "All saints Day":		"Allhelgonadagen",
+      "King's Nameday":		"H K M Konungens namnsdag",
+      "King's Birthday":	"H K M Konungens födelsedag",
+      "St. Lucy":		"Luciadagen",
+      "Queen's Birthday":	"H K M Drottningens födelsedag",
+      "Christmas Eve":		"Julafton",
+      "Christmas Day":		"Juldagen",
+      "St. Stephen":		"Annandagen",
+      "New Year's Eve":		"Nyårsafton",
+      "Midsummer's Eve":	"Midsommarafton",
+      "Midsummer's Day":	"Midsommardagen",
+      "All Saints Day":		"Allhelgonadagen",
+
+      "Fat Tuesday":		"Fettisdagen",
+      "Palm Sunday":		"Palmsöndagen",
+      "Good Friday":		"Långfredagen",
+      "Easter Eve":		"Påskafton",
+      "Easter":			"Påskdagen",
+      "Easter Monday":		"Annandag påsk",
+      "Ascension":		"Kristi himmelsfärd",
+      "Pentecost Eve":		"Pingstafton",
+      "Pentecost":		"Pingst",
+      "Pentecost Monday":	"Annandag pingst",
+      "Advent 1":		"Första advent",
+      "Advent 2":		"Andra advent",
+      "Advent 3":		"Tredje advent",
+      "Advent 4":		"Fjärde advent",
+      "Mother's Day":		"Mors dag",
+      "Father's Day":		"Fars dag",
+
+      "Summer Solstice":	"Sommarsolstånd",
+      "Winter Solstice":	"Vintersolstånd",
+      "Spring Equinox":		"Vårdagjämning",
+      "Autumn Equinox":		"Höstdagjämning",
+
+// not translated:
+//	"Halloween"
+//	"Alla helgons dag"
+//	"Valborgsmässoafton"
+   ]);
+
+   void create()
+   {
+      SETUPSTUFF;
+   }
+
+   string week_name_from_number(int n)
+   {
+      return sprintf("v%d",n);
+   }
+
+   int week_number_from_name(string s)
+   {
+      if (sscanf(s,"v%d",int w)) return w;
+      return ::week_number_from_name(s);
+   }
+
+   string year_name_from_number(int y)
+   {
+      if (y<1) return sprintf("%d fk",1-y);
+      return (string)y;
+   }
+}
+
+// austrian
+// Martin Baehr <mbaehr@email.archlab.tuwien.ac.at>
+
+class cAUSTRIAN
+{
+   inherit _ymd_base;
+
+   static private constant month_names=
+      ({"jänner","feber","märz","april","mai","juni","juli","august",
+        "september","oktober","november","dezember"});
+
+   static private constant week_day_names=
+      ({"montag","dienstag","mittwoch","donnerstag",
+        "freitag","samstag","sonntag"});
+
+   void create()
+   {
+      SETUPSTUFF;
+   }
+}
+
+// Welsh
+
+class cWELSH
+{
+   inherit _ymd_base;
+
+   static private constant month_names=
+   ({"ionawr","chwefror","mawrth","ebrill","mai","mehefin",
+     "gorffenaf","awst","medi","hydref","tachwedd","rhagfyr"});
+
+   static private constant week_day_names=
+   ({"Llun","Mawrth","Mercher","Iau","Gwener","Sadwrn","Sul"});
+
+   string week_day_name_from_number(int n)
+   {
+      return "dydd "+::week_day_name_from_number(n);
+   }
+
+   int week_day_number_from_name(string name)
+   {
+      sscanf(name,"dydd %s",name);
+      return week_day_number_from_name(name);
+   }
+
+   void create()
+   {
+      SETUPSTUFF;
+   }
+}
+
+// Spanish
+// Julio César Gázquez <jgazquez@dld.net>
+
+class cSPANISH
+{
+   inherit _ymd_base;
+
+   static private constant month_names=
+   ({"enero","febrero","marzo","abril","mayo","junio",
+     "julio","agosto","setiembre","octubre","noviembre","diciembre"});
+
+   static private constant week_day_names=
+   ({"lunes","martes","miércoles","jueves",
+     "viernes","sábado","domingo"});
+
+// contains argentina for now
+   static mapping events_translate=
+   ([
+      "Epiphany":"Día de Reyes", // Epifania
+      "Malvinas Day":"Día de las Malvinas",
+      "Labor Day":"Aniversario de la Revolución",
+      "Soberany's Day":"Día de la soberania",
+      "Flag's Day":"Día de la bandera",
+      "Independence Day":"Día de la independencia",
+      "Assumption Day":"Día de la asunción", // ?
+      "Gral San Martín decease":
+      "Aniversario del fallecimiento del Gral. San Martin",
+      "Race's Day":"Día de la Raza",
+      "All Saints Day":"Día de todos los santos",
+      "Immaculate Conception":"Inmaculada Concepción",
+      "Christmas Day":"Natividad del Señor",
+      "New Year's Day":"Año Nuevo",
+      "Holy Thursday":"Jueves Santo",
+      "Good Friday":"Viernes Santo",
+      "Holy Saturday":"Sãbado de gloria",
+      "Easter":"Domingo de resurrección",
+      "Corpus Christi":"Corpus Christi"
+   ]);
+
+   void create()
+   {
+      SETUPSTUFF;
+   }
+}
+
+// Hungarian
+// Csongor Fagyal <concept@conceptonline.hu>
+
+class cHUNGARIAN
+{
+   inherit _ymd_base;
+
+   static private constant month_names=
+   ({"Január","Február","Március","Április","Május","Június",
+     "Július","August","September","October","November","December"});
+
+   static private constant week_day_names=
+   ({"Hétfo","Kedd","Szerda","Csütörtkök","Péntek","Szombat","Vasárnap"});
+
+// contains argentina for now
+   static mapping events_translate=
+   ([
+      "New Year's Day":"Úb év ünnepe",
+      "1848 Revolution Day":"Az 'Az 1848-as Forradalom Napja",
+      "Holiday of Labor":"A munka ünnepe",
+      "Constitution Day":"Az alkotmány ünnepe",
+      "'56 Revolution Day":"Az '56-os Forradalom ünnepe",
+      "Easter":"Húsvét",
+      "Easter monday":"Húsvét",
+      "Whitsunday":"Pünkösd",
+      "Whitmonday":"Pünkösd",
+      "Christmas":"Christmas",
+   ]);
+
+   void create()
+   {
+      SETUPSTUFF;
+   }
+}
+
+// Modern Latin
+
+class cLATIN
+{
+   inherit _ymd_base;
+
+   static array(string) month_names=
+   ({"Ianuarius", "Februarius", "Martius", "Aprilis", "Maius", "Iunius", 
+     "Iulius", "Augustus", "September", "October", "November", "December" });
+
+   static private constant week_day_names=
+   ({"lunae","Martis","Mercurii","Jovis","Veneris","Saturni","solis"});
+
+   string week_day_name_from_number(int n)
+   {
+      return ::week_day_name_from_number(n)+" dies";
+   }
+
+   int week_day_number_from_name(string name)
+   {
+      sscanf(name,"%s dies",name);
+      return week_day_number_from_name(name);
+   }
+
+   string gregorian_year_name_from_number(int y)
+   {
+      return year_name_from_number(y);
+   }
+
+   string year_name_from_number(int y)
+   {
+      if (y<1) return sprintf("%d BC",1-y); // ?
+      return sprintf("anno ab Incarnatione Domini %s",roman_number(y));
+   }
+
+   void create()
+   {
+      SETUPSTUFF;
+   }
+}
+
+// Roman latin
+
+class cROMAN
+{
+   inherit cLATIN;
+
+   static array(string) month_names=
+   ({"Ianuarius", "Februarius", "Martius", "Aprilis", "Maius", "Iunius",
+     "Quintilis", // Iulius
+     "Sextilis",  // Augustus
+     "September", "October", "November", "December"
+   });
+
+   string year_name_from_number(int y)
+   {
+      return sprintf("%s ab urbe condita",roman_number(y+752));
+   }
+   
+   string month_day_name_from_number(int d,int mnd)
+   {
+// this is not really correct, I've seen but
+// i can't find it - they did something like 4 from the start of the
+// months, 19 from the end of the month.
+      return roman_number(d); 
+   }
+}
+
+
+
+
+// ----------------------------------------------------------------
+
+// find & compile language
+
+static mapping _cache=([]);
+
+Ruleset.Language `[](string lang)
+{
+   lang=upper_case(lang);
+   Ruleset.Language l=_cache[lang];
+   if (l) return l;
+   program cl=::`[]("c"+lang);
+
+   if (!cl) { return ([])[0]; }
+
+   l=_cache[lang]=cl();
+   
+   return l;
+}
diff --git a/lib/modules/Calendar.pmod/Namedays.pmod b/lib/modules/Calendar.pmod/Namedays.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..42be2a93469709ae294e40d045f0b3e3d9212dce
--- /dev/null
+++ b/lib/modules/Calendar.pmod/Namedays.pmod
@@ -0,0 +1,745 @@
+import ".";
+inherit Event;
+
+// ----------------------------------------------------------------
+// special nameday objects
+// ----------------------------------------------------------------
+
+class Sweden
+{
+   inherit Namedays;
+
+   mapping lookup_pre1986=0;
+   mapping lookup_1986=0;
+   mapping lookup_1993=0;
+
+   void create()
+   {
+      name="Sweden";
+   }
+
+   static array(string) namedays_year(int y)
+   {
+      if (y<1986) return swedish_namedays_pre1986;
+      if (y<1993) return swedish_namedays_1986;
+      return swedish_namedays_1993;
+   }
+
+   static int nameday_lookup(int y,string s)
+   {
+      if (y<1986) 
+	 return (lookup_pre1986||
+		 (lookup_pre1986=make_lookup(swedish_namedays_pre1986)))
+	    [lower_case(s)];
+      if (y<1993) 
+	 return (lookup_1986||
+		 (lookup_1986=make_lookup(swedish_namedays_1986)))
+	    [lower_case(s)];
+      return (lookup_1993||
+	      (lookup_1993=make_lookup(swedish_namedays_1993)))
+	 [lower_case(s)];
+   }
+
+   constant swedish_namedays_pre1986=
+   ({ 0, "Svea", "Alfred", "Rut", "Hanna", 0 /* trettondag */,
+      "August", "Erland", "Gunnar", "Sigurd", "Hugo", "Frideborg",
+      "Knut", "Felix", "Laura", "Hjalmar", "Anton", "Hilda", "Henrik",
+      "Fabian", "Agnes", "Vincent", "Emilia", "Erika", "Paulus",
+      "Botolda", "Göte", "Karl", "Valter", "Gunhild", "Ivar", "Max",
+      0/*kyndels*/, "Disa", "Ansgar", "Agata", "Dorotea", "Rikard",
+      "Berta", "Fanny", "Eugenia", "Yngve", "Evelina", "Agne",
+      "Valentin", "Sigfrid", "Julia", "Alexandra", "Frida",
+      "Gabriella", "Hulda", "Hilding", "Martina", "Torsten",
+      "Mattias", "Sigvard", "Torgny", "Lage", "Maria", "Albin",
+      "Ernst", "Gunborg", "Adrian", "Tora", "Ebba", "Ottilia",
+      "Filippa", "Torbjörn", "Edla", "Edvin", "Viktoria", "Greger",
+      "Matilda", "Kristofer", "Herbert", "Gertrud", "Edvard", "Josef",
+      "Joakim", "Bengt", "Viktor", "Gerda", "Gabriel", "Mary",
+      "Emanuel", "Rudolf", "Malkolm", "Jonas", "Holger", "Ester",
+      "Harald", "Gudmund", "Ferdinand", "Ambrosius", "Nanna",
+      "Vilhelm", "Ingemund", "Hemming", "Otto", "Ingvar", "Ulf",
+      "Julius", "Artur", "Tiburtius", "Olivia", "Patrik", "Elias",
+      "Valdemar", "Olavus Petri", "Amalia", "Anselm", "Albertina",
+      "Georg", "Vega", "Markus", "Teresia", "Engelbrekt", "Ture",
+      "Tyko", "Mariana", "Valborg", "Filip", "Göta", "Monika",
+      "Gotthard", "Sigmund", "Gustava", "Åke", "Jonathan", "Esbjörn",
+      "Märta", "Charlotta", "Linnea", "Halvard", "Sofia", "Hilma",
+      "Rebecka", "Erik", "Alrik", "Karolina", "Konstantin", "Henning",
+      "Desideria", "Ragnvald", "Urban", "Vilhelmina", "Blenda",
+      "Ingeborg", "Baltsar", "Fritjof", "Isabella", "Nikodemus",
+      "Rutger", "Ingemar", "Holmfrid", "Bo", "Gustav", "Robert",
+      "Salomon", "Börje", "Svante", "Bertil", "Eskil", "Aina",
+      "Håkan", "Justina", "Axel", "Torborg", "Björn", "Germund",
+      "Flora", "Alf", "Paulina", "Adolf", "Johan", "David", "Rakel",
+      "Selma", "Leo", "Petrus", "Elof", "Aron", "Rosa", "Aurora",
+      "Ulrika", "Melker", "Esaias", "Klas", "Kjell", "Götilda",
+      "Anund", "Eleonora", "Herman", "Joel", "Folke", "Ragnhild",
+      "Reinhold", "Alexis", "Fredrik", "Sara", "Margareta", "Johanna",
+      "Magdalena", "Emma", "Kristina", "Jakob", "Jesper", "Marta",
+      "Botvid", "Olof", "Algot", "Elin", "Per", "Karin", "Tage",
+      "Arne", "Ulrik", "Sixten", "Arnold", "Sylvia", "Roland", "Lars",
+      "Susanna", "Klara", "Hillevi", "Ebbe", "Stella", "Brynolf",
+      "Verner", "Helena", "Magnus", "Bernhard", "Josefina",
+      "Henrietta", "Signe", "Bartolomeus", "Lovisa", "Östen", "Rolf",
+      "Augustin", "Hans", "Albert", "Arvid", "Samuel", "Justus",
+      "Alfhild", "Moses", "Adela", "Sakarias", "Regina", "Alma",
+      "Augusta", "Tord", "Dagny", "Tyra", "Ambjörn", "Ida", "Sigrid",
+      "Eufemia", "Hildegard", "Alvar", "Fredrika", "Agda", "Matteus",
+      "Maurits", "Tekla", "Gerhard", "Signhild", "Enar", "Dagmar",
+      "Lennart", "Mikael", "Helge", "r", "Ludvig", "Evald", "Frans",
+      "Bror", "Jenny", "Birgitta", "Nils", "Ingrid", "Helmer",
+      "Erling", "Valfrid", "Teofil", "Manfred", "Hedvig", "Fingal",
+      "Antonietta", "Lukas", "Tore", "Sibylla", "Birger", "Seved",
+      "Sören", "Evert", "Inga", "Amanda", "Sabina", "Simon", "Viola",
+      "Elsa", "Edit", 0 /* allhelgona */, "Tobias", "Hubert",
+      "Sverker", "Eugen", "Gustav Adolf", "Ingegerd", "Vendela",
+      "Teodor", "Martin Luther", "Mårten", "Konrad", "Kristian",
+      "Emil", "Leopold", "Edmund", "Napoleon", "Magnhild", "Elisabet",
+      "Pontus", "Helga", "Cecilia", "Klemens", "Gudrun", "Katarina",
+      "Torkel", "Astrid", "Malte", "Sune", "Anders", "Oskar", "Beata",
+      "Lydia", "Barbro", "Sven", "Nikolaus", "Agaton", "Virginia",
+      "Anna", "Malin", "Daniel", "Alexander", "Lucia", "Sten",
+      "Gottfrid", "Assar", "Inge", "Abraham", "Isak", "Israel",
+      "Tomas", "Natanael", "Adam", "Eva", "Stefan", "Johannes",
+      "Abel", "Set", "Sylvester",0});
+
+   constant swedish_namedays_1986=
+   ({ 0, "Svea,Bore,Sverre",
+      "Alfred,Alfrida,Annefrid", "Rut,Ritva,Roger",
+      "Hanna,Hannele,Hanny", 0 /* trettondag */, "August,Öjar,Örjan",
+      "Erland,Erhard,Erla", "Gunnar,Gun,Gunno", "Sigurd,Sigrun,Sigyn",
+      "Hugo,Hagar", "Frideborg,Fridolf,Fridolin", "Knut,Kent,Kennet",
+      "Felix,Felicia,Fritz", "Laura,Lauritz,Lotten",
+      "Hjalmar,Herdis,Hjördis", "Anton,Anja,Antonia",
+      "Hilda,Hildor,Hildur", "Henrik,Henrika,Henry", "Fabian,Lina,Linus",
+      "Agnes,Agnar,Agneta", "Vincent,Vanja,Veine",
+      "Emilia,Emilie,Mildred", "Erika,Jarl,Jarla", "Paulus,Paul,Paula",
+      "Botolda,Tilda,Tilly", "Göte,Götar,Jöns", "Karl,Kally,Karla",
+      "Valter,Valerie,Volter", "Gunhild,Gunilla,Gunnel", "Ivar,Iva,Ivan",
+      "Max,Marielle,Marietta", 0/*kyndels*/, "Disa,Dick,Didrik",
+      "Ansgar,Anneli,Ansa", "Agata,Aili,Aivi", "Dorotea,Dora,Doris",
+      "Rikard,Ricky,Rigmor", "Berta,Bert,Bertram", "Fanny,Sanny,Sonny",
+      "Eugenia,Egon,Eira", "Yngve,Yvette,Yvonne",
+      "Evelina,Elaine,Evelyn", "Agne,Alin,Alina",
+      "Valentin,Valentina,Vally", "Sigfrid,Sigbert,Sigbritt",
+      "Julia,Juliana,Juliette", "Alexandra,Sandor,Sandra",
+      "Frida,Fride,Frode", "Gabriella,Ella,Elna", "Hulda,Haldis,Haldo",
+      "Hilding,Hildeborg,Hildemar", "Martina,Tim,Tina",
+      "Torsten,Toivo,Torun", "Mattias,Matti,Mats",
+      "Sigvard,Sigvald,Sigvor", "Torgny,Torvald", "Lage,Laila,Lave",
+      "Maria,Marie,Mary", "Albin,Alba,Alban", "Ernst,Erna,Ernfrid",
+      "Gunborg,Gunbritt,Gunvald", "Adrian,Adrienne,Astor",
+      "Tora,Toini,Tor", "Ebba,Ebon,Evonne", "Ottilia,Petra,Petronella",
+      "Filippa,Gunlög,Åslög", "Torbjörn,Torben,Torgun",
+      "Edla,Edling,Ethel", "Edvin,Diana,Edna", "Viktoria,Vibeke,Viking",
+      "Greger,Grels,Greta", "Matilda,Maud,Moa",
+      "Kristofer,Christel,Christer", "Herbert,Herta,Hervor",
+      "Gertrud,Gertie,Gölin", "Edvard,Eda,Eddie", "Josef,James,Janet",
+      "Joakim,Jockum,Kim", "Bengt,Bengta,Benita", "Viktor,Vimar,Våge",
+      "Gerda,Anngerd,Gerd", "Gabriel,Gabrielle,Gunni", "Mary,Marion",
+      "Emanuel,Emanuella,Immanuel", "Rudolf,Rode,Rudi",
+      "Malkolm,Elma,Elmer", "Jonas,Jon,Jonna", "Holger,Olga",
+      "Ester,Estrid,Vasti", "Harald,Hadar,Hardy",
+      "Gudmund,Gudmar,Gunder", "Ferdinand,Gunvi,Gunvor",
+      "Ambrosius,Irene,Irina", "Nanna,Nancy,Nanny",
+      "Vilhelm,William,Willy", "Ingemund,Ingemo,Irma",
+      "Hemming,Heimer,Helmut", "Otto,Orvar,Ottar",
+      "Ingvar,Ingvald,Ingvor", "Ulf,Ylva,Yrsa", "Julius,Gillis",
+      "Artur,Aldor,Atle", "Tiburtius,Ellen,Elly", "Olivia,Oliver,Ove",
+      "Patrik,Patricia,Percy", "Elias,Elis,Elise",
+      "Valdemar,Valdis,Volmar", "Olavus Petri,Olaus Petri",
+      "Amalia,Amelie,Amy", "Anselm,Annevi,Annvor",
+      "Albertina,Alida,Allan", "Georg,Georgina,Jörgen",
+      "Vega,Viggo,Viveka", "Markus,Marika,Mark", "Teresia,Terese,Tessy",
+      "Engelbrekt,Engelbert,Enok", "Ture,Turid,Tuve",
+      "Tyko,Toralf,Torulf", "Mariana,Marianne,Marina",
+      "Valborg,Maj,Maja", "Filip,Åsa,Åse", "Göta,Görel,Götmar",
+      "Monika,Majne,Mona", "Gotthard,Gotthild,Gotty", "Sigmund,Sigge",
+      "Gustava,Gullvi,Gullbritt", "Åke,Åge,Ågot", "Jonathan,John,Johnny",
+      "Esbjörn,Elvy,Essy", "Märta,Meta,Märit",
+      "Charlotta,Charlotte,Lotta", "Linnea,Linn,Lis",
+      "Halvard,Hallvor,Halvar", "Sofia,Sia,Sofie", "Hilma,Helvi,Hilmer",
+      "Rebecka,Renee,Rosita", "Erik,Erk,Jerker", "Alrik,Alda,Altea",
+      "Karolina,Carola,Caroline", "Konstantin,Conny,Konstatia",
+      "Henning,Henny,Pål", "Desideria,Dennis,Desiree",
+      "Ragnvald,Ragnvi,Ragnvor", "Urban,Una,Uno",
+      "Vilhelmina,Vilma,Vilmar", "Blenda,Beda,Britten",
+      "Ingeborg,Ingabritt,Ingbritt", "Baltsar,Bill,Billy",
+      "Fritjof,Majny,Majvi", "Isabella,Iris,Isa", "Nikodemus,Nina,Ninni",
+      "Rutger,Runa,Rune", "Ingemar,Ingar,Ingmarie",
+      "Holmfrid,Helfrid,Helfrida", "Bo,Bodil,Boel",
+      "Gustav,Gusten,Gösta", "Robert,Robin,Ruben", "Salomon,Sally",
+      "Börje,Belinda,Björg", "Svante,Sante,Sjunne",
+      "Bertil,Berit,Berthold", "Eskil,Eje,Evan", "Aina,Aino,Roine",
+      "Håkan,Hakon,Hakvin", "Justina,Jim,Jimmy", "Axel,Axelia,Axelina",
+      "Torborg,Torhild,Toril", "Björn,Bjarne,Björne",
+      "Germund,Jerry,Jill", "Flora,Florence,Florentin",
+      "Alf,Alvin,Alvina", "Paulina,Pamela,Paulette",
+      "Adolf,Adolfina,Ally", "Johan,Jan", "David,Davida,Daisy",
+      "Rakel,Rafael,Ralf", "Selma,Selim,Selmer", "Leo,Lola,Liselott",
+      "Petrus,Peter,Petter", "Elof,Elvira,Viran", "Aron,Arent,Arild",
+      "Rosa,Rose,Rosemarie", "Aurora,Andre,Aurelia",
+      "Ulrika,Ellika,Ulla", "Melker,Marja,Mirjam", "Esaias,Elisiv,Esse",
+      "Klas,Claudia,Klaus", "Kjell,Kajsa,Kettil", "Götilda,Göran,Jörn",
+      "Anund,Anita,Ante", "Eleonora,Eleonor,Ellinor",
+      "Herman,Hanne,Hermine", "Joel,Joar,Jorunn", "Folke,Fale,Fylgia",
+      "Ragnhild,Ragni,Runo", "Reinhold,Reine,Reino", "Alexis,Alex,Alice",
+      "Fredrik,Fred,Freddy", "Sara,Charles,Saga",
+      "Margareta,Margit,Margret", "Johanna,Jean,Jeanette",
+      "Magdalena,Magda,Madeleine", "Emma,Elena,Emmy",
+      "Kristina,Kerstin,Kristin", "Jakob,Jack", "Jesper,Jessika,Jessie",
+      "Marta,Marit,Marita", "Botvid,Reidar,Reidun", "Olof,Ola,Olle",
+      "Algot,Margot,Vilgot", "Elin,Elon,Elina", "Per,Peder,Pernilla",
+      "Karin,Karen,Kåre", "Tage,Tanja,Truls", "Arne,Arna,Arnevi",
+      "Ulrik,Unn,Unni", "Sixten,Säve,Sölve", "Arnold,Annika,Annmari",
+      "Sylvia,Silja,Silvia", "Roland,Ronald,Ronny", "Lars,Lasse,Lorentz",
+      "Susanna,Sanna,Susanne", "Klara,Clarence,Clary",
+      "Hillevi,Hilja,Irja", "Ebbe,Eberhard,Efraim",
+      "Stella,Estelle,Stellan", "Brynolf,Benjamin,Benny",
+      "Verner,Verna,Veronika", "Helena,Helen,Helny",
+      "Magnus,Mogens,Måns", "Bernhard,Berna,Bernt", "Josefina,Josefin",
+      "Henrietta,Harriet,Harry", "Signe,Signar,Signy",
+      "Bartolomeus,Carita,Rita", "Lovisa,Louis,Louise",
+      "Östen,Ejvind,Öjvind", "Rolf,Raoul,Rasmus", "Augustin,Gusti,Gurli",
+      "Hans,Hampus,Hasse", "Albert,Albrekt,Aste", "Arvid,Arvida,Vidar",
+      "Samuel,Sam,Solveig", "Justus,Jane,Judit", "Alfhild,Alfons,Arja",
+      "Moses,Molly,My", "Adela,Adele,Adin", "Sakarias,Siv,Sivert",
+      "Regina,Gilbert,Gisela", "Alma,Adils,Almar", "Augusta,Gunda,Gunde",
+      "Tord,Tordis,Torgil", "Dagny,Dag,Daga", "Tyra,Tyr",
+      "Ambjörn,Stig,Styrbjörn", "Ida,Idar,Vida", "Sigrid,Siri,Solbritt",
+      "Eufemia,Cornelia,Cornelius", "Hildegard,Hilbert,Hildebrand",
+      "Alvar,Alva,Alve", "Fredrika,Frej,Freja", "Agda,Jan,Jannika",
+      "Matteus,Majbritt,Majlis", "Maurits,Marlene,Moritz",
+      "Tekla,Trond,Tryggve", "Gerhard,Gert,Glenn",
+      "Signhild,Sanfrid,Signhild", "Enar,Einar,Eja",
+      "Dagmar,Donald,Douglas", "Lennart,Lena,Leonard",
+      "Mikael,Majken,Mikaela", "Helge,Heidi,Härje", "r,Ragna,Ragne",
+      "Ludvig,Levi,Liv", "Evald,Eila,Eilert", "Frans,Franciska,Frank",
+      "Bror,Brage,Bruno", "Jenny,Jennifer,Jens", "Birgitta,Birgit,Britt",
+      "Nils,Nilla,Nelly", "Ingrid,Inger,Ingolf", "Helmer,Helmina,Helmy",
+      "Erling,Elvin,Elvina", "Valfrid,Ina,Inez", "Teofil,Terje,tjelvar",
+      "Manfred,Mandor,Manne", "Hedvig,Hartvig,Hedda",
+      "Fingal,Finn,Flemming", "Antonietta,Anette,Tony",
+      "Lukas,Lillemor,Lilly", "Tore,Bojan Borghild",
+      "Sibylla,Camilla,Kasper", "Birger,Brita,Britta",
+      "Seved,Sigvid,Ursula", "Sören,Severin", "Evert,Eivor,Elving",
+      "Inga,Ingalill,Ingert", "Amanda,Manda,Mandy",
+      "Sabina,Sebastian,Sussy", "Simon,Simeon,Simone",
+      "Viola,Vivi,Vivianne", "Elsa,Elsie,Ilse", "Edit,Edgar,Edor", 
+      0/*allhelgona */, "Tobias,Tova,Tove", "Hubert,Raymond,Roy",
+      "Sverker,Nora,Nore", "Eugen,Ebert,Egil", "Gustav Adolf,Gull,Gulli",
+      "Ingegerd,Ingel,Ingela", "Vendela,Vanda,Ville", "Teodor,Tea,Ted",
+      "Martin Luther,Mait,Martin", "Mårten,Marion,Morgan",
+      "Konrad,Kuno,Kurt", "Kristian,Karsten,Kersti", "Emil,Milly,Mimmi",
+      "Leopold,Leif,Lilian", "Edmund,Elida,Elisa",
+      "Napoleon,Naemi,Naima", "Magnhild,Magna,Magne",
+      "Elisabet,Lisa,Lisbeth", "Pontus,Polly,Povel", "Helga,Helle,Hilde",
+      "Cecilia,Cilla,Cissi", "Klemens,Ketty,Kitty",
+      "Gudrun,Gullan,Gullvor", "Katarina,Carina,Katrin",
+      "Torkel,Torleif", "Astrid,Asta,Astri", "Malte,Malvina,Mia",
+      "Sune,Sonja,Synnöve", "Anders,Andrea,Andreas", "Oskar,Ole,Ossian",
+      "Beata,Beatrice,Betty", "Lydia,Linda,Love", "Barbro,Barbara,Boris",
+      "Sven,Svend,Svenning", "Nikolaus,Niklas,nikolina",
+      "Agaton,Angela,Angelika", "Virginia,Vera,Vesta", "Anna,Ann,Annie",
+      "Malin,Majvor,Malena", "Daniel,Dan,Daniela",
+      "Alexander,Pia,Pierre", "Lucia,Lisen,Lisette", "Sten,Stina,Sture",
+      "Gottfrid,Kaj,Kajsa", "Assar,Odd,Osvald", "Inge,Ilona,Irmeli",
+      "Abraham,Abdon,Gideon", "Isak,Isidor,Isidora", "Israel,Gina,Gitte",
+      "Tomas,Tom,Tommy", "Natanael,Natalia,Natan", "Adam,Ada,Adina",
+      "Eva,Evita,Evy", "Stefan,Staffan,Stefanie",
+      "Johannes,Hannes,Johan", "Abel,Abbe", "Set,Viva,Vivari",
+      "Sylvester,Sylve,Sylvi",0});
+
+   constant swedish_namedays_1993= 
+   ({ 0, "Svea,Sverker",
+      "Alfred,Alfrida", "Rut,Ritva", "Hanna,Hannele", "Baltsar,Kasper",
+      "August,Augusta", "Erland,Erhard", "Gunnar,Gunder",
+      "Sigurd,Sigmund", "Hugo,Hagar", "Frideborg,Fridolf", "Knut",
+      "Felix,Felicia", "Laura,Liv", "Hjalmar,Hervor", "Anton,Tony",
+      "Hilda,Hildur", "Henrik,Henry", "Fabian,Sebastian", "Agnes,Agneta",
+      "Vincent,Veine", "Emilia,Emilie", "Erika,Eira", "Paul,Pål",
+      "Bodil,Boel", "Göte,Göta", "Karl,Karla", "Valter,Vilma",
+      "Gunhild,Gunilla", "Ivar,Joar", "Max,Magda", "Marja,Mia",
+      "Disa,Hjördis", "Ansgar,Anselm", "Lisa,Elise", "Dorotea,Dora",
+      "Rikard,Dick", "Berta,Berthold", "Fanny,Betty", "Egon,Egil",
+      "Yngve,Ingolf", "Evelina,Evy", "Agne,Agnar", "Valentin,Tina",
+      "Sigfrid,Sigbritt", "Julia,Jill", "Alexandra,Sandra",
+      "Frida,Fritz", "Gabriella,Ella", "Rasmus,Ruben", "Hilding,Hulda",
+      "Marina,Marlene", "Torsten,Torun", "Mattias,Mats",
+      "Sigvard,Sivert", "Torgny,Torkel", "Lage,Laila", "Maria,Maja",
+      "Albin,Inez", "Ernst,Erna", "Gunborg,Gunvor", "Adrian,Ada",
+      "Tora,Tor", "Ebba,Ebbe", "Isidor,Doris", "Siv,Saga",
+      "Torbjörn,Ambjörn", "Edla,Ethel", "Edvin,Elon", "Viktoria,Viktor",
+      "Greger,Iris", "Matilda,Maud", "Kristofer,Christel",
+      "Herbert,Gilbert", "Gertrud,Görel", "Edvard,Eddie",
+      "Josef,Josefina", "Joakim,Kim", "Bengt,Benny", "Viking,Vilgot",
+      "Gerda,Gert", "Gabriel,Rafael", "Mary,Marion", "Emanuel,Manne",
+      "Ralf,Raymond", "Elma,Elmer", "Jonas,Jens", "Holger,Reidar",
+      "Ester,Estrid", "Harald,Halvar", "Gunnel,Gun",
+      "Ferdinand,Florence", "Irene,Irja", "Nanna,Nanny", "Vilhelm,Willy",
+      "Irma,Mimmi", "Vanja,Ronja", "Otto,Ottilia", "Ingvar,Ingvor",
+      "Ulf,Ylva", "Julius,Gillis", "Artur,Douglas", "Tiburtius,Tim",
+      "Olivia,Oliver", "Patrik,Patricia", "Elias,Elis",
+      "Valdemar,Volmar", "Olaus,Ola", "Amalia,Amelie", "Annika,Anneli",
+      "Allan,Alida", "Georg,Göran", "Vega,Viveka", "Markus,Mark",
+      "Teresia,Terese", "Engelbrekt,Enok", "Ture,Tyko", "Kennet,Kent",
+      "Mariana,Marianne", "Valborg,Maj", "Filip,Filippa", "John,Jack",
+      "Monika,Mona", "Vivianne,Vivan", "Marit,Rita", "Lilian,Lilly",
+      "Åke,Ove", "Jonatan,Gideon", "Elvira,Elvy", "Märta,Märit",
+      "Charlotta,Lotta", "Linnea,Nina", "Lillemor,Lill", "Sofia,Sonja",
+      "Hilma,Hilmer", "Nore,Nora", "Erik,Jerker", "Majken,Majvor",
+      "Karolina,Lina", "Konstantin,Conny", "Henning,Hemming",
+      "Desiree,Renee", "Ivan,Yvonne", "Urban,Ursula", "Vilhelmina,Helmy",
+      "Blenda,Beda", "Ingeborg,Borghild", "Jean,Jeanette",
+      "Fritiof,Frej", "Isabella,Isa", "Rune,Runa", "Rutger,Roger",
+      "Ingemar,Gudmar", "Solveig,Solbritt", "Bo,Boris", "Gustav,Gösta",
+      "Robert,Robin", "Eivor,Elaine", "Petra,Petronella",
+      "Kerstin,Karsten", "Bertil,Berit", "Eskil,Esbjörn", "Aina,Eila",
+      "Håkan,Heidi", "Margit,Mait", "Axel,Axelina", "Torborg,Torvald",
+      "Björn,Bjarne", "Germund,Jerry", "Linda,Linn", "Alf,Alva",
+      "Paulina,Paula", "Adolf,Adela", "Johan,Jan", "David,Salomon",
+      "Gunni,Jim", "Selma,Herta", "Leo,Leopold", "Petrus,Peter",
+      "Elof,Leif", "Aron,Mirjam", "Rosa,Rosita", "Aurora,Adina",
+      "Ulrika,Ulla", "Melker,Agaton", "Ronald,Ronny", "Klas,Kaj",
+      "Kjell,Tjelvar", "Jörgen,Örjan", "Anund,Gunda", "Eleonora,Ellinor",
+      "Herman,Hermine", "Joel,Judit", "Folke,Odd", "Ragnhild,Ragnvald",
+      "Reinhold,Reine", "Alexis,Alice", "Fredrik,Fred", "Sara,Sally",
+      "Margareta,Greta", "Johanna,Jane", "Magdalena,Madeleine",
+      "Emma,Emmy", "Kristina,Stina", "Jakob,James", "Jesper,Jessika",
+      "Marta,Moa", "Botvid,Seved", "Olof,Olle", "Algot,Margot",
+      "Elin,Elna", "Per,Pernilla", "Karin,Kajsa", "Tage,Tanja",
+      "Arne,Arnold", "Ulrik,Alrik", "Sixten,Sölve", "Dennis,Donald",
+      "Silvia,Sylvia", "Roland,Roine", "Lars,Lorentz", "Susanna,Sanna",
+      "Klara,Clary", "Hillevi,Gullvi", "William,Bill", "Stella,Stellan",
+      "Brynolf,Sigyn", "Verner,Veronika", "Helena,Lena", "Magnus,Måns",
+      "Bernhard,Bernt", "Jon,Jonna", "Henrietta,Henny", "Signe,Signhild",
+      "Bartolomeus,Bert", "Lovisa,Louise", "Östen,Ejvind", "Rolf,Rudolf",
+      "Gurli,Gull", "Hans,Hampus", "Albert,Albertina", "Arvid,Vidar",
+      "Samuel,Sam", "Justus,Justina", "Alfhild,Alfons", "Gisela,Glenn",
+      "Harry,Harriet", "Sakarias,Esaias", "Regina,Roy", "Alma,Ally",
+      "Anita,Anja", "Tord,Tove", "Dagny,Daniela", "Tyra,Åsa",
+      "Sture,Styrbjörn", "Ida,Ellida", "Sigrid,Siri", "Dag,Daga",
+      "Hildegard,Magnhild", "Alvar,Orvar", "Fredrika,Carita",
+      "Agda,Agata", "Ellen,Elly", "Maurits,Morgan", "Tekla,Tea",
+      "Gerhard,Gert", "Kåre,Tryggve", "Einar,Enar", "Dagmar,Rigmor",
+      "Lennart,Leonard", "Mikael,Mikaela", "Helge,Helny", "Ragnar,Ragna",
+      "Ludvig,Louis", "Evald,Osvald", "Frans,Frank", "Bror,Bruno",
+      "Jenny,Jennifer", "Birgitta,Britta", "Nils,Nelly", "Ingrid,Inger",
+      "Helmer,Hadar", "Erling,Jarl", "Valfrid,Ernfrid", "Birgit,Britt",
+      "Manfred,Helfrid", "Hedvig,Hedda", "Fingal,Finn",
+      "Antonia,Annette", "Lukas,Matteus", "Tore,Torleif",
+      "Sibylla,Camilla", "Birger,Börje", "Marika,Marita",
+      "Sören,Severin", "Evert,Eilert", "Inga,Ingvald", "Amanda,My",
+      "Sabina,Ina", "Simon,Simone", "Viola,Vivi", "Elsa,Elsie",
+      "Edit,Edgar", "Andre,Andrea", "Tobias,Toini", "Hubert,Diana",
+      "Uno,Unn", "Eugen,Eugenia", "Gustav Adolf", "Ingegerd,Ingela",
+      "Vendela,Vanda", "Teodor,Ted", "Martin,Martina", "Mårten",
+      "Konrad,Kurt", "Kristian,Krister", "Emil,Mildred", "Katja,Nadja",
+      "Edmund,Gudmund", "Naemi,Nancy", "Pierre,Percy",
+      "Elisabet,Lisbeth", "Pontus,Pia", "Helga,Olga", "Cecilia,Cornelia",
+      "Klemens,Clarence", "Gudrun,Runar", "Katarina,Carina",
+      "Linus,Love", "Astrid,Asta", "Malte,Malkolm", "Sune,Synnöve",
+      "Anders,Andreas", "Oskar,Ossian", "Beata,Beatrice", "Lydia,Carola",
+      "Barbro,Barbara", "Sven,Svante", "Nikolaus,Niklas",
+      "Angelika,Angela", "Virginia,Vera", "Anna,Annie", "Malin,Malena",
+      "Daniel,Dan", "Alexander,Alex", "Lucia", "Sten,Stig",
+      "Gottfrid,Gotthard", "Assar,Astor", "Inge,Ingemund",
+      "Abraham,Efraim", "Isak,Rebecka", "Israel,Moses", "Tomas,Tom",
+      "Natanael,Natalia", "Adam", "Eva", 0, "Stefan,Staffan",
+      "Johannes,Hannes", "Abel,Set", "Gunlög,Åslög", "Sylvester", 0});
+
+}
+
+class Hungary
+{
+   inherit Namedays;
+
+   mapping lookup=0;
+
+   void create()
+   {
+      name="Sweden";
+   }
+
+   static array(string) namedays_year(int y)
+   {
+      return hungarian_namedays;
+   }
+
+   static int nameday_lookup(int y,string s)
+   {
+      return (lookup||
+	      (lookup=make_lookup(hungarian_namedays)))
+	 [lower_case(s)];
+   }
+
+   constant hungarian_namedays=
+   ({
+      "Fruzsina",
+      "Ábel",
+      "Genovéna,Benjámin",
+      "Titusz,Leóna,Angéla",
+      "Simon,Amata",
+      "Boldizsár",
+      "Attila,Ramóna",
+      "Gyöngyvér",
+      "Marcell",
+      "Melánia",
+      "Ágota",
+      "Ernõ",
+      "Veronika",
+      "Bódog",
+      "Lóránt,Lóránd",
+      "Gusztáv",
+      "Antal,Antónia",
+      "Piroska",
+      "Sára,Márió",
+      "Fábián,Sebestyén",
+      "Ágnes",
+      "Vince,Artúr,Anasztáz",
+      "Zelma,Rajmund",
+      "Timót",
+      "Pál",
+      "Vanda,Paula",
+      "Angelika,Angéla",
+      "Károly,Karola",
+      "Adél",
+      "Martina,Gerda",
+      "Marcella",
+      "Ignác",
+      "Karolina,Aida",
+      "Balázs",
+      "Ráhel,Csenge,András",
+      "Ágota,Ingrid",
+      "Dorottya,Dóra,Ajándék,Amanda",
+      "Tódor,Rómeó",
+      "Aranka",
+      "Abigél,Alex",
+      "Elvira",
+      "Bertold,Marietta,Adolf",
+      "Lívia,Lídia",
+      "Ella,Linda",
+      "Bálint,Valentin",
+      "Kolos,Georgina",
+      "Julianna,Lilla",
+      "Donát",
+      "Bernadett",
+      "Zsuzsanna",
+      "Aladár,Álmos,Amata",
+      "Eleonóra",
+      "Gerzson",
+      "Alfréd",
+      "Mátyás",
+      "Géza",
+      "Edina",
+      "Ákos,Bátor",
+      "Elemér",
+      "Albin,Albina",
+      "Lujza",
+      "Kornélia",
+      "Kázmér,Adorján,Adrián,Adrienn",
+      "Adorján,Adrián,Adrienn",
+      "Leonora,Inez",
+      "Tamás",
+      "Zoltán",
+      "Franciska,Fanni",
+      "Ildikó",
+      "Szilárd,Aladár",
+      "Gergely",
+      "Krisztián,Ajtóny",
+      "Matild",
+      "Kristóf",
+      "Henrietta",
+      "Gertrúd,Patrik",
+      "Sándor,Ede,Alexandra",
+      "József,Bánk",
+      "Klaudia",
+      "Benedek",
+      "Beáta,Izolda",
+      "Emõke",
+      "Gábor,Karina",
+      "Irén,Írisz",
+      "Emánuel",
+      "Hajnalka",
+      "Gedeon,Johanna",
+      "Aguszta",
+      "Zalán,Amade",
+      "Árpád,Ajtóny",
+      "Hugó",
+      "Áron",
+      "Buda,Richárd",
+      "Izidor",
+      "Vince",
+      "Vilmos,Bíborka",
+      "Herman",
+      "Dénes",
+      "Erhard",
+      "Zsolt",
+      "Leó,Szaniszló",
+      "Gyula",
+      "Ida",
+      "Tibor",
+      "Anasztázia,Tas",
+      "Csongor",
+      "Rudolf",
+      "Andrea,Ilma,András",
+      "Emma",
+      "Tivadar",
+      "Konrád",
+      "Csilla,Noémi",
+      "Béla",
+      "György",
+      "Márk",
+      "Ervin",
+      "Zita",
+      "Valéria",
+      "Péter,Albert,Albertína",
+      "Katalin,Kitti",
+      "Fülöp,Jakab,Amarilla",
+      "Zsigmond",
+      "Tímea,Irma",
+      "Mónika,Flórián",
+      "Györgyi",
+      "Ivett,Frida",
+      "Gizella",
+      "Mihály",
+      "Gergely",
+      "Ármin,Pálma",
+      "Ferenc,Adolf",
+      "Pongrác",
+      "Szervác,Imola",
+      "Bonifác",
+      "Zsófia,Szonja",
+      "Mózes,Botond",
+      "Paszkál",
+      "Erik,Alexandra",
+      "Ivó,Milán",
+      "Bernát,Felícia",
+      "Konstantin,András",
+      "Júlia,Rita",
+      "Dezsõ",
+      "Eszter,Eliza",
+      "Orbán",
+      "Fülöp,Evelin,Amanda",
+      "Hella",
+      "Emil,Csanád,Ágoston",
+      "Magdolna",
+      "Janka,Zsanett",
+      "Angéla,Petronella",
+      "Tünde",
+      "Kármen,Anita,Anna,Annamária",
+      "Klotild",
+      "Bulcsú",
+      "Fatime",
+      "Norbert,Cintia",
+      "Róbert",
+      "Medárd",
+      "Félix,Annabella",
+      "Margit,Gréta",
+      "Barnabás",
+      "Villó",
+      "Antal,Anett,Anna",
+      "Vazul",
+      "Jolán,Vid",
+      "Jusztin",
+      "Laura,Alida,Adolf,Alina,Alinda",
+      "Arnold,Levente",
+      "Gyárfás",
+      "Rafael",
+      "Alajos,Leila,Aladár,Aloma",
+      "Paulina",
+      "Zoltán",
+      "Iván",
+      "Vilmos",
+      "János,Pál",
+      "Lászlo",
+      "Levente,Irén",
+      "Péter,Pál",
+      "Pál",
+      "Tihamér,Annamária",
+      "Ottó",
+      "Kornél,Soma,Anatol",
+      "Ulrik",
+      "Emese,Sarolta,Antal",
+      "Csaba",
+      "Apollonia",
+      "Ellák",
+      "Lukrécia",
+      "Amália,Alma",
+      "Nóra,Lili",
+      "Izabella,Dalma",
+      "Jenõ",
+      "Örs,Stella",
+      "Henrik,Roland",
+      "Valter",
+      "Endre,Elek,Ajándék,András",
+      "Frigyes",
+      "Emília",
+      "Íllás",
+      "Dániel,Daniella",
+      "Magdolna",
+      "Lenke",
+      "Kinga,Kincsó",
+      "Kristóf,Jakab",
+      "Anna,Anikó,Annamária",
+      "Olga,Liliana,Ajtóny",
+      "Szabolcs",
+      "Márta,Flóra",
+      "Judit,Xénia",
+      "Oszkár",
+      "Boglárka",
+      "Lehel,Alfonz",
+      "Hermina",
+      "Domonkos,Dominika",
+      "Krisztina,Afrodité",
+      "Berta,Bettína",
+      "Ibolya,Afrodité",
+      "László",
+      "Emõd",
+      "Lõrinc",
+      "Zsuzsanna,Tiborc",
+      "Klára",
+      "Ipoly",
+      "Marcell",
+      "Mária",
+      "Ábrahám",
+      "Jácint,Anasztáz",
+      "Ilona",
+      "Huba",
+      "István",
+      "Sámuel,Hajna",
+      "Menyhért,Mirjam",
+      "Bence",
+      "Bertalan",
+      "Lajos,Patrícia",
+      "Izsó",
+      "Gáspár",
+      "Ágoston",
+      "Beatrix,Erna",
+      "Rózsa",
+      "Erika,Bella",
+      "Egyed,Egon",
+      "Rebeka,Dorina",
+      "Hilda",
+      "Rozália",
+      "Viktor,Lõrinc,Alpár",
+      "Zakariás",
+      "Regina",
+      "Mária,Adrienn,Adorján,Adrián",
+      "Ádám,András",
+      "Nikolett,Hunor",
+      "Teodóra",
+      "Mária",
+      "Kornél,Amata",
+      "Szeréna,Roxána",
+      "Enikõ,Melitta",
+      "Edit",
+      "Zsófia",
+      "Diána",
+      "Vilhelmina",
+      "Friderika",
+      "Máté,Mirella",
+      "Móric",
+      "Tekla",
+      "Gellért,Mercédesz",
+      "Eufrózina,Kende",
+      "Jusztina",
+      "Adalbert,Adolf,Albertina",
+      "Vencel",
+      "Mihály",
+      "Jeromos",
+      "Malvin",
+      "Petra",
+      "Helga",
+      "Ferenc",
+      "Aurél",
+      "Brúnó,Renáta",
+      "Amália",
+      "Koppány",
+      "Dénes",
+      "Gedeon",
+      "Brigitta",
+      "Miksa",
+      "Kálmán,Ede",
+      "Helén",
+      "Teréz",
+      "Gál",
+      "Hedvig",
+      "Lukács",
+      "Nándor",
+      "Vendel",
+      "Orsolya",
+      "Elõd",
+      "Gyöngyi",
+      "Salamon",
+      "Blanka,Bianka",
+      "Dömötör",
+      "Szabina",
+      "Simon,Szimonetta",
+      "Nárcisz",
+      "Alfonz",
+      "Farkas",
+      "Marianna",
+      "Achilles",
+      "Gyõzõ",
+      "Károly",
+      "Imre",
+      "Lénárd",
+      "Rezsõ",
+      "Zsombor",
+      "Tivadar",
+      "Réka,András",
+      "Márton",
+      "Jónás,Renátó,Aba",
+      "Szilvia",
+      "Alíz",
+      "Albert,Lipót",
+      "Ödön",
+      "Hortenzia,Gergõ",
+      "Jenõ",
+      "Erzsébet",
+      "Jolán",
+      "Olivér",
+      "Cecília",
+      "Kelemen,Klementína",
+      "Emma",
+      "Katalin,Alan",
+      "Virág",
+      "Virgil",
+      "Stefánia",
+      "Taksony",
+      "András,Andor",
+      "Elza",
+      "Melinda,Vivien",
+      "Ferenc",
+      "Borbála,Barbara",
+      "Vilma",
+      "Miklós",
+      "Ambrus",
+      "Mária",
+      "Natália",
+      "Judit",
+      "Árpád",
+      "Gabriella",
+      "Luca,Otília",
+      "Szilárda",
+      "Valér",
+      "Etelka,Aletta,Albina",
+      "Lázár,Olimpia",
+      "Auguszta",
+      "Viola",
+      "Teofil",
+      "Tamás",
+      "Zénó",
+      "Viktória",
+      "Ádám,Éva,Ada,Adél",
+      "Eugénia",
+      "István",
+      "János",
+      "Kamilla",
+      "Tamás,Tamara",
+      "Dávid",
+      "Szilveszter",
+      0,
+   });
+}
diff --git a/lib/modules/Calendar.pmod/Roman.pmod b/lib/modules/Calendar.pmod/Roman.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..a0c5121b48c16bf1ee48fbe3ac43523a662ccdcd
--- /dev/null
+++ b/lib/modules/Calendar.pmod/Roman.pmod
@@ -0,0 +1,20 @@
+//!
+//! module Calendar
+//! submodule Roman
+//!
+//! base for all Roman-kind of calendars
+//! ie, one with years, months, weeks and days
+//!
+
+#pragma strict_types
+
+import ".";
+inherit Time:Time;
+
+class cMinute
+{
+   inherit Time::cMinute;
+   void bip() { werror("roman\n"); }
+   int roman(int x,int y) { return 17; }
+}
+
diff --git a/lib/modules/Calendar.pmod/Ruleset.pike b/lib/modules/Calendar.pmod/Ruleset.pike
new file mode 100644
index 0000000000000000000000000000000000000000..8b81169cfca201e04e2d955646d3c0832fb70627
--- /dev/null
+++ b/lib/modules/Calendar.pmod/Ruleset.pike
@@ -0,0 +1,109 @@
+class Timezone
+{
+   constant is_timezone=1;
+
+// seconds to utc, not counting DST
+   static int offset_to_utc;  
+   
+// timezone name
+   string name;
+
+   static void create(int offset,string _name) 
+   { 
+      offset_to_utc=offset; 
+      name=_name;
+   }
+
+   // seconds to UTC, counting DST
+
+   array(int) tz_ux(int unixtime)
+   {
+      return ({offset_to_utc,name}); 
+   }
+
+   array(int) tz_jd(int julian_day)
+   {
+      return ({offset_to_utc,name}); 
+   }
+
+   string _sprintf(int t) { return (t=='O')?"Timezone("+name+")":0; }
+
+   int raw_utc_offset() { return offset_to_utc; }
+};
+
+Timezone timezone;
+
+class Language
+{
+   constant is_language=1;
+   
+   string month_name_from_number(int n);
+   string month_shortname_from_number(int n);
+   int month_number_from_name(string name);
+
+   string week_day_name_from_number(int n);
+   string week_day_shortname_from_number(int n);
+   int week_day_number_from_name(string name);
+
+   string gregoiran_week_day_name_from_number(int n);
+   string gregorian_week_day_shortname_from_number(int n);
+   int gregorian_week_day_number_from_name(string name);
+
+   string week_name_from_number(int n);
+   int week_number_from_name(string s);
+   string year_name_from_number(int y);
+}
+
+Language language;
+
+this_program set_timezone(string|Timezone t)
+{
+   this_program r=clone();
+   if (stringp(t))
+   {
+      t=master()->resolv("Calendar")["Timezone"][t];
+      if (!t) error("no timezone %O\n",t);
+   }
+
+   if (!t->is_timezone)
+      error("Not a timezone: %O\n",t);
+   r->timezone=t;
+   return r;
+}
+
+this_program set_language(string|Language lang)
+{
+   this_program r=clone();
+   if (stringp(lang))
+   {
+      lang=master()->resolv("Calendar")["Language"][lang];
+      if (!lang) lang=master()->resolv("Calendar")["Language"]["ISO"];
+   }
+   if (!lang->is_language)
+      error("Not a language: %O\n",lang);
+   r->language=lang;
+   return r;
+}
+
+this_program set_rule(Language|Timezone rule)
+{
+   this_program r=clone();
+   if (rule->is_timezone) r->timezone=rule;
+   if (rule->is_language) r->language=rule;
+   return r;
+}
+
+this_program clone()
+{
+   this_program r=object_program(this_object())();   
+   r->timezone=timezone;
+   r->language=language;
+   return r;
+}
+
+int(0..1) `==(this_program other)
+{
+   return 
+      other->timezone==timezone &&
+      other->language==language;
+}
diff --git a/lib/modules/Calendar.pmod/Stardate.pmod b/lib/modules/Calendar.pmod/Stardate.pmod
index a91e964fca62279d71949e5522cb65a7fa45aa73..d81099120599e7354bbef06cc11204f2e0629662 100644
--- a/lib/modules/Calendar.pmod/Stardate.pmod
+++ b/lib/modules/Calendar.pmod/Stardate.pmod
@@ -1,106 +1,305 @@
+//! module Calendar
 //! submodule Stardate
-//!	time unit: TNGDate
+//!	This implements TNG stardates. 
 
-//! class TNGDate
-//!	implements ST:TNG stardates
-//!	can be used as create argument to Day 
+import ".";
 
-class TNGDate
-{
-   inherit Calendar._TimeUnit;
+inherit TimeRanges;
+
+static constant TNGSTARPERJULIAN=1000.0/365.2425;
+static constant TNGSTARPERSECOND=TNGSTARPERJULIAN/86400;
+static constant TNG0JULIAN=2569518.5;
+static constant TNG0UNIX=11139552000;
+
+string calendar_name() { return "Stardate"; }
 
-   // 40759.5  2363-10-05  2584405
-   // 47391.2  2370-05-23  2586827
+function(mixed...:cTick) Tick=cTick;
+class cTick
+{
+   inherit TimeRange;
 
-   // 50893.5  2373-11-23  2588107
+   constant is_stardate=1;
 
-   //  6631.7  ----------  2422 
-   // 10134.0  ----------  3702
-   //  1000.0  ----------  365.2425
-   //     0.0      -  -    2569519
-#define TNGSTARPERJULIAN (1000.0/365.2425)
+   float tick;
+   float len;
 
-//-- variables ------------------------------------------------------
+//! method void create(mixed ...)
+//! method void create(int|float date)
+//! method void create()
+//!	Apart from the standard creation methods
+//!	(julian day, etc), you can create a stardate
+//!	from the stardate number. The length
+//!	of the period will then be zero.
+//!
+//!	You can also omit any arguments to create now.
+//!
+//! known bugs:
+//!	Since the precision is limited to the float type
+//!	of pike you can get non-precise results:
+//!
+//!     <pre>
+//!	> Calendar.Second(Calendar.Stardate.Day(Calendar.Year()));
+//!	Result: Second(Fri 31 Dec 1999 23:59:18 CET - Sun 31 Dec 2000 23:59:18 CET)
+//!	</pre>
 
-   float jd;
-   float tics;
-   
-//-- standard methods -----------------------------------------------
 
-   void create(int|float|object ... day)
+   void create(mixed ...args)
    {
-      float jd;
-      if (!sizeof(day))
-	 day=({Calendar.Gregorian.Second()});
-      else if (floatp(day[0]))
-      {
-	 from_stardate(day[0]);
-	 return;
-      }
-      if (!intp(day[0]))
+      switch (sizeof(args))
       {
-	 object o=day[0];
-
-	 if (o->julian_day || o->julian_day_f)
-	    jd=(float)(o->julian_day_f||o->julian_day)();
-	 else // dig
-	    if (o->day) // larger
+	 case 4:
+      // internal
+	    if (args[0]=="stardate")
 	    {
-	       o=o->day(0);
-	       if (o->julian_day_f)
-		  jd=o->julian_day_f();
-	       else if (o->julian_day)
-		  jd=(float)o->julian_day();
-	       else
-		  ; // error, like
+	       rules=args[1];
+	       tick=args[2];
+	       len=args[3];
+	       return;
 	    }
-	    else // smaller
+	    break;
+	 case 1:
+	    if (intp(args[0]) || floatp(args[0]))
 	    {
-	       float z=1.0;
-	       while (sizeof(o->greater()))
-	       {
-		  string name=o->is();
-		  o=o[o->greater()[0]]();
-		  z*=o["number_of_"+name+"s"]();
-		  if (o->julian_day_f || o->julian_day) 
-		  {
-		     jd=(o->julian_day||o->julian_day_f)()/z;
-		     break;
-		  }
-	       }
+	       rules=default_rules;
+	       tick=(float)args[0];
+	       len=0.0;
+	       return;
 	    }
+	    break;
+	 case 0:
+	    rules=default_rules;
+	    create_unixtime_default(time());
+	    return;
       }
+      rules=default_rules;
+      ::create(@args);
+   }
+
+   static void create_unixtime(int unixtime,int seconds)
+   {
+      tick=(unixtime-TNG0UNIX)*TNGSTARPERSECOND;
+      len=seconds*TNGSTARPERSECOND;
+   }
+
+   static void create_unixtime_default(int unixtime)
+   {
+      tick=(unixtime-TNG0UNIX)*TNGSTARPERSECOND;
+      len=0.0;
+   }
+
+   static void create_julian_day(int|float jd)
+   {
+      tick=(jd-TNG0JULIAN)*TNGSTARPERJULIAN;
+      len=0.0;
+   }
+
+//! method float tics()
+//!	This gives back the number of stardate tics
+//!	in the period.
+
+   float tics()
+   {
+      return len;
+   }
+
+//! method int number_of_seconds()
+//! method int number_of_days()
+//!	This gives back the Gregorian/Earth/ISO number of seconds
+//!	and number of days, for convinience and conversion to
+//!	other calendars.
+
+   int number_of_seconds()
+   {
+      return (int)(len/TNGSTARPERSECOND);
+   }
+
+   int number_of_days()
+   {
+      return (int)(len/TNGSTARPERJULIAN);
+   }
+
+   int unix_time()
+   {
+      return ((int)(tick/TNGSTARPERSECOND))+TNG0UNIX;
+   }
+
+   float julian_day()
+   {
+      return ((int)(tick/TNGSTARPERJULIAN))+TNG0JULIAN;
+   }
+
+   TimeRange add(int n,void|this_program step)
+   {
+      float x;
+      if (!step) 
+	 x=len;
       else 
-	 jd=(float)day[0];
-      from_julian_day(jd);
+      {
+	 if (!step->is_stardate)
+	    error("add: Incompatible type %O\n",step);
+	 x=step->len;
+      }
+
+
+      if (n&&x)
+	 return Tick("stardate",rules,tick+x,len);
+      return this_object();
    }
 
-   static void from_stardate(float f)
+   static void convert_from(TimeRange other)
    {
-      tics=f;
-      jd=f/TNGSTARPERJULIAN+2569518.5;
+      if (other->unix_time)
+	 create_unixtime_default(other->unix_time());
+      else
+	 ::convert_from(other);
+      if (other->is_stardate)
+      {
+	 tick=other->tick;
+	 len=other->len;
+      }
+      else if (other->number_of_seconds)
+	 len=TNGSTARPERSECOND*other->number_of_seconds();
+      else if (other->number_of_days)
+	 len=TNGSTARPERJULIAN*other->number_of_days();
+      else
+	 len=0.0;
    }
 
-   static void from_julian_day(float f)
+   static TimeRange _set_size(int n,TimeRange x)
    {
-      jd=f;
-      tics=(f-2569518.5)*TNGSTARPERJULIAN;
+      if (!x->is_stardate)
+	 error("distance: Incompatible type %O\n",x);
+      return Tick("stardate",rules,tick,x->len);
    }
 
-//-- nonstandard methods --------------------------------------------
+   TimeRange place(TimeRange what,void|int force)
+   {
+// can't do this
+      return this_object();
+   }
 
-   float number()
+   array(TimeRange) split(int n)
    {
-      return tics;
+      if (!n) return ({this_object()}); // foo
+
+      float z=tick;
+      float l=len/n;
+      array(TimeRange) res=({});
+
+      while (n--)
+	 res+=({Tick("stardate",rules,z,l)}),z+=l;
+
+      return res;
+   }
+
+   TimeRange beginning()
+   {
+      if (!len) return this_object();
+      return Tick("stardate",rules,tick,0.0);
+   }
+
+   TimeRange end()
+   {
+      if (!len) return this_object();
+      return Tick("stardate",rules,tick+len,0.0);
+   }
+
+   TimeRange distance(TimeRange to)
+   {
+      if (!to->is_stardate)
+	 error("distance: Incompatible type %O\n",to);
+      if (to->tick<tick)
+	 error("negative distance\n");
+      return Tick("stardate",rules,tick,to->tick-tick);
    }
-   
-   int julian_day()
+
+   array _compare(TimeRange with)
    {
-      return (int)jd;
+      float b1=tick;
+      float e1=tick+len;
+      float b2,e2;
+      if (with->is_stardate)
+	 b2=with->tick,e2=b2+with->len;
+      else 
+	 ::_compare(with);
+#define CMP(A,B) ( ((A)<(B))?-1:((A)>(B))?1:0 )
+      return ({ CMP(b1,b2),CMP(b1,e2),CMP(e1,b2),CMP(e1,e2) });
    }
 
-   float julian_day_f()
+   int __hash() { return (int)tick; }
+
+   cTick set_ruleset(Ruleset r)
    {
-      return jd;
+      return Tick("stardate",r,tick,len);
    }
+
+   string _sprintf(int t)
+   {
+      switch (t)
+      {
+	 case 'O':
+	    if (len!=0.0) 
+	       return sprintf("Tick(%s)",nice_print_period());
+	    return sprintf("Tick(%s)",nice_print());
+	 default:
+	    return 0;
+      }
+   }
+
+   string nice_print_period()
+   {
+      if (len>0.010)
+	 return sprintf("%s..%s",nice_print(),end()->nice_print());
+      else
+	 return sprintf("%s..%+g",nice_print(),len);
+   }
+
+   string nice_print()
+   {
+      return sprintf("%.3f",tick);
+   }
+
+//! string format_long()
+//! string format_short()
+//! string format_vshort()
+//!	Format the stardate tick nicely.
+//!	<pre>
+//!	   long    "-322537.312"
+//!	   short   "77463.312"  (w/o >100000-component)
+//!	   short   "7463.312"  (w/o >10000-component)
+//!	</pre>
+
+   string format_long()
+   {
+      return sprintf("%.3f",tick);
+   }
+
+   string format_short()
+   {
+      return sprintf("%.3f",tick-((int)tick/100000)*100000);
+   }
+
+   string format_vshort()
+   {
+      return sprintf("%.3f",tick-((int)tick/10000)*10000);
+   }
+}
+
+// compat
+function(mixed...:cTick) TNGDate=cTick;
+
+// for events
+function(mixed...:cTick) Day=cTick;
+
+//------------------------------------------------------------------------
+//  global convinience functions
+//------------------------------------------------------------------------
+
+//! method TimeofDay now()
+//!	Give the zero-length time period of the
+//!	current time.
+
+TimeofDay now()
+{
+   return Tick();
 }
diff --git a/lib/modules/Calendar.pmod/Swedish.pmod b/lib/modules/Calendar.pmod/Swedish.pmod
index 861bd0a7f8fb3c7690cf34fc7407f1c5452d66c2..39a9dd88a553eb1d7b78800c2907fce9f533aba7 100644
--- a/lib/modules/Calendar.pmod/Swedish.pmod
+++ b/lib/modules/Calendar.pmod/Swedish.pmod
@@ -1,238 +1,19 @@
-// by Mirar 
-
-inherit Calendar.ISO:ISO;
-
-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 ISO::Week;
-
-   string name()
-   {
-      return "v"+(string)this->number();
-   }
-}
-
-class Year
-{
-   inherit ISO::Year;
-
-   array(array(string)) _namedays;
-   mapping(string:int) _nameday_lookup;
-
-   string name()
-   {
-      if (this->number()<=0) 
-	 return (string)(1-this->number())+" fk";
-      return (string)this->number();
-   }
-
-   array(array(string)) namedays()
-   {
-      if (_namedays) return _namedays;
-
-      array(array(string)) a;
-
-      // insert test for year here
-      if (!(a=namedays_cache[this->leap()+" "+this->leap_day()]))
-      {
-      // insert test for year here
-	 a=namedays_1993;
-
-	 if (this->leap())
-	 {
-	    a=a[..this->leap_day()-1]+
-	       Array.map(allocate(this->leap()),
-			 lambda(int x) { return ({}); })+
-	       a[this->leap_day()..];
-	 }
-
-	 namedays_cache[this->leap()+" "+this->leap_day()]=a;
-      }
-
-      return _namedays=a;
-   }
-
-   object nameday(string name)
-   {
-      if (!_nameday_lookup
-	 && !(_nameday_lookup=
-	      namedays_lookup_cache[this->leap()+" "+this->leap_day()]))
-      {
-	 mapping m=([]);
-	 int i;
-	 foreach (this->namedays(),array a)
-	 {
-	    foreach (a,string name) m[lower_case(name)]=i;
-	    i++;
-	 }
-	 _nameday_lookup =
-	    namedays_lookup_cache[this->leap()+" "+this->leap_day()] = m;
-      }
-      
-      if (zero_type(_nameday_lookup[lower_case(name)])) return 0;
-      return this->day(_nameday_lookup[lower_case(name)]);
-   }
-}
-
-class Day
+//!
+//! module Calendar
+//! submodule Swedish
+//!
+//!	Same as the ISO calendar,
+//!	but with swedish namedays added, and
+//!	swedish is the default language.
+//!
+//!	This calendar exist only for backwards compatible 
+//!	purposes. 
+//!
+
+import ".";
+inherit ISO:ISO;
+
+private static mixed __initstuff=lambda()
 {
-   inherit ISO::Day;
-
-   array(string) names()
-   {
-      return this->year()->namedays()[this->year_day()];
-   }
-}
-
-// --- namnsdagar, data -------------------------------------------------
-
-mapping namedays_cache=([]);
-mapping namedays_lookup_cache=([]);
-
-/**
-
-Name database from alma-1.0, 
-http://www.lysator.liu.se/~tab/alma-1.0.tar.gz
-
-Permission to use from Kent Engström, 1998-01-28
-
- **/
-
-
-array(array(string)) namedays_1993= 
-({ ({}), ({"Svea","Sverker"}), ({"Alfred","Alfrida"}),
-   ({"Rut","Ritva"}), ({"Hanna","Hannele"}), ({"Baltsar","Kasper"}),
-   ({"August","Augusta"}), ({"Erland","Erhard"}), ({"Gunnar","Gunder"}),
-   ({"Sigurd","Sigmund"}), ({"Hugo","Hagar"}), ({"Frideborg","Fridolf"}),
-   ({"Knut"}), ({"Felix","Felicia"}), ({"Laura","Liv"}),
-   ({"Hjalmar","Hervor"}), ({"Anton","Tony"}), ({"Hilda","Hildur"}),
-   ({"Henrik","Henry"}), ({"Fabian","Sebastian"}), ({"Agnes","Agneta"}),
-   ({"Vincent","Veine"}), ({"Emilia","Emilie"}), ({"Erika","Eira"}),
-   ({"Paul","Pål"}), ({"Bodil","Boel"}), ({"Göte","Göta"}),
-   ({"Karl","Karla"}), ({"Valter","Vilma"}), ({"Gunhild","Gunilla"}),
-   ({"Ivar","Joar"}), ({"Max","Magda"}), ({"Marja","Mia"}),
-   ({"Disa","Hjördis"}), ({"Ansgar","Anselm"}), ({"Lisa","Elise"}),
-   ({"Dorotea","Dora"}), ({"Rikard","Dick"}), ({"Berta","Berthold"}),
-   ({"Fanny","Betty"}), ({"Egon","Egil"}), ({"Yngve","Ingolf"}),
-   ({"Evelina","Evy"}), ({"Agne","Agnar"}), ({"Valentin","Tina"}),
-   ({"Sigfrid","Sigbritt"}), ({"Julia","Jill"}),
-   ({"Alexandra","Sandra"}), ({"Frida","Fritz"}), ({"Gabriella","Ella"}),
-   ({"Rasmus","Ruben"}), ({"Hilding","Hulda"}), ({"Marina","Marlene"}),
-   ({"Torsten","Torun"}), ({"Mattias","Mats"}), ({"Sigvard","Sivert"}),
-   ({"Torgny","Torkel"}), ({"Lage","Laila"}), ({"Maria","Maja"}),
-   ({"Albin","Inez"}), ({"Ernst","Erna"}), ({"Gunborg","Gunvor"}),
-   ({"Adrian","Ada"}), ({"Tora","Tor"}), ({"Ebba","Ebbe"}),
-   ({"Isidor","Doris"}), ({"Siv","Saga"}), ({"Torbjörn","Ambjörn"}),
-   ({"Edla","Ethel"}), ({"Edvin","Elon"}), ({"Viktoria","Viktor"}),
-   ({"Greger","Iris"}), ({"Matilda","Maud"}), ({"Kristofer","Christel"}),
-   ({"Herbert","Gilbert"}), ({"Gertrud","Görel"}), ({"Edvard","Eddie"}),
-   ({"Josef","Josefina"}), ({"Joakim","Kim"}), ({"Bengt","Benny"}),
-   ({"Viking","Vilgot"}), ({"Gerda","Gert"}), ({"Gabriel","Rafael"}),
-   ({"Mary","Marion"}), ({"Emanuel","Manne"}), ({"Ralf","Raymond"}),
-   ({"Elma","Elmer"}), ({"Jonas","Jens"}), ({"Holger","Reidar"}),
-   ({"Ester","Estrid"}), ({"Harald","Halvar"}), ({"Gunnel","Gun"}),
-   ({"Ferdinand","Florence"}), ({"Irene","Irja"}), ({"Nanna","Nanny"}),
-   ({"Vilhelm","Willy"}), ({"Irma","Mimmi"}), ({"Vanja","Ronja"}),
-   ({"Otto","Ottilia"}), ({"Ingvar","Ingvor"}), ({"Ulf","Ylva"}),
-   ({"Julius","Gillis"}), ({"Artur","Douglas"}), ({"Tiburtius","Tim"}),
-   ({"Olivia","Oliver"}), ({"Patrik","Patricia"}), ({"Elias","Elis"}),
-   ({"Valdemar","Volmar"}), ({"Olaus","Ola"}), ({"Amalia","Amelie"}),
-   ({"Annika","Anneli"}), ({"Allan","Alida"}), ({"Georg","Göran"}),
-   ({"Vega","Viveka"}), ({"Markus","Mark"}), ({"Teresia","Terese"}),
-   ({"Engelbrekt","Enok"}), ({"Ture Tyko"}), ({"Kennet","Kent"}),
-   ({"Mariana","Marianne"}), ({"Valborg","Maj"}), ({"Filip","Filippa"}),
-   ({"John","Jack"}), ({"Monika","Mona"}), ({"Vivianne","Vivan"}),
-   ({"Marit","Rita"}), ({"Lilian","Lilly"}), ({"Åke","Ove"}),
-   ({"Jonatan","Gideon"}), ({"Elvira","Elvy"}), ({"Märta","Märit"}),
-   ({"Charlotta","Lotta"}), ({"Linnea","Nina"}), ({"Lillemor","Lill"}),
-   ({"Sofia","Sonja"}), ({"Hilma","Hilmer"}), ({"Nore","Nora"}),
-   ({"Erik","Jerker"}), ({"Majken","Majvor"}), ({"Karolina","Lina"}),
-   ({"Konstantin","Conny"}), ({"Henning","Hemming"}),
-   ({"Desiree","Renee"}), ({"Ivan","Yvonne"}), ({"Urban","Ursula"}),
-   ({"Vilhelmina","Helmy"}), ({"Blenda","Beda"}),
-   ({"Ingeborg","Borghild"}), ({"Jean","Jeanette"}),
-   ({"Fritiof","Frej"}), ({"Isabella","Isa"}), ({"Rune","Runa"}),
-   ({"Rutger","Roger"}), ({"Ingemar","Gudmar"}),
-   ({"Solveig","Solbritt"}), ({"Bo","Boris"}), ({"Gustav","Gösta"}),
-   ({"Robert","Robin"}), ({"Eivor","Elaine"}), ({"Petra","Petronella"}),
-   ({"Kerstin","Karsten"}), ({"Bertil","Berit"}), ({"Eskil","Esbjörn"}),
-   ({"Aina","Eila"}), ({"Håkan","Heidi"}), ({"Margit","Mait"}),
-   ({"Axel","Axelina"}), ({"Torborg","Torvald"}), ({"Björn","Bjarne"}),
-   ({"Germund","Jerry"}), ({"Linda","Linn"}), ({"Alf","Alva"}),
-   ({"Paulina","Paula"}), ({"Adolf","Adela"}), ({"Johan","Jan"}),
-   ({"David","Salomon"}), ({"Gunni","Jim"}), ({"Selma","Herta"}),
-   ({"Leo","Leopold"}), ({"Petrus","Peter"}), ({"Elof","Leif"}),
-   ({"Aron","Mirjam"}), ({"Rosa","Rosita"}), ({"Aurora","Adina"}),
-   ({"Ulrika","Ulla"}), ({"Melker","Agaton"}), ({"Ronald","Ronny"}),
-   ({"Klas","Kaj"}), ({"Kjell","Tjelvar"}), ({"Jörgen","Örjan"}),
-   ({"Anund","Gunda"}), ({"Eleonora","Ellinor"}), ({"Herman","Hermine"}),
-   ({"Joel","Judit"}), ({"Folke","Odd"}), ({"Ragnhild","Ragnvald"}),
-   ({"Reinhold","Reine"}), ({"Alexis","Alice"}), ({"Fredrik","Fred"}),
-   ({"Sara","Sally"}), ({"Margareta","Greta"}), ({"Johanna","Jane"}),
-   ({"Magdalena","Madeleine"}), ({"Emma","Emmy"}),
-   ({"Kristina","Stina"}), ({"Jakob","James"}), ({"Jesper","Jessika"}),
-   ({"Marta","Moa"}), ({"Botvid","Seved"}), ({"Olof","Olle"}),
-   ({"Algot","Margot"}), ({"Elin","Elna"}), ({"Per","Pernilla"}),
-   ({"Karin","Kajsa"}), ({"Tage","Tanja"}), ({"Arne","Arnold"}),
-   ({"Ulrik","Alrik"}), ({"Sixten","Sölve"}), ({"Dennis","Donald"}),
-   ({"Silvia","Sylvia"}), ({"Roland","Roine"}), ({"Lars","Lorentz"}),
-   ({"Susanna","Sanna"}), ({"Klara","Clary"}), ({"Hillevi","Gullvi"}),
-   ({"William","Bill"}), ({"Stella","Stellan"}), ({"Brynolf","Sigyn"}),
-   ({"Verner","Veronika"}), ({"Helena","Lena"}), ({"Magnus","Måns"}),
-   ({"Bernhard","Bernt"}), ({"Jon","Jonna"}), ({"Henrietta","Henny"}),
-   ({"Signe","Signhild"}), ({"Bartolomeus","Bert"}),
-   ({"Lovisa","Louise"}), ({"Östen","Ejvind"}), ({"Rolf","Rudolf"}),
-   ({"Gurli","Gull"}), ({"Hans","Hampus"}), ({"Albert","Albertina"}),
-   ({"Arvid","Vidar"}), ({"Samuel","Sam"}), ({"Justus","Justina"}),
-   ({"Alfhild","Alfons"}), ({"Gisela","Glenn"}), ({"Harry","Harriet"}),
-   ({"Sakarias","Esaias"}), ({"Regina","Roy"}), ({"Alma","Ally"}),
-   ({"Anita","Anja"}), ({"Tord","Tove"}), ({"Dagny","Daniela"}),
-   ({"Tyra","Åsa"}), ({"Sture","Styrbjörn"}), ({"Ida","Ellida"}),
-   ({"Sigrid","Siri"}), ({"Dag","Daga"}), ({"Hildegard","Magnhild"}),
-   ({"Alvar","Orvar"}), ({"Fredrika","Carita"}), ({"Agda","Agata"}),
-   ({"Ellen","Elly"}), ({"Maurits","Morgan"}), ({"Tekla","Tea"}),
-   ({"Gerhard","Gert"}), ({"Kåre","Tryggve"}), ({"Einar","Enar"}),
-   ({"Dagmar","Rigmor"}), ({"Lennart","Leonard"}),
-   ({"Mikael","Mikaela"}), ({"Helge","Helny"}), ({"Ragnar","Ragna"}),
-   ({"Ludvig","Louis"}), ({"Evald","Osvald"}), ({"Frans","Frank"}),
-   ({"Bror","Bruno"}), ({"Jenny","Jennifer"}), ({"Birgitta","Britta"}),
-   ({"Nils","Nelly"}), ({"Ingrid","Inger"}), ({"Helmer","Hadar"}),
-   ({"Erling","Jarl"}), ({"Valfrid","Ernfrid"}), ({"Birgit","Britt"}),
-   ({"Manfred","Helfrid"}), ({"Hedvig","Hedda"}), ({"Fingal","Finn"}),
-   ({"Antonia","Annette"}), ({"Lukas","Matteus"}), ({"Tore","Torleif"}),
-   ({"Sibylla","Camilla"}), ({"Birger","Börje"}), ({"Marika","Marita"}),
-   ({"Sören","Severin"}), ({"Evert","Eilert"}), ({"Inga","Ingvald"}),
-   ({"Amanda","My"}), ({"Sabina","Ina"}), ({"Simon","Simone"}),
-   ({"Viola","Vivi"}), ({"Elsa","Elsie"}), ({"Edit","Edgar"}),
-   ({"Andre","Andrea"}), ({"Tobias","Toini"}), ({"Hubert","Diana"}),
-   ({"Uno","Unn"}), ({"Eugen","Eugenia"}), ({"Gustav Adolf"}),
-   ({"Ingegerd","Ingela"}), ({"Vendela","Vanda"}), ({"Teodor","Ted"}),
-   ({"Martin","Martina"}), ({"Mårten"}), ({"Konrad","Kurt"}),
-   ({"Kristian","Krister"}), ({"Emil","Mildred"}), ({"Katja","Nadja"}),
-   ({"Edmund","Gudmund"}), ({"Naemi","Nancy"}), ({"Pierre","Percy"}),
-   ({"Elisabet","Lisbeth"}), ({"Pontus","Pia"}), ({"Helga","Olga"}),
-   ({"Cecilia","Cornelia"}), ({"Klemens","Clarence"}),
-   ({"Gudrun","Runar"}), ({"Katarina","Carina"}), ({"Linus","Love"}),
-   ({"Astrid","Asta"}), ({"Malte","Malkolm"}), ({"Sune","Synnöve"}),
-   ({"Anders","Andreas"}), ({"Oskar","Ossian"}), ({"Beata","Beatrice"}),
-   ({"Lydia","Carola"}), ({"Barbro","Barbara"}), ({"Sven","Svante"}),
-   ({"Nikolaus","Niklas"}), ({"Angelika","Angela"}),
-   ({"Virginia","Vera"}), ({"Anna","Annie"}), ({"Malin","Malena"}),
-   ({"Daniel","Dan"}), ({"Alexander","Alex"}), ({"Lucia"}),
-   ({"Sten","Stig"}), ({"Gottfrid","Gotthard"}), ({"Assar","Astor"}),
-   ({"Inge","Ingemund"}), ({"Abraham","Efraim"}), ({"Isak","Rebecka"}),
-   ({"Israel","Moses"}), ({"Tomas","Tom"}), ({"Natanael","Natalia"}),
-   ({"Adam"}), ({"Eva"}), ({}), ({"Stefan","Staffan"}),
-   ({"Johannes","Hannes"}), ({"Abel","Set"}), ({"Gunlög","Åslög"}),
-   ({"Sylvester"}), });
+   default_rules=default_rules->set_language("SE_sv");
+}();
diff --git a/lib/modules/Calendar.pmod/TZnames.pmod b/lib/modules/Calendar.pmod/TZnames.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..0e36c57f70236f9eaf1afd8a330cf7c3ffa8ab7e
--- /dev/null
+++ b/lib/modules/Calendar.pmod/TZnames.pmod
@@ -0,0 +1,86 @@
+// ----------------------------------------------------------------
+// Timezone names
+//
+// NOTE: this file is generated by mkrules.pike;
+//       please do not edit manually /Mirar
+// ----------------------------------------------------------------
+
+mapping _module_value=
+([
+   "America":   ({"Scoresbysund","Godthab","Thule","New_York","Chicago",    
+                  "Denver","Los_Angeles","Juneau","Yakutat","Anchorage",    
+                  "Nome","Adak","Phoenix","Boise","Indianapolis",           
+                  "Indiana/Marengo","Indiana/Knox","Indiana/Vevay",           
+                  "Louisville","Detroit","Menominee","St_Johns","Goose_Bay",
+                  "Halifax","Glace_Bay","Montreal","Thunder_Bay","Nipigon", 
+                  "Rainy_River","Winnipeg","Regina","Swift_Current",         
+                  "Edmonton","Vancouver","Dawson_Creek","Pangnirtung",       
+                  "Iqaluit","Rankin_Inlet","Cambridge_Bay","Yellowknife",    
+                  "Inuvik","Whitehorse","Dawson","Cancun","Mexico_City",    
+                  "Chihuahua","Hermosillo","Mazatlan","Tijuana","Anguilla", 
+                  "Antigua","Nassau","Barbados","Belize","Cayman",          
+                  "Costa_Rica","Havana","Dominica","Santo_Domingo",          
+                  "El_Salvador","Grenada","Guadeloupe","Guatemala",          
+                  "Port-au-Prince","Tegucigalpa","Jamaica","Martinique",     
+                  "Montserrat","Managua","Panama","Puerto_Rico","St_Kitts", 
+                  "St_Lucia","Miquelon","St_Vincent","Grand_Turk","Tortola",
+                  "St_Thomas","Buenos_Aires","Rosario","Cordoba","Jujuy",   
+                  "Catamarca","Mendoza","Aruba","La_Paz","Noronha","Belem",
+                  "Fortaleza","Araguaina","Maceio","Sao_Paulo","Cuiaba",    
+                  "Porto_Velho","Boa_Vista","Manaus","Porto_Acre","Santiago",
+                  "Bogota","Curacao","Guayaquil","Cayenne","Guyana",        
+                  "Asuncion","Lima","Paramaribo","Port_of_Spain",            
+                  "Montevideo","Caracas"}),                    
+   "Pacific":   ({"Rarotonga","Fiji","Gambier","Marquesas","Tahiti","Guam",
+                  "Tarawa","Enderbury","Kiritimati","Saipan","Majuro",      
+                  "Kwajalein","Yap","Truk","Ponape","Kosrae","Nauru",      
+                  "Noumea","Auckland","Chatham","Niue","Norfolk","Palau",  
+                  "Port_Moresby","Pitcairn","Pago_Pago","Apia","Guadalcanal",
+                  "Fakaofo","Tongatapu","Funafuti","Johnston","Midway",     
+                  "Wake","Efate","Wallis","Honolulu","Easter","Galapagos"}),
+   "Antarctica":({"Casey","Davis","Mawson","DumontDUrville","Syowa",        
+                  "Palmer","McMurdo"}),                        
+   "Atlantic":  ({"Cape_Verde","St_Helena","Faeroe","Reykjavik","Jan_Mayen",
+                  "Azores","Madeira","Canary","Bermuda","Stanley",          
+                  "South_Georgia"}),                            
+   "Indian":    ({"Comoro","Antananarivo","Mauritius","Mayotte","Reunion",  
+                  "Mahe","Kerguelen","Chagos","Maldives","Christmas",       
+                  "Cocos"}),                                    
+   "Europe":    ({"London","Belfast","Dublin","Tirane","Andorra","Vienna", 
+                  "Minsk","Brussels","Sofia","Prague","Copenhagen",         
+                  "Tallinn","Helsinki","Paris","Berlin","Gibraltar",        
+                  "Athens","Budapest","Rome","Riga","Vaduz","Vilnius",     
+                  "Luxembourg","Malta","Chisinau","Tiraspol","Monaco",      
+                  "Amsterdam","Oslo","Warsaw","Lisbon","Bucharest",         
+                  "Kaliningrad","Moscow","Samara","Madrid","Stockholm",     
+                  "Zurich","Istanbul","Kiev","Uzhgorod","Zaporozhye",       
+                  "Simferopol","Belgrade"}),                   
+   "Africa":    ({"Algiers","Luanda","Porto-Novo","Gaborone","Ouagadougou", 
+                  "Bujumbura","Douala","Bangui","Ndjamena","Kinshasa",      
+                  "Lubumbashi","Brazzaville","Abidjan","Djibouti","Cairo",  
+                  "Malabo","Asmera","Addis_Ababa","Libreville","Banjul",    
+                  "Accra","Conakry","Bissau","Nairobi","Maseru","Monrovia",
+                  "Tripoli","Blantyre","Bamako","Timbuktu","Nouakchott",    
+                  "Casablanca","El_Aaiun","Maputo","Windhoek","Niamey",     
+                  "Lagos","Kigali","Sao_Tome","Dakar","Freetown",           
+                  "Mogadishu","Johannesburg","Khartoum","Mbabane",           
+                  "Dar_es_Salaam","Lome","Tunis","Kampala","Lusaka",        
+                  "Harare","Ceuta"}),                          
+   "Asia":      ({"Kabul","Yerevan","Baku","Bahrain","Dacca","Thimbu",     
+                  "Brunei","Rangoon","Phnom_Penh","Harbin","Shanghai",      
+                  "Chungking","Urumqi","Kashgar","Hong_Kong","Taipei",      
+                  "Macao","Nicosia","Tbilisi","Dili","Calcutta","Jakarta", 
+                  "Ujung_Pandang","Jayapura","Tehran","Baghdad","Jerusalem",
+                  "Tokyo","Amman","Almaty","Aqtobe","Aqtau","Bishkek",     
+                  "Seoul","Pyongyang","Kuwait","Vientiane","Beirut",        
+                  "Kuala_Lumpur","Kuching","Hovd","Ulaanbaatar","Katmandu", 
+                  "Muscat","Karachi","Gaza","Manila","Qatar","Riyadh",     
+                  "Singapore","Colombo","Damascus","Dushanbe","Bangkok",    
+                  "Ashkhabad","Dubai","Samarkand","Tashkent","Saigon",      
+                  "Aden","Yekaterinburg","Omsk","Novosibirsk","Krasnoyarsk",
+                  "Irkutsk","Yakutsk","Vladivostok","Magadan","Kamchatka",  
+                  "Anadyr"}),                                   
+   "Australia": ({"Darwin","Perth","Brisbane","Lindeman","Adelaide",        
+                  "Hobart","Melbourne","Sydney","Broken_Hill","Lord_Howe"}),
+]);
+
diff --git a/lib/modules/Calendar.pmod/TZrules.pmod b/lib/modules/Calendar.pmod/TZrules.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..60cbd2c308c4b8fc9461ce9c1980c1e4e8ad1cc3
--- /dev/null
+++ b/lib/modules/Calendar.pmod/TZrules.pmod
@@ -0,0 +1,6003 @@
+// ----------------------------------------------------------------
+// Daylight savings and war time rules
+//
+// NOTE: this file is generated by mkrules.pike;
+//       please do not edit manually /Mirar
+// ----------------------------------------------------------------
+
+// ----------------------------------------------------------------
+// all rules are based on the gregorian calendar, so 
+// this is the gregorian rule:
+// ----------------------------------------------------------------
+
+static array gregorian_yjd(int jd)
+{
+   int d=jd-1721426;
+
+   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;
+
+   int y=century*100+century_year+1;
+
+   return 
+   ({
+      y,
+      1721426+century_year*365+century_year/4+century_jd,
+      (!(((y)%4) || (!((y)%100) && ((y)%400))))
+   });
+}
+
+// ----------------------------------------------------------------
+// Base "Timezone with rules" class
+// ----------------------------------------------------------------
+
+class TZRules
+{
+   constant is_timezone=1;
+   constant is_dst_timezone=1;
+   static int offset_to_utc;  
+   string name;
+
+   static function(string:string) tzformat;
+   static array names;
+
+   static void create(int offset,string _name) 
+   { 
+      offset_to_utc=offset; 
+      name=_name;
+      if (search(name,"/")!=-1)
+      {
+	 names=name/"/";
+	 tzformat=lambda(string s)
+		  {
+		     if (s=="") return names[0]; else return names[1];
+		  };
+      }
+      else
+	 tzformat=lambda(string s) { return sprintf(name,s); };
+   }
+
+// the Rule:
+// which julian day does dst start and end this year?
+   static array(array(string|int)) jd_year_periods(int jd);
+
+// is (midnight) this julian day dst?
+   array tz_jd(int jd)
+   {
+      array(array(string|int)) a=jd_year_periods(jd);
+
+      int i=0,n=sizeof(a)-1;
+      while (i<n)
+      {
+	 array b=a[i+1];
+	 if (jd<b[0]) break;
+	 if (jd==b[0] && -offset_to_utc+b[1]>=0) break;
+	 i++;
+      }
+
+      return ({offset_to_utc-a[i][2],tzformat(a[i][3])});
+   }
+
+// is this unixtime (utc) dst?
+   array tz_ux(int ux)
+   {
+      int jd=2440588+ux/86400;
+      array(array(string|int)) a=jd_year_periods(jd);
+
+      int i=0,n=sizeof(a)-1;
+      while (i<n)
+      {
+	 array b=a[i+1];
+	 if (jd<b[0]-1) break;
+	 if (jd<b[0]+1 &&
+	     ux<(b[0]-2440588)*86400+b[1]) break;
+	 i++;
+      }
+
+      return ({offset_to_utc-a[i][2],tzformat(a[i][3])});
+   }
+
+   string _sprintf(int t) { return (t=='O')?"Timezone("+name+")":0; }
+
+   int raw_utc_offset() { return offset_to_utc; }
+}
+
+// ----------------------------------------------------------------------
+// DST Rules
+// ----------------------------------------------------------------------
+
+// useful macros
+#define FIXED(D)   (yjd+((D)-1))
+#define FIX_L(D)   (yjd+leap+((D)-1))
+#define LDAY(D,W)  (yjd+((D)-1)-( (yjd+((D)+(8-W)-1)) % 7))
+#define LDAYL(D,W) (yjd+((D)-1)+leap-( (yjd+leap+((D)+(8-W)-1)) % 7))
+#define UO offset_to_utc
+
+// ----------------------------------------------------------------------
+class Algeria
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1916:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(166)  ,UO+82800  ,3600 ,"S"   }),  // Jun 14
+                     ({LDAY (281,7),UO+82800  ,0    ,""    })});// Oct Sun<=7
+         case 1917:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(83)   ,UO+82800  ,3600 ,"S"   }),  // Mar 24
+                     ({LDAY (280,7),UO+82800  ,0    ,""    })});// Oct Sun<=7
+         case 1918:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(68)   ,UO+82800  ,3600 ,"S"   }),  // Mar 9
+                     ({LDAY (280,7),UO+82800  ,0    ,""    })});// Oct Sun<=7
+         case 1919:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(60)   ,UO+82800  ,3600 ,"S"   }),  // Mar 1
+                     ({LDAY (280,7),UO+82800  ,0    ,""    })});// Oct Sun<=7
+         case 1920:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(45)   ,UO+82800  ,3600 ,"S"   }),  // Feb 14
+                     ({FIXED(297)  ,UO+82800  ,0    ,""    })});// Oct 23
+         case 1921:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(73)   ,UO+82800  ,3600 ,"S"   }),  // Mar 14
+                     ({FIXED(172)  ,UO+82800  ,0    ,""    })});// Jun 21
+         case 1939:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(254)  ,UO+82800  ,3600 ,"S"   }),  // Sep 11
+                     ({FIXED(323)  ,UO+0      ,0    ,""    })});// Nov 19
+         case 1944:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (98,1) ,UO+7200   ,3600 ,"S"   }),  // Apr Mon<=7
+                     ({FIXED(282)  ,UO+3600   ,0    ,""    })});// Oct 8
+         case 1945:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,1) ,UO+7200   ,3600 ,"S"   }),  // Apr Mon<=7
+                     ({FIXED(259)  ,UO+0      ,0    ,""    })});// Sep 16
+         case 1971:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(115)  ,UO+82800  ,3600 ,"S"   }),  // Apr 25
+                     ({FIXED(269)  ,UO+82800  ,0    ,""    })});// Sep 26
+         case 1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(126)  ,UO+0      ,3600 ,"S"   }),  // May 6
+                     ({FIXED(294)  ,UO-3600   ,0    ,""    })});// Oct 21
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(83)   ,UO+3600   ,3600 ,"S"   }),  // Mar 24
+                     ({FIXED(265)  ,UO+7200   ,0    ,""    })});// Sep 22
+         case 1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(116)  ,UO+0      ,3600 ,"S"   }),  // Apr 25
+                     ({FIXED(305)  ,UO+3600   ,0    ,""    })});// Oct 31
+         default: // ..1915 and 1981..
+         case 1922..1938:
+         case 1940..1943:
+         case 1946..1970:
+         case 1972..1976:
+         case 1979:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Egypt
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1940:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(197)  ,UO+0      ,3600 ,"S"   }),  // Jul 15
+                     ({FIXED(275)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1941:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(105)  ,UO+0      ,3600 ,"S"   }),  // Apr 15
+                     ({FIXED(259)  ,UO-3600   ,0    ,""    })});// Sep 16
+         case 1942:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(91)   ,UO+0      ,3600 ,"S"   }),  // Apr 1
+                     ({FIXED(300)  ,UO-3600   ,0    ,""    })});// Oct 27
+         case 1943..1944:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(91)   ,UO+0      ,3600 ,"S"   }),  // Apr 1
+                     ({FIX_L(305)  ,UO-3600   ,0    ,""    })});// Nov 1
+         case 1945:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(106)  ,UO+0      ,3600 ,"S"   }),  // Apr 16
+                     ({FIXED(305)  ,UO-3600   ,0    ,""    })});// Nov 1
+         default: // ..1939:
+         case 1946..1956:
+            return ({({0           ,0         ,0    ,""    })});
+         case 1957:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(130)  ,UO+0      ,3600 ,"S"   }),  // May 10
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1958:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(121)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1959..1965:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(121)  ,UO+3600   ,3600 ,"S"   }),  // May 1
+                     ({FIX_L(273)  ,UO+7200   ,0    ,""    })});// Sep 30
+         case 1982:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(206)  ,UO+3600   ,3600 ,"S"   }),  // Jul 25
+                     ({FIXED(274)  ,UO+7200   ,0    ,""    })});// Oct 1
+         case 1983:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(193)  ,UO+3600   ,3600 ,"S"   }),  // Jul 12
+                     ({FIXED(274)  ,UO+7200   ,0    ,""    })});// Oct 1
+         case 1989:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(126)  ,UO+3600   ,3600 ,"S"   }),  // May 6
+                     ({FIXED(274)  ,UO+7200   ,0    ,""    })});// Oct 1
+         case 1966..1981:
+         case 1984..1988:
+         case 1990..1994:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(121)  ,UO+3600   ,3600 ,"S"   }),  // May 1
+                     ({FIX_L(274)  ,UO+7200   ,0    ,""    })});// Oct 1
+         case 1995..:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(120,5),UO+0      ,3600 ,"S"   }),  // Apr lastFri
+                     ({LDAYL(273,4),UO+82800  ,0    ,""    })});// Sep lastThu
+      }
+   }
+}
+
+class Ghana
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1936..1942:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({FIX_L(244)  ,UO+0      ,1200 ,"GHST"}),  // Sep 1
+                     ({FIX_L(365)  ,UO-1200   ,0    ,"GMT" })});// Dec 31
+         default: // ..1935 and 1943..
+            return ({({0           ,0         ,0    ,"GMT" })});
+      }
+   }
+}
+
+class Libya
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1951:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(287)  ,UO+7200   ,3600 ,"S"   })});// Oct 14
+         case 1953:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(282)  ,UO+7200   ,3600 ,"S"   })});// Oct 9
+         case 1955:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(273)  ,UO+0      ,3600 ,"S"   })});// Sep 30
+         case 1952:
+         case 1954:
+         case 1956:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(1)    ,UO-3600   ,0    ,""    })});// Jan 1
+         case 1985:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(96)   ,UO+0      ,3600 ,"S"   }),  // Apr 6
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1986:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(94)   ,UO+0      ,3600 ,"S"   }),  // Apr 4
+                     ({FIXED(276)  ,UO-3600   ,0    ,""    })});// Oct 3
+         case 1982..1984:
+         case 1987..1989:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(91)   ,UO+0      ,3600 ,"S"   }),  // Apr 1
+                     ({FIX_L(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1990:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(274)  ,UO+0      ,0    ,""    })});// Oct 1
+         default: // ..1950 and 1991..
+         case 1957..1981:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Morocco
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1939:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(255)  ,UO+0      ,3600 ,"S"   }),  // Sep 12
+                     ({FIXED(323)  ,UO-3600   ,0    ,""    })});// Nov 19
+         case 1940:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(56)   ,UO+0      ,3600 ,"S"   })});// Feb 25
+         case 1941..1944:
+            return ({({0           ,0         ,3600 ,"S"   })});
+         case 1945:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(322)  ,UO-3600   ,0    ,""    })});// Nov 18
+         case 1950:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(162)  ,UO+0      ,3600 ,"S"   }),  // Jun 11
+                     ({FIXED(302)  ,UO-3600   ,0    ,""    })});// Oct 29
+         case 1967:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(154)  ,UO+43200  ,3600 ,"S"   }),  // Jun 3
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1974:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(175)  ,UO+0      ,3600 ,"S"   }),  // Jun 24
+                     ({FIXED(244)  ,UO-3600   ,0    ,""    })});// Sep 1
+         case 1976:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(122)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({FIXED(214)  ,UO-3600   ,0    ,""    })});// Aug 1
+         case 1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(121)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({FIXED(271)  ,UO-3600   ,0    ,""    })});// Sep 28
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(152)  ,UO+0      ,3600 ,"S"   }),  // Jun 1
+                     ({FIXED(216)  ,UO-3600   ,0    ,""    })});// Aug 4
+         default: // ..1938 and 1979..
+         case 1946..1949:
+         case 1951..1966:
+         case 1968..1973:
+         case 1975:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Namibia
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1993:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1994:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({LDAY (250,7),UO+7200   ,3600 ,"S"   })});// Sep Sun>=1
+         case 1995..:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+3600   ,0    ,""    }),  // Apr Sun>=1
+                     ({LDAYL(250,7),UO+7200   ,3600 ,"S"   })});// Sep Sun>=1
+      }
+   }
+}
+
+class SL
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1935..1942:
+            return ({({0           ,0         ,0    ,"WAT" }),  
+                     ({FIX_L(152)  ,UO+0      ,2400 ,"SLST"}),  // Jun 1
+                     ({FIX_L(274)  ,UO-2400   ,0    ,"WAT" })});// Oct 1
+         default: // ..1934:
+         case 1943..1956:
+            return ({({0           ,0         ,0    ,"WAT" })});
+         case 1957:
+            return ({({0           ,0         ,0    ,"WAT" }),  
+                     ({FIXED(152)  ,UO+0      ,3600 ,"SLST"}),  // Jun 1
+                     ({FIXED(244)  ,UO-3600   ,0    ,"GMT" })});// Sep 1
+         case 1958..1962:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({FIX_L(152)  ,UO+0      ,3600 ,"SLST"}),  // Jun 1
+                     ({FIX_L(244)  ,UO-3600   ,0    ,"GMT" })});// Sep 1
+         case 1963..:
+            return ({({0           ,0         ,0    ,"GMT" })});
+      }
+   }
+}
+
+class SA
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1942:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({LDAY (264,7),UO+7200   ,3600 ,""    })});// Sep Sun>=15
+         case 1943:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (80,7) ,UO+3600   ,0    ,""    }),  // Mar Sun>=15
+                     ({LDAY (264,7),UO+7200   ,3600 ,""    })});// Sep Sun>=15
+         case 1944:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (81,7) ,UO+3600   ,0    ,""    })});// Mar Sun>=15
+         default: // ..1941 and 1945..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Sudan
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1970:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(121)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({FIXED(288)  ,UO-3600   ,0    ,""    })});// Oct 15
+         case 1971:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(120)  ,UO+0      ,3600 ,"S"   }),  // Apr 30
+                     ({FIXED(288)  ,UO-3600   ,0    ,""    })});// Oct 15
+         case 1972..1985:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(120,7),UO+0      ,3600 ,"S"   }),  // Apr lastSun
+                     ({FIX_L(288)  ,UO-3600   ,0    ,""    })});// Oct 15
+         default: // ..1969 and 1986..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Tunisia
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1939:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(105)  ,UO+82800  ,3600 ,"S"   }),  // Apr 15
+                     ({FIXED(322)  ,UO+82800  ,0    ,""    })});// Nov 18
+         case 1940:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(56)   ,UO+82800  ,3600 ,"S"   })});// Feb 25
+         case 1941:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(279)  ,UO-3600   ,0    ,""    })});// Oct 6
+         case 1942:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(68)   ,UO+0      ,3600 ,"S"   }),  // Mar 9
+                     ({FIXED(306)  ,UO+7200   ,0    ,""    })});// Nov 2
+         case 1943:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(88)   ,UO+7200   ,3600 ,"S"   }),  // Mar 29
+                     ({FIXED(107)  ,UO+3600   ,0    ,""    }),  // Apr 17
+                     ({FIXED(115)  ,UO+7200   ,3600 ,"S"   }),  // Apr 25
+                     ({FIXED(277)  ,UO+3600   ,0    ,""    })});// Oct 4
+         case 1944:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (98,1) ,UO+7200   ,3600 ,"S"   }),  // Apr Mon>=1
+                     ({FIXED(282)  ,UO-3600   ,0    ,""    })});// Oct 8
+         case 1945:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,1) ,UO+7200   ,3600 ,"S"   }),  // Apr Mon>=1
+                     ({FIXED(259)  ,UO-3600   ,0    ,""    })});// Sep 16
+         case 1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(120)  ,UO+0      ,3600 ,"S"   }),  // Apr 30
+                     ({FIXED(267)  ,UO+0      ,0    ,""    })});// Sep 24
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(121)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({FIXED(274)  ,UO+0      ,0    ,""    })});// Oct 1
+         case 1988:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(153)  ,UO+0      ,3600 ,"S"   }),  // Jun 1
+                     ({LDAY (274,7),UO+0      ,0    ,""    })});// Sep lastSun
+         case 1989:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(85)   ,UO+0      ,3600 ,"S"   }),  // Mar 26
+                     ({LDAY (273,7),UO+0      ,0    ,""    })});// Sep lastSun
+         case 1990:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(121)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({LDAY (273,7),UO+0      ,0    ,""    })});// Sep lastSun
+         default: // ..1938 and 1991..
+         case 1946..1976:
+         case 1979..1987:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class ArgAQ
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1964:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(61)   ,UO+0      ,0    ,""    }),  // Mar 1
+                     ({FIXED(289)  ,UO+0      ,3600 ,"S"   })});// Oct 15
+         case 1965..1966:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(60)   ,UO-3600   ,0    ,""    }),  // Mar 1
+                     ({FIXED(288)  ,UO+0      ,3600 ,"S"   })});// Oct 15
+         case 1967:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(91)   ,UO-3600   ,0    ,""    }),  // Apr 1
+                     ({LDAY (280,7),UO+0      ,3600 ,"S"   })});// Oct Sun<=7
+         case 1974:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(23)   ,UO+0      ,3600 ,"S"   }),  // Jan 23
+                     ({FIXED(121)  ,UO-3600   ,0    ,""    }),  // May 1
+                     ({LDAY (280,7),UO+0      ,3600 ,"S"   })});// Oct Sun<=7
+         case 1968:
+         case 1975..1976:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAYL(97,7) ,UO-3600   ,0    ,""    }),  // Apr Sun<=7
+                     ({LDAYL(280,7),UO+0      ,3600 ,"S"   })});// Oct Sun<=7
+         case 1969:
+         case 1977:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (97,7) ,UO-3600   ,0    ,""    })});// Apr Sun<=7
+         default: // ..1963 and 1978..
+         case 1970..1973:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class ChileAQ
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1968:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1969:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({LDAY (288,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=9
+         case 1998:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (74,7) ,UO-3600   ,0    ,""    }),  // Mar Sun>=9
+                     ({FIXED(270)  ,UO+0      ,3600 ,"S"   })});// Sep 27
+         case 1999:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(94)   ,UO-3600   ,0    ,""    }),  // Apr 4
+                     ({LDAY (288,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=9
+         case 1970..1997:
+         case 2000..:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAYL(74,7) ,UO-3600   ,0    ,""    }),  // Mar Sun>=9
+                     ({LDAYL(288,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=9
+      }
+   }
+}
+
+class NZAQ
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1973:
+            return ({({0           ,0         ,0    ,"S"   })});// ?
+         case 1974:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(307)  ,UO+7200   ,3600 ,"D"   })});// Nov 3
+         case 1975:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({FIXED(54)   ,UO+7200   ,0    ,"S"   }),  // Feb 23
+                     ({LDAY (304,7),UO+7200   ,3600 ,"D"   })});// Oct lastSun
+         case 1976..1988:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({LDAYL(66,7) ,UO+7200   ,0    ,"S"   }),  // Mar Sun>=1
+                     ({LDAYL(304,7),UO+7200   ,3600 ,"D"   })});// Oct lastSun
+         case 1989:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({LDAY (66,7) ,UO+7200   ,0    ,"S"   }),  // Mar Sun>=1
+                     ({FIXED(281)  ,UO+7200   ,3600 ,"D"   })});// Oct 8
+         case 1990..:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({LDAYL(80,7) ,UO+7200   ,0    ,"S"   }),  // Mar Sun>=15
+                     ({LDAYL(280,7),UO+7200   ,3600 ,"D"   })});// Oct Sun>=1
+      }
+   }
+}
+
+class EUAsia
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1980:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1981:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({LDAY (90,7) ,3600      ,3600 ,"S"   })});// Mar lastSun
+         case 1982..1995:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAYL(90,7) ,3600      ,3600 ,"S"   })});// Mar lastSun
+         case 1996:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (91,7) ,3600      ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAY (305,7),3600      ,0    ,""    })});// Oct lastSun
+         case 1997..:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,3600      ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(304,7),3600      ,0    ,""    })});// Oct lastSun
+      }
+   }
+}
+
+class E_EurAsia
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1978:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1979..1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(273,7),UO+0      ,0    ,""    })});// Sep lastSun
+         case 1981..1995:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+0      ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(273,7),UO-3600   ,0    ,""    })});// Sep lastSun
+         case 1996..:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+0      ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(304,7),UO-3600   ,0    ,""    })});// Oct lastSun
+      }
+   }
+}
+
+class RussiaAsia
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1980:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1981..1983:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(91)   ,UO+0      ,3600 ,"S"   }),  // Apr 1
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1984:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(92)   ,UO+0      ,3600 ,"S"   }),  // Apr 1
+                     ({LDAY (274,7),UO+7200   ,0    ,""    })});// Sep lastSun
+         case 1992:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (91,6) ,UO+82800  ,3600 ,"S"   }),  // Mar lastSat
+                     ({LDAY (274,6),UO+79200  ,0    ,""    })});// Sep lastSat
+         case 1985..1991:
+         case 1993..1995:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+7200   ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(273,7),UO+7200   ,0    ,""    })});// Sep lastSun
+         case 1996..:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+7200   ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(304,7),UO+7200   ,0    ,""    })});// Oct lastSun
+      }
+   }
+}
+
+class Azer
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1996:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1997..:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+3600   ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(304,7),UO+0      ,0    ,""    })});// Oct lastSun
+      }
+   }
+}
+
+class Shang
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1940:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(155)  ,UO+0      ,3600 ,"D"   }),  // Jun 3
+                     ({FIXED(275)  ,UO-3600   ,0    ,"S"   })});// Oct 1
+         case 1941:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(75)   ,UO+0      ,3600 ,"D"   }),  // Mar 16
+                     ({FIXED(274)  ,UO-3600   ,0    ,"S"   })});// Oct 1
+         default: // ..1939 and 1942..
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class PRC
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1949:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(1)    ,UO+0      ,0    ,"S"   })});// Jan 1
+         case 1986:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(124)  ,UO+0      ,3600 ,"D"   }),  // May 4
+                     ({LDAY (260,7),UO-3600   ,0    ,"S"   })});// Sep Sun>=11
+         case 1987..1991:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(106,7),UO+0      ,3600 ,"D"   }),  // Apr Sun>=10
+                     ({LDAYL(260,7),UO-3600   ,0    ,"S"   })});// Sep Sun>=11
+         default: // ..1948 and 1992..
+         case 1950..1985:
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class HK
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1946:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(110)  ,UO+12600  ,3600 ,"S"   }),  // Apr 20
+                     ({FIXED(335)  ,UO+9000   ,0    ,""    })});// Dec 1
+         case 1947:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(103)  ,UO+12600  ,3600 ,"S"   }),  // Apr 13
+                     ({FIXED(364)  ,UO+9000   ,0    ,""    })});// Dec 30
+         case 1948:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(123)  ,UO+12600  ,3600 ,"S"   }),  // May 2
+                     ({LDAY (305,7),UO+9000   ,0    ,""    })});// Oct lastSun
+         case 1949..1952:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(97,7) ,UO+12600  ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO+9000   ,0    ,""    })});// Oct lastSun
+         case 1953:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+12600  ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({FIXED(305)  ,UO+9000   ,0    ,""    })});// Nov 1
+         case 1954:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (83,7) ,UO+12600  ,3600 ,"S"   }),  // Mar Sun>=18
+                     ({FIXED(304)  ,UO+9000   ,0    ,""    })});// Oct 31
+         case 1955..1964:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(83,7) ,UO+12600  ,3600 ,"S"   }),  // Mar Sun>=18
+                     ({LDAYL(311,7),UO+9000   ,0    ,""    })});// Nov Sun>=1
+         case 1965..1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(112,7),UO+12600  ,3600 ,"S"   }),  // Apr Sun>=16
+                     ({LDAYL(295,7),UO+9000   ,0    ,""    })});// Oct Sun>=16
+         case 1979..1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(134,7),UO+12600  ,3600 ,"S"   }),  // May Sun>=8
+                     ({LDAYL(295,7),UO+9000   ,0    ,""    })});// Oct Sun>=16
+         default: // ..1945 and 1981..
+         case 1978:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Taiwan
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1945..1951:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIX_L(121)  ,UO+0      ,3600 ,"D"   }),  // May 1
+                     ({FIX_L(274)  ,UO-3600   ,0    ,"S"   })});// Oct 1
+         case 1952:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(61)   ,UO+0      ,3600 ,"D"   }),  // Mar 1
+                     ({FIXED(306)  ,UO-3600   ,0    ,"S"   })});// Nov 1
+         case 1953..1954:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(91)   ,UO+0      ,3600 ,"D"   }),  // Apr 1
+                     ({FIXED(305)  ,UO-3600   ,0    ,"S"   })});// Nov 1
+         case 1960..1961:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIX_L(152)  ,UO+0      ,3600 ,"D"   }),  // Jun 1
+                     ({FIX_L(274)  ,UO-3600   ,0    ,"S"   })});// Oct 1
+         case 1955..1959:
+         case 1974..1975:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIX_L(91)   ,UO+0      ,3600 ,"D"   }),  // Apr 1
+                     ({FIX_L(274)  ,UO-3600   ,0    ,"S"   })});// Oct 1
+         case 1980:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(182)  ,UO+0      ,3600 ,"D"   }),  // Jun 30
+                     ({FIXED(274)  ,UO-3600   ,0    ,"S"   })});// Sep 30
+         default: // ..1944 and 1981..
+         case 1962..1973:
+         case 1976..1979:
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Macao
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1963:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (81,7) ,UO+0      ,3600 ,"S"   }),  // Mar Sun>=16
+                     ({LDAY (311,7),UO+9000   ,0    ,""    })});// Nov Sun>=1
+         case 1961..1962:
+         case 1964:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(81,7) ,UO+12600  ,3600 ,"S"   }),  // Mar Sun>=16
+                     ({LDAYL(311,7),UO+9000   ,0    ,""    })});// Nov Sun>=1
+         case 1965:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (81,7) ,UO+0      ,3600 ,"S"   }),  // Mar Sun>=16
+                     ({FIXED(304)  ,UO-3600   ,0    ,""    })});// Oct 31
+         case 1966..1971:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(112,7),UO+12600  ,3600 ,"S"   }),  // Apr Sun>=16
+                     ({LDAYL(295,7),UO+9000   ,0    ,""    })});// Oct Sun>=16
+         case 1974:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (111,7),UO+0      ,3600 ,"S"   }),  // Apr Sun>=15
+                     ({LDAY (294,7),UO+9000   ,0    ,""    })});// Oct Sun>=15
+         case 1975..1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(111,7),UO+12600  ,3600 ,"S"   }),  // Apr Sun>=15
+                     ({LDAYL(294,7),UO+9000   ,0    ,""    })});// Oct Sun>=15
+         case 1972..1973:
+         case 1978..1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(111,7),UO+0      ,3600 ,"S"   }),  // Apr Sun>=15
+                     ({LDAYL(294,7),UO-3600   ,0    ,""    })});// Oct Sun>=15
+         default: // ..1960 and 1981..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Cyprus
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1974:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1975:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(103)  ,UO+0      ,3600 ,"S"   }),  // Apr 13
+                     ({FIXED(285)  ,UO-3600   ,0    ,""    })});// Oct 12
+         case 1976:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(136)  ,UO+0      ,3600 ,"S"   }),  // May 15
+                     ({FIXED(285)  ,UO-3600   ,0    ,""    })});// Oct 11
+         case 1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+0      ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({FIXED(268)  ,UO-3600   ,0    ,""    })});// Sep 25
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+0      ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({FIXED(275)  ,UO-3600   ,0    ,""    })});// Oct 2
+         case 1979..1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(97,7) ,UO+0      ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({LDAYL(273,7),UO-3600   ,0    ,""    })});// Sep lastSun
+         case 1981..1997:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+0      ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(273,7),UO-3600   ,0    ,""    })});// Sep lastSun
+         case 1998:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (90,7) ,UO+0      ,3600 ,"S"   })});// Mar lastSun
+         case 1999..:
+            return ({({0           ,0         ,3600 ,"S"   })});
+      }
+   }
+}
+
+class Iran
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(80)   ,UO+0      ,3600 ,"S"   }),  // Mar 21
+                     ({FIXED(294)  ,UO-3600   ,0    ,""    })});// Oct 21
+         case 1979:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(80)   ,UO+0      ,3600 ,"S"   }),  // Mar 21
+                     ({FIXED(262)  ,UO-3600   ,0    ,""    })});// Sep 19
+         case 1991:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(123)  ,UO+0      ,3600 ,"S"   }),  // May 3
+                     ({FIXED(263)  ,UO+0      ,0    ,""    })});// Sep 20
+         case 1980:
+         case 1992..1995:
+         case 1997..1999:
+         case 2001..2003:
+         case 2005..2007:
+         case 2009..2011:
+         case 2013..2015:
+         case 2017..2019:
+         case 2021..2023:
+         case 2026..2027:
+         case 2030..2031:
+         case 2034..2035:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(80)   ,UO+0      ,3600 ,"S"   }),  // Mar 21
+                     ({FIX_L(266)  ,UO-3600   ,0    ,""    })});// Sep 23
+         case 1996:
+         case 2000:
+         case 2004:
+         case 2008:
+         case 2012:
+         case 2016:
+         case 2020:
+         case 2024..2025:
+         case 2028..2029:
+         case 2032..2033:
+         case 2036..2037:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(79)   ,UO+0      ,3600 ,"S"   }),  // Mar 20
+                     ({FIX_L(265)  ,UO-3600   ,0    ,""    })});// Sep 22
+         default: // ..1977 and 2038..
+         case 1981..1990:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Iraq
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1981:
+            return ({({0           ,0         ,0    ,"S"   })});// ?
+         case 1982:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(121)  ,UO+0      ,3600 ,"D"   }),  // May 1
+                     ({FIXED(274)  ,UO-3600   ,0    ,"S"   })});// Oct 1
+         case 1983:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(90)   ,UO+0      ,3600 ,"D"   }),  // Mar 31
+                     ({FIXED(274)  ,UO-3600   ,0    ,"S"   })});// Oct 1
+         case 1984:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(92)   ,UO+0      ,3600 ,"D"   }),  // Apr 1
+                     ({FIXED(275)  ,UO-3600   ,0    ,"S"   })});// Oct 1
+         case 1985:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(91)   ,UO+0      ,3600 ,"D"   }),  // Apr 1
+                     ({LDAY (273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1986..1990:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(90,7) ,UO+3600   ,3600 ,"D"   }),  // Mar lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1991:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(91)   ,UO+10800  ,3600 ,"D"   }),  // Apr 1
+                     ({FIXED(274)  ,UO+10800  ,0    ,"D"   })});// Oct 1
+         case 1992..:
+            return ({({0           ,0         ,0    ,"D"   }),  
+                     ({FIX_L(91)   ,UO+10800  ,3600 ,"D"   }),  // Apr 1
+                     ({FIX_L(274)  ,UO+10800  ,0    ,"D"   })});// Oct 1
+      }
+   }
+}
+
+class Zion
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1940:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(153)  ,UO+0      ,3600 ,"D"   })});// Jun 1
+         case 1941:
+            return ({({0           ,0         ,3600 ,"D"   })});
+         case 1942:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({FIXED(305)  ,UO-3600   ,0    ,"S"   })});// Nov 1
+         case 1943:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(91)   ,UO+7200   ,3600 ,"D"   }),  // Apr 1
+                     ({FIXED(305)  ,UO-3600   ,0    ,"S"   })});// Nov 1
+         case 1944:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(92)   ,UO+0      ,3600 ,"D"   }),  // Apr 1
+                     ({FIXED(306)  ,UO-3600   ,0    ,"S"   })});// Nov 1
+         case 1945:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(106)  ,UO+0      ,3600 ,"D"   }),  // Apr 16
+                     ({FIXED(305)  ,UO+3600   ,0    ,"S"   })});// Nov 1
+         case 1946:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(106)  ,UO+7200   ,3600 ,"D"   }),  // Apr 16
+                     ({FIXED(305)  ,UO-3600   ,0    ,"S"   })});// Nov 1
+         case 1948:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(144)  ,UO+0      ,7200 ,"DD"  }),  // May 23
+                     ({FIXED(245)  ,UO-7200   ,3600 ,"D"   }),  // Sep 1
+                     ({FIXED(306)  ,UO+3600   ,0    ,"S"   })});// Nov 1
+         case 1949:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(121)  ,UO+0      ,3600 ,"D"   }),  // May 1
+                     ({FIXED(305)  ,UO+3600   ,0    ,"S"   })});// Nov 1
+         case 1950:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(106)  ,UO+0      ,3600 ,"D"   }),  // Apr 16
+                     ({FIXED(258)  ,UO+7200   ,0    ,"S"   })});// Sep 15
+         case 1951:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(91)   ,UO+0      ,3600 ,"D"   }),  // Apr 1
+                     ({FIXED(315)  ,UO+7200   ,0    ,"S"   })});// Nov 11
+         case 1952:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(111)  ,UO+7200   ,3600 ,"D"   }),  // Apr 20
+                     ({FIXED(293)  ,UO+7200   ,0    ,"S"   })});// Oct 19
+         case 1953:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(102)  ,UO+7200   ,3600 ,"D"   }),  // Apr 12
+                     ({FIXED(256)  ,UO+7200   ,0    ,"S"   })});// Sep 13
+         case 1954:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(164)  ,UO+0      ,3600 ,"D"   }),  // Jun 13
+                     ({FIXED(255)  ,UO-3600   ,0    ,"S"   })});// Sep 12
+         case 1955:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(162)  ,UO+7200   ,3600 ,"D"   }),  // Jun 11
+                     ({FIXED(254)  ,UO-3600   ,0    ,"S"   })});// Sep 11
+         case 1956:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(155)  ,UO+0      ,3600 ,"D"   }),  // Jun 3
+                     ({FIXED(274)  ,UO+7200   ,0    ,"S"   })});// Sep 30
+         case 1957:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(119)  ,UO+7200   ,3600 ,"D"   }),  // Apr 29
+                     ({FIXED(265)  ,UO-3600   ,0    ,"S"   })});// Sep 22
+         case 1974:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(188)  ,UO+0      ,3600 ,"D"   }),  // Jul 7
+                     ({FIXED(286)  ,UO-3600   ,0    ,"S"   })});// Oct 13
+         case 1975:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(110)  ,UO+0      ,3600 ,"D"   }),  // Apr 20
+                     ({FIXED(243)  ,UO-3600   ,0    ,"S"   })});// Aug 31
+         default: // ..1939:
+         case 1947:
+         case 1958..1973:
+         case 1976..1984:
+            return ({({0           ,0         ,0    ,"S"   })});
+         case 1985:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(104)  ,UO+0      ,3600 ,"D"   }),  // Apr 14
+                     ({FIXED(258)  ,UO-3600   ,0    ,"S"   })});// Sep 15
+         case 1986:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(138)  ,UO+0      ,3600 ,"D"   }),  // May 18
+                     ({FIXED(250)  ,UO-3600   ,0    ,"S"   })});// Sep 7
+         case 1987:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(105)  ,UO+0      ,3600 ,"D"   }),  // Apr 15
+                     ({FIXED(256)  ,UO-3600   ,0    ,"S"   })});// Sep 13
+         case 1988:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(100)  ,UO+0      ,3600 ,"D"   }),  // Apr 9
+                     ({FIXED(247)  ,UO-3600   ,0    ,"S"   })});// Sep 3
+         case 1989:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(120)  ,UO+0      ,3600 ,"D"   }),  // Apr 30
+                     ({FIXED(246)  ,UO-3600   ,0    ,"S"   })});// Sep 3
+         case 1990:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(84)   ,UO+0      ,3600 ,"D"   }),  // Mar 25
+                     ({FIXED(238)  ,UO-3600   ,0    ,"S"   })});// Aug 26
+         case 1991:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(83)   ,UO+0      ,3600 ,"D"   }),  // Mar 24
+                     ({FIXED(244)  ,UO-3600   ,0    ,"S"   })});// Sep 1
+         case 1992:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(89)   ,UO+0      ,3600 ,"D"   }),  // Mar 29
+                     ({FIXED(250)  ,UO-3600   ,0    ,"S"   })});// Sep 6
+         case 1993:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(92)   ,UO+0      ,3600 ,"D"   }),  // Apr 2
+                     ({FIXED(248)  ,UO-3600   ,0    ,"S"   })});// Sep 5
+         case 1994:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(91)   ,UO+0      ,3600 ,"D"   }),  // Apr 1
+                     ({FIXED(240)  ,UO-3600   ,0    ,"S"   })});// Aug 28
+         case 1995:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(90)   ,UO+0      ,3600 ,"D"   }),  // Mar 31
+                     ({FIXED(246)  ,UO-3600   ,0    ,"S"   })});// Sep 3
+         case 1996:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(75)   ,UO+0      ,3600 ,"D"   }),  // Mar 15
+                     ({FIXED(260)  ,UO-3600   ,0    ,"S"   })});// Sep 16
+         case 1997:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(80)   ,UO+0      ,3600 ,"D"   }),  // Mar 21
+                     ({FIXED(257)  ,UO-3600   ,0    ,"S"   })});// Sep 14
+         case 1998:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(79)   ,UO+0      ,3600 ,"D"   }),  // Mar 20
+                     ({FIXED(249)  ,UO-3600   ,0    ,"S"   })});// Sep 6
+         case 1999:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(92)   ,UO+7200   ,3600 ,"D"   }),  // Apr 2
+                     ({FIXED(246)  ,UO+3600   ,0    ,"S"   })});// Sep 3
+         case 2000:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(105)  ,UO+7200   ,3600 ,"D"   }),  // Apr 14
+                     ({FIXED(296)  ,UO+3600   ,0    ,"S"   })});// Oct 22
+         case 2001:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(96)   ,UO+7200   ,3600 ,"D"   }),  // Apr 6
+                     ({FIXED(283)  ,UO+3600   ,0    ,"S"   })});// Oct 10
+         case 2002:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(88)   ,UO+7200   ,3600 ,"D"   }),  // Mar 29
+                     ({FIXED(272)  ,UO+3600   ,0    ,"S"   })});// Sep 29
+         case 2003..:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(90,5) ,UO+7200   ,3600 ,"D"   }),  // Mar Fri>=25
+                     ({FIX_L(274)  ,UO+3600   ,0    ,"S"   })});// Oct 1
+      }
+   }
+}
+
+class Jordan
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1973:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(157)  ,UO+0      ,3600 ,"S"   }),  // Jun 6
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1976:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(122)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({FIXED(306)  ,UO-3600   ,0    ,""    })});// Nov 1
+         case 1974..1975:
+         case 1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(121)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(120)  ,UO+0      ,3600 ,"S"   }),  // Apr 30
+                     ({FIXED(273)  ,UO-3600   ,0    ,""    })});// Sep 30
+         default: // ..1972:
+         case 1979..1984:
+            return ({({0           ,0         ,0    ,""    })});
+         case 1985:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(91)   ,UO+0      ,3600 ,"S"   }),  // Apr 1
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1989:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(128)  ,UO+0      ,3600 ,"S"   }),  // May 8
+                     ({LDAY (280,5),UO-3600   ,0    ,""    })});// Oct Fri>=1
+         case 1990:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(117)  ,UO+0      ,3600 ,"S"   }),  // Apr 27
+                     ({LDAY (280,5),UO-3600   ,0    ,""    })});// Oct Fri>=1
+         case 1991:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(107)  ,UO+0      ,3600 ,"S"   }),  // Apr 17
+                     ({FIXED(270)  ,UO-3600   ,0    ,""    })});// Sep 27
+         case 1992:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(101)  ,UO+0      ,3600 ,"S"   }),  // Apr 10
+                     ({LDAY (281,5),UO-3600   ,0    ,""    })});// Oct Fri>=1
+         case 1986..1988:
+         case 1993:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(97,5) ,UO+0      ,3600 ,"S"   }),  // Apr Fri>=1
+                     ({LDAYL(280,5),UO-3600   ,0    ,""    })});// Oct Fri>=1
+         case 1994:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,5) ,UO+0      ,3600 ,"S"   }),  // Apr Fri>=1
+                     ({LDAY (264,5),UO-3600   ,0    ,""    })});// Sep Fri>=15
+         case 1995..1998:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(97,5) ,UO+0      ,3600 ,"S"   }),  // Apr Fri>=1
+                     ({LDAYL(264,5),UO+0      ,0    ,""    })});// Sep Fri>=15
+         case 1999:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(182)  ,UO+0      ,3600 ,"S"   }),  // Jul 1
+                     ({LDAY (273,4),UO+0      ,0    ,""    })});// Sep lastThu
+         case 2000..:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,4) ,UO+0      ,3600 ,"S"   }),  // Mar lastThu
+                     ({LDAYL(273,4),UO+0      ,0    ,""    })});// Sep lastThu
+      }
+   }
+}
+
+class Kirgiz
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1991:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1992..1996:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(103,7),UO+0      ,3600 ,"S"   }),  // Apr Sun>=7
+                     ({LDAYL(273,7),UO-3600   ,0    ,""    })});// Sep lastSun
+         case 1997..:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+9000   ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(304,7),UO+5400   ,0    ,""    })});// Oct lastSun
+      }
+   }
+}
+
+class ROK
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1960:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(136)  ,UO+0      ,3600 ,"D"   }),  // May 15
+                     ({FIXED(257)  ,UO-3600   ,0    ,"S"   })});// Sep 13
+         case 1987..1988:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(134,7),UO+0      ,3600 ,"D"   }),  // May Sun<=14
+                     ({LDAYL(287,7),UO-3600   ,0    ,"S"   })});// Oct Sun<=14
+         default: // ..1959 and 1989..
+         case 1961..1986:
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Lebanon
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1920:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(88)   ,UO+0      ,3600 ,"S"   }),  // Mar 28
+                     ({FIXED(299)  ,UO-3600   ,0    ,""    })});// Oct 25
+         case 1921:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(93)   ,UO+0      ,3600 ,"S"   }),  // Apr 3
+                     ({FIXED(276)  ,UO-3600   ,0    ,""    })});// Oct 3
+         case 1922:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(85)   ,UO+0      ,3600 ,"S"   }),  // Mar 26
+                     ({FIXED(281)  ,UO-3600   ,0    ,""    })});// Oct 8
+         case 1923:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(112)  ,UO+0      ,3600 ,"S"   }),  // Apr 22
+                     ({FIXED(259)  ,UO-3600   ,0    ,""    })});// Sep 16
+         case 1972:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(174)  ,UO+0      ,3600 ,"S"   }),  // Jun 22
+                     ({FIXED(275)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1957..1961:
+         case 1973..1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(121)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({FIX_L(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(120)  ,UO+0      ,3600 ,"S"   }),  // Apr 30
+                     ({FIXED(273)  ,UO-3600   ,0    ,""    })});// Sep 30
+         default: // ..1919:
+         case 1924..1956:
+         case 1962..1971:
+         case 1979..1983:
+            return ({({0           ,0         ,0    ,""    })});
+         case 1988:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(153)  ,UO+0      ,3600 ,"S"   }),  // Jun 1
+                     ({FIXED(290)  ,UO-3600   ,0    ,""    })});// Oct 16
+         case 1989:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(130)  ,UO+0      ,3600 ,"S"   }),  // May 10
+                     ({FIXED(289)  ,UO-3600   ,0    ,""    })});// Oct 16
+         case 1984..1987:
+         case 1990..1991:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(121)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({FIX_L(289)  ,UO-3600   ,0    ,""    })});// Oct 16
+         case 1992:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(122)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({FIXED(278)  ,UO-3600   ,0    ,""    })});// Oct 4
+         case 1993..1998:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+0      ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(273,7),UO-3600   ,0    ,""    })});// Sep lastSun
+         case 1999..:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+0      ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(304,7),UO-3600   ,0    ,""    })});// Oct lastSun
+      }
+   }
+}
+
+class NBorneo
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1935..1941:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(257)  ,UO+0      ,1200 ,"TS"  }),  // Sep 14
+                     ({FIX_L(348)  ,UO-1200   ,0    ,""    })});// Dec 14
+         default: // ..1934 and 1942..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Mongol
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1981..1984:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(91)   ,UO+0      ,3600 ,"S"   }),  // Apr 1
+                     ({FIX_L(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1985..1990:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+7200   ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(273,7),UO+7200   ,0    ,""    })});// Sep lastSun
+         case 1996:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (91,7) ,UO+0      ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAY (305,7),UO-3600   ,0    ,""    })});// Oct lastSun
+         case 1991..1995:
+         case 1997..1998:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+0      ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(273,7),UO-3600   ,0    ,""    })});// Sep lastSun
+         default: // ..1980 and 1999..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class EgyptAsia
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1956:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1957:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(130)  ,UO+0      ,3600 ,"S"   }),  // May 10
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1958:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(121)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1959..1965:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(121)  ,UO+3600   ,3600 ,"S"   }),  // May 1
+                     ({FIX_L(273)  ,UO+7200   ,0    ,""    })});// Sep 30
+         case 1966:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(121)  ,UO+3600   ,3600 ,"S"   }),  // May 1
+                     ({FIXED(274)  ,UO+7200   ,0    ,""    })});// Oct 1
+         case 1967:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(121)  ,UO+3600   ,3600 ,"S"   })});// May 1
+         case 1968..:
+            return ({({0           ,0         ,3600 ,"S"   })});
+      }
+   }
+}
+
+class Palestine
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1998:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1999..:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(111,5),UO+0      ,3600 ,"S"   }),  // Apr Fri>=15
+                     ({LDAYL(294,5),UO-3600   ,0    ,""    })});// Oct Fri>=15
+      }
+   }
+}
+
+class Phil
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1936:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(306)  ,UO+0      ,3600 ,"S"   })});// Nov 1
+         case 1937:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(32)   ,UO-3600   ,0    ,""    })});// Feb 1
+         case 1954:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(102)  ,UO+0      ,3600 ,"S"   }),  // Apr 12
+                     ({FIXED(182)  ,UO-3600   ,0    ,""    })});// Jul 1
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(81)   ,UO+0      ,3600 ,"S"   }),  // Mar 22
+                     ({FIXED(264)  ,UO-3600   ,0    ,""    })});// Sep 21
+         default: // ..1935 and 1979..
+         case 1938..1953:
+         case 1955..1977:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Syria
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1920..1923:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(111,7),UO+7200   ,3600 ,"S"   }),  // Apr Sun>=15
+                     ({LDAYL(280,7),UO+3600   ,0    ,""    })});// Oct Sun>=1
+         case 1962:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(119)  ,UO+7200   ,3600 ,"S"   }),  // Apr 29
+                     ({FIXED(274)  ,UO+3600   ,0    ,""    })});// Oct 1
+         case 1963:
+         case 1965:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(121)  ,UO+7200   ,3600 ,"S"   }),  // May 1
+                     ({FIXED(273)  ,UO+3600   ,0    ,""    })});// Sep 30
+         case 1966:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(114)  ,UO+7200   ,3600 ,"S"   }),  // Apr 24
+                     ({FIXED(274)  ,UO+3600   ,0    ,""    })});// Oct 1
+         case 1964:
+         case 1967..1976:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(121)  ,UO+7200   ,3600 ,"S"   }),  // May 1
+                     ({FIX_L(274)  ,UO+3600   ,0    ,""    })});// Oct 1
+         case 1977..1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(121)  ,UO+7200   ,3600 ,"S"   }),  // May 1
+                     ({FIXED(244)  ,UO+3600   ,0    ,""    })});// Sep 1
+         case 1983..1984:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(99)   ,UO+7200   ,3600 ,"S"   }),  // Apr 9
+                     ({FIX_L(274)  ,UO+3600   ,0    ,""    })});// Oct 1
+         default: // ..1919:
+         case 1924..1961:
+         case 1979..1982:
+         case 1985:
+            return ({({0           ,0         ,0    ,""    })});
+         case 1986:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(47)   ,UO+7200   ,3600 ,"S"   }),  // Feb 16
+                     ({FIXED(282)  ,UO+3600   ,0    ,""    })});// Oct 9
+         case 1987:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(60)   ,UO+7200   ,3600 ,"S"   }),  // Mar 1
+                     ({FIXED(304)  ,UO+3600   ,0    ,""    })});// Oct 31
+         case 1988:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(75)   ,UO+7200   ,3600 ,"S"   }),  // Mar 15
+                     ({FIXED(305)  ,UO+3600   ,0    ,""    })});// Oct 31
+         case 1989:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(90)   ,UO+7200   ,3600 ,"S"   }),  // Mar 31
+                     ({FIXED(274)  ,UO+3600   ,0    ,""    })});// Oct 1
+         case 1990:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(91)   ,UO+7200   ,3600 ,"S"   }),  // Apr 1
+                     ({FIXED(273)  ,UO+3600   ,0    ,""    })});// Sep 30
+         case 1992:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(99)   ,UO+0      ,3600 ,"S"   }),  // Apr 8
+                     ({FIXED(275)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1993:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(85)   ,UO+0      ,3600 ,"S"   }),  // Mar 26
+                     ({FIXED(268)  ,UO-3600   ,0    ,""    })});// Sep 25
+         case 1997..1998:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (90,1) ,UO+0      ,3600 ,"S"   }),  // Mar lastMon
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1991:
+         case 1994..1996:
+         case 1999..:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(91)   ,UO+0      ,3600 ,"S"   }),  // Apr 1
+                     ({FIX_L(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+      }
+   }
+}
+
+class Aus
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1917:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(1)    ,UO+60     ,3600 ,""    }),  // Jan 1
+                     ({FIXED(84)   ,UO+3600   ,0    ,""    })});// Mar 25
+         case 1942:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(1)    ,UO+7200   ,3600 ,""    }),  // Jan 1
+                     ({FIXED(88)   ,UO+3600   ,0    ,""    }),  // Mar 29
+                     ({FIXED(270)  ,UO+7200   ,3600 ,""    })});// Sep 27
+         case 1943:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (90,7) ,UO+3600   ,0    ,""    }),  // Mar lastSun
+                     ({FIXED(276)  ,UO+7200   ,3600 ,""    })});// Oct 3
+         case 1944:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (91,7) ,UO+3600   ,0    ,""    })});// Mar lastSun
+         default: // ..1916 and 1945..
+         case 1918..1941:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class AQ
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1972:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (60,7) ,UO+7200   ,0    ,""    })});// Feb lastSun
+         case 1971:
+         case 1989:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1990..1991:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (66,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=1
+                     ({LDAY (304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1992:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (67,7) ,UO+7200   ,0    ,""    })});// Mar Sun>=1
+         default: // ..1970 and 1993..
+         case 1973..1988:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Holiday
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1992:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({LDAY (305,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1993:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (66,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=1
+                     ({LDAY (304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1994:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (66,7) ,UO+7200   ,0    ,""    })});// Mar Sun>=1
+         default: // ..1991 and 1995..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class AS
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1970:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1971:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({LDAY (304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1972:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({FIXED(58)   ,UO+7200   ,0    ,""    }),  // Feb 27
+                     ({LDAY (305,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1986:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (80,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=15
+                     ({FIXED(292)  ,UO+7200   ,3600 ,""    })});// Oct 19
+         case 1987..1989:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAYL(80,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=15
+                     ({LDAYL(304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1973..1985:
+         case 1991:
+         case 1993:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAYL(66,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=1
+                     ({LDAYL(304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1990:
+         case 1992:
+         case 1994:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAYL(83,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=18
+                     ({LDAYL(304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1995..:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAYL(90,7) ,UO+7200   ,0    ,""    }),  // Mar lastSun
+                     ({LDAYL(304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+      }
+   }
+}
+
+class AT
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1966:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1967:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({LDAY (280,7),UO+7200   ,3600 ,""    })});// Oct Sun>=1
+         case 1969..1971:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (73,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=8
+                     ({LDAY (304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1972:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (60,7) ,UO+7200   ,0    ,""    }),  // Feb lastSun
+                     ({LDAY (305,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1968:
+         case 1982..1983:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAYL(90,7) ,UO+7200   ,0    ,""    }),  // Mar lastSun
+                     ({LDAYL(304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1973..1981:
+         case 1984..1985:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAYL(66,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=1
+                     ({LDAYL(304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1986:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (66,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=1
+                     ({LDAY (294,7),UO+7200   ,3600 ,""    })});// Oct Sun>=15
+         case 1987:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (80,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=15
+                     ({LDAY (301,7),UO+7200   ,3600 ,""    })});// Oct Sun>=22
+         case 1988..1990:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAYL(80,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=15
+                     ({LDAYL(304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 2000:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (91,7) ,UO+7200   ,0    ,""    }),  // Mar lastSun
+                     ({LDAY (244,7),UO+7200   ,3600 ,""    })});// Aug lastSun
+         case 1991..1999:
+         case 2001..:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAYL(90,7) ,UO+7200   ,0    ,""    }),  // Mar lastSun
+                     ({LDAYL(280,7),UO+7200   ,3600 ,""    })});// Oct Sun>=1
+      }
+   }
+}
+
+class AV
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1970:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1971:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({LDAY (304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1972:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (60,7) ,UO+7200   ,0    ,""    }),  // Feb lastSun
+                     ({LDAY (305,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1986..1987:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (80,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=15
+                     ({LDAY (294,7),UO+7200   ,3600 ,""    })});// Oct Sun>=15
+         case 1988..1990:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAYL(80,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=15
+                     ({LDAYL(304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1973..1985:
+         case 1991..1994:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAYL(66,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=1
+                     ({LDAYL(304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 2000:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (91,7) ,UO+7200   ,0    ,""    }),  // Mar lastSun
+                     ({LDAY (244,7),UO+7200   ,3600 ,""    })});// Aug lastSun
+         case 1995..1999:
+         case 2001..:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAYL(90,7) ,UO+7200   ,0    ,""    }),  // Mar lastSun
+                     ({LDAYL(304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+      }
+   }
+}
+
+class AN
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1970:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1971:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({LDAY (304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1972:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({FIXED(58)   ,UO+7200   ,0    ,""    }),  // Feb 27
+                     ({LDAY (305,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1982:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (97,7) ,UO+7200   ,0    ,""    }),  // Apr Sun>=1
+                     ({LDAY (304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1986:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (80,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=15
+                     ({FIXED(292)  ,UO+7200   ,3600 ,""    })});// Oct 19
+         case 1987..1989:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAYL(80,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=15
+                     ({LDAYL(304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1973..1981:
+         case 1983..1985:
+         case 1990..1995:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAYL(66,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=1
+                     ({LDAYL(304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 2000:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (91,7) ,UO+7200   ,0    ,""    }),  // Mar lastSun
+                     ({LDAY (244,7),UO+7200   ,3600 ,""    })});// Aug lastSun
+         case 1996..1999:
+         case 2001..:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAYL(90,7) ,UO+7200   ,0    ,""    }),  // Mar lastSun
+                     ({LDAYL(304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+      }
+   }
+}
+
+class LH
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1980:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1981:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({LDAY (304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1982..1984:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAYL(66,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=1
+                     ({LDAYL(304,7),UO+7200   ,3600 ,""    })});// Oct lastSun
+         case 1985:
+            return ({({0           ,0         ,3600 ,""    }),  
+                     ({LDAY (66,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=1
+                     ({LDAY (304,7),UO+7200   ,1800 ,""    })});// Oct lastSun
+         case 1986:
+            return ({({0           ,0         ,1800 ,""    }),  
+                     ({LDAY (80,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=15
+                     ({FIXED(292)  ,UO+7200   ,1800 ,""    })});// Oct 19
+         case 1987..1989:
+            return ({({0           ,0         ,1800 ,""    }),  
+                     ({LDAYL(80,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=15
+                     ({LDAYL(304,7),UO+7200   ,1800 ,""    })});// Oct lastSun
+         case 1990..1995:
+            return ({({0           ,0         ,1800 ,""    }),  
+                     ({LDAYL(66,7) ,UO+7200   ,0    ,""    }),  // Mar Sun>=1
+                     ({LDAYL(304,7),UO+7200   ,1800 ,""    })});// Oct lastSun
+         case 2000:
+            return ({({0           ,0         ,1800 ,""    }),  
+                     ({LDAY (91,7) ,UO+7200   ,0    ,""    }),  // Mar lastSun
+                     ({LDAY (244,7),UO+7200   ,1800 ,""    })});// Aug lastSun
+         case 1996..1999:
+         case 2001..:
+            return ({({0           ,0         ,1800 ,""    }),  
+                     ({LDAYL(90,7) ,UO+7200   ,0    ,""    }),  // Mar lastSun
+                     ({LDAYL(304,7),UO+7200   ,1800 ,""    })});// Oct lastSun
+      }
+   }
+}
+
+class Cook
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(316)  ,UO+0      ,1800 ,"HS"  })});// Nov 12
+         case 1979..1990:
+            return ({({0           ,0         ,1800 ,"HS"  }),  
+                     ({LDAYL(66,7) ,UO-1800   ,0    ,""    }),  // Mar Sun>=1
+                     ({LDAYL(304,7),UO+0      ,1800 ,"HS"  })});// Oct lastSun
+         case 1991:
+            return ({({0           ,0         ,1800 ,"HS"  }),  
+                     ({LDAY (66,7) ,UO-1800   ,0    ,""    })});// Mar Sun>=1
+         default: // ..1977 and 1992..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Fiji
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1997:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1998:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({LDAY (311,7),UO+7200   ,3600 ,"S"   })});// Nov Sun>=1
+         case 1999..:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAYL(59,7) ,UO+7200   ,0    ,""    }),  // Feb lastSun
+                     ({LDAYL(311,7),UO+7200   ,3600 ,"S"   })});// Nov Sun>=1
+      }
+   }
+}
+
+class NC
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1977:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({LDAY (341,7),UO+0      ,3600 ,"S"   })});// Dec Sun>=1
+         case 1978:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(58)   ,UO-3600   ,0    ,""    }),  // Feb 27
+                     ({LDAY (341,7),UO+0      ,3600 ,"S"   })});// Dec Sun>=1
+         case 1979:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(58)   ,UO-3600   ,0    ,""    })});// Feb 27
+         case 1996:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(336)  ,UO+7200   ,3600 ,"S"   })});// Dec 1
+         case 1997:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(61)   ,UO+7200   ,0    ,""    })});// Mar 2
+         default: // ..1976 and 1998..
+         case 1980..1995:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class NZ
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1927:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(330)  ,UO+7200   ,1800 ,"HD"  })});// Nov 26
+         case 1928:
+            return ({({0           ,0         ,1800 ,"HD"  }),  
+                     ({LDAY (67,7) ,UO+5400   ,0    ,"S"   }),  // Mar Sun>=1
+                     ({FIXED(309)  ,UO+7200   ,1800 ,"HD"  })});// Nov 4
+         case 1929:
+            return ({({0           ,0         ,1800 ,"HD"  }),  
+                     ({LDAY (66,7) ,UO+5400   ,0    ,"S"   }),  // Mar Sun>=1
+                     ({FIXED(303)  ,UO+7200   ,1800 ,"HD"  })});// Oct 30
+         case 1930..1933:
+            return ({({0           ,0         ,1800 ,"HD"  }),  
+                     ({LDAYL(80,7) ,UO+5400   ,0    ,"S"   }),  // Mar Sun>=15
+                     ({LDAYL(287,7),UO+7200   ,1800 ,"HD"  })});// Oct Sun>=8
+         case 1934..1939:
+            return ({({0           ,0         ,1800 ,"HD"  }),  
+                     ({LDAYL(120,7),UO+5400   ,0    ,"S"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+7200   ,1800 ,"HD"  })});// Sep lastSun
+         case 1940:
+            return ({({0           ,0         ,1800 ,"HD"  }),  
+                     ({LDAY (121,7),UO+5400   ,0    ,"S"   })});// Apr lastSun
+         default: // ..1926:
+         case 1941..1973:
+            return ({({0           ,0         ,0    ,"S"   })});
+         case 1974:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(307)  ,UO+7200   ,3600 ,"D"   })});// Nov 3
+         case 1975:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({FIXED(54)   ,UO+7200   ,0    ,"S"   }),  // Feb 23
+                     ({LDAY (304,7),UO+7200   ,3600 ,"D"   })});// Oct lastSun
+         case 1976..1988:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({LDAYL(66,7) ,UO+7200   ,0    ,"S"   }),  // Mar Sun>=1
+                     ({LDAYL(304,7),UO+7200   ,3600 ,"D"   })});// Oct lastSun
+         case 1989:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({LDAY (66,7) ,UO+7200   ,0    ,"S"   }),  // Mar Sun>=1
+                     ({FIXED(281)  ,UO+7200   ,3600 ,"D"   })});// Oct 8
+         case 1990..:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({LDAYL(80,7) ,UO+7200   ,0    ,"S"   }),  // Mar Sun>=15
+                     ({LDAYL(280,7),UO+7200   ,3600 ,"D"   })});// Oct Sun>=1
+      }
+   }
+}
+
+class Chatham
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1989:
+            return ({({0           ,0         ,0    ,"S"   })});// ?
+         case 1990:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({LDAY (280,7),UO+9900   ,3600 ,"D"   })});// Oct Sun>=1
+         case 1991..:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({LDAYL(80,7) ,UO+9900   ,0    ,"S"   }),  // Mar Sun>=15
+                     ({LDAYL(280,7),UO+9900   ,3600 ,"D"   })});// Oct Sun>=1
+      }
+   }
+}
+
+class Tonga
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1998:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1999:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({LDAY (280,6),UO+7200   ,3600 ,"S"   })});// Oct Sat>=1
+         case 2000..:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAYL(112,7),UO+7200   ,0    ,""    }),  // Apr Sun>=16
+                     ({LDAYL(280,6),UO+7200   ,3600 ,"S"   })});// Oct Sat>=1
+      }
+   }
+}
+
+class Vanuatu
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1983:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(268)  ,UO+0      ,3600 ,"S"   })});// Sep 25
+         case 1984:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (89,7) ,UO-3600   ,0    ,""    }),  // Mar Sun>=23
+                     ({FIXED(297)  ,UO+0      ,3600 ,"S"   })});// Oct 23
+         case 1985..1991:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAYL(88,7) ,UO-3600   ,0    ,""    }),  // Mar Sun>=23
+                     ({LDAYL(272,7),UO+0      ,3600 ,"S"   })});// Sep Sun>=23
+         case 1992:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (29,7) ,UO-3600   ,0    ,""    }),  // Jan Sun>=23
+                     ({LDAY (303,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=23
+         case 1993:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (29,7) ,UO-3600   ,0    ,""    })});// Jan Sun>=23
+         default: // ..1982 and 1994..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class GB_Eire
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1916:
+            return ({({0           ,0         ,0    ,"GMT" }),  // ?
+                     ({FIXED(142)  ,UO+7200   ,3600 ,"BST" }),  // May 21
+                     ({FIXED(275)  ,UO+7200   ,0    ,"GMT" })});// Oct 1
+         case 1917:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({FIXED(98)   ,UO+7200   ,3600 ,"BST" }),  // Apr 8
+                     ({FIXED(260)  ,UO+7200   ,0    ,"GMT" })});// Sep 17
+         case 1918:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({FIXED(83)   ,UO+7200   ,3600 ,"BST" }),  // Mar 24
+                     ({FIXED(273)  ,UO+7200   ,0    ,"GMT" })});// Sep 30
+         case 1919:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({FIXED(89)   ,UO+7200   ,3600 ,"BST" }),  // Mar 30
+                     ({FIXED(272)  ,UO+7200   ,0    ,"GMT" })});// Sep 29
+         case 1920:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({FIXED(88)   ,UO+7200   ,3600 ,"BST" }),  // Mar 28
+                     ({FIXED(299)  ,UO+7200   ,0    ,"GMT" })});// Oct 25
+         case 1921:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({FIXED(93)   ,UO+7200   ,3600 ,"BST" }),  // Apr 3
+                     ({FIXED(276)  ,UO+7200   ,0    ,"GMT" })});// Oct 3
+         case 1922:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({FIXED(85)   ,UO+7200   ,3600 ,"BST" }),  // Mar 26
+                     ({FIXED(281)  ,UO+7200   ,0    ,"GMT" })});// Oct 8
+         case 1923:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({LDAY (112,7),UO+7200   ,3600 ,"BST" }),  // Apr Sun>=16
+                     ({LDAY (265,7),UO+7200   ,0    ,"GMT" })});// Sep Sun>=16
+         case 1924:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({LDAY (106,7),UO+7200   ,3600 ,"BST" }),  // Apr Sun>=9
+                     ({LDAY (266,7),UO+7200   ,0    ,"GMT" })});// Sep Sun>=16
+         case 1939:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({LDAY (112,7),UO+7200   ,3600 ,"BST" }),  // Apr Sun>=16
+                     ({LDAY (326,7),UO+7200   ,0    ,"GMT" })});// Nov Sun>=16
+         case 1940:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({LDAY (61,7) ,UO+7200   ,3600 ,"BST" })});// Feb Sun>=23
+         case 1941:
+            return ({({0           ,0         ,3600 ,"BST" }),  
+                     ({LDAY (128,7),UO+3600   ,7200 ,"BDST"}),  // May Sun>=2
+                     ({LDAY (227,7),UO+3600   ,3600 ,"BST" })});// Aug Sun>=9
+         case 1942..1943:
+            return ({({0           ,0         ,3600 ,"BST" }),  
+                     ({LDAY (98,7) ,UO+3600   ,7200 ,"BDST"}),  // Apr Sun>=2
+                     ({LDAY (227,7),UO+3600   ,3600 ,"BST" })});// Aug Sun>=9
+         case 1944:
+            return ({({0           ,0         ,3600 ,"BST" }),  
+                     ({LDAY (99,7) ,UO+3600   ,7200 ,"BDST"}),  // Apr Sun>=2
+                     ({LDAY (266,7),UO+3600   ,3600 ,"BST" })});// Sep Sun>=16
+         case 1945:
+            return ({({0           ,0         ,3600 ,"BST" }),  
+                     ({LDAY (98,1) ,UO+3600   ,7200 ,"BDST"}),  // Apr Mon>=2
+                     ({LDAY (196,7),UO+3600   ,3600 ,"BST" }),  // Jul Sun>=9
+                     ({LDAY (281,7),UO+7200   ,0    ,"GMT" })});// Oct Sun>=2
+         case 1947:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({FIXED(75)   ,UO+7200   ,3600 ,"BST" }),  // Mar 16
+                     ({FIXED(103)  ,UO+3600   ,7200 ,"BDST"}),  // Apr 13
+                     ({FIXED(222)  ,UO+3600   ,3600 ,"BST" }),  // Aug 10
+                     ({FIXED(306)  ,UO+7200   ,0    ,"GMT" })});// Nov 2
+         case 1948:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({FIXED(74)   ,UO+7200   ,3600 ,"BST" }),  // Mar 14
+                     ({FIXED(305)  ,UO+7200   ,0    ,"GMT" })});// Oct 31
+         case 1949:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({FIXED(93)   ,UO+7200   ,3600 ,"BST" }),  // Apr 3
+                     ({FIXED(303)  ,UO+7200   ,0    ,"GMT" })});// Oct 30
+         case 1950..1952:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({LDAYL(110,7),UO+7200   ,3600 ,"BST" }),  // Apr Sun>=14
+                     ({LDAYL(300,7),UO+7200   ,0    ,"GMT" })});// Oct Sun>=21
+         case 1925..1926:
+         case 1928..1929:
+         case 1931..1932:
+         case 1934:
+         case 1936..1937:
+         case 1953:
+         case 1955..1956:
+         case 1958..1959:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({LDAYL(112,7),UO+7200   ,3600 ,"BST" }),  // Apr Sun>=16
+                     ({LDAYL(281,7),UO+7200   ,0    ,"GMT" })});// Oct Sun>=2
+         case 1927:
+         case 1930:
+         case 1933:
+         case 1935:
+         case 1938:
+         case 1946:
+         case 1954:
+         case 1957:
+         case 1960:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({LDAYL(105,7),UO+7200   ,3600 ,"BST" }),  // Apr Sun>=9
+                     ({LDAYL(281,7),UO+7200   ,0    ,"GMT" })});// Oct Sun>=2
+         case 1961..1963:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({LDAY (90,7) ,UO+7200   ,3600 ,"BST" }),  // Mar lastSun
+                     ({LDAY (302,7),UO+7200   ,0    ,"GMT" })});// Oct Sun>=23
+         case 1964..1967:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({LDAYL(84,7) ,UO+7200   ,3600 ,"BST" }),  // Mar Sun>=19
+                     ({LDAYL(302,7),UO+7200   ,0    ,"GMT" })});// Oct Sun>=23
+         case 1968:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({FIXED(49)   ,UO+7200   ,3600 ,"BST" }),  // Feb 18
+                     ({LDAY (303,7),UO+7200   ,0    ,"GMT" })});// Oct Sun>=23
+         case 1972..1980:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({LDAYL(81,7) ,UO+7200   ,3600 ,"BST" }),  // Mar Sun>=16
+                     ({LDAYL(302,7),UO+7200   ,0    ,"GMT" })});// Oct Sun>=23
+         case 1981..1989:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({LDAYL(90,7) ,3600      ,3600 ,"BST" }),  // Mar lastSun
+                     ({LDAYL(302,7),3600      ,0    ,"GMT" })});// Oct Sun>=23
+         case 1990..1995:
+            return ({({0           ,0         ,0    ,"GMT" }),  
+                     ({LDAYL(90,7) ,3600      ,3600 ,"BST" }),  // Mar lastSun
+                     ({LDAYL(301,7),3600      ,0    ,"GMT" })});// Oct Sun>=22
+         default: // ..1915 and 1996..
+         case 1969..1971:
+            return ({({0           ,0         ,0    ,"GMT" })});
+      }
+   }
+}
+
+class EU
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1976:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,3600      ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({FIXED(274)  ,3600      ,0    ,""    })});// Oct 1
+         case 1977:
+         case 1979..1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(97,7) ,3600      ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({LDAYL(273,7),3600      ,0    ,""    })});// Sep lastSun
+         case 1981..1995:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,3600      ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(273,7),3600      ,0    ,""    })});// Sep lastSun
+         case 1996..:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,3600      ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(304,7),3600      ,0    ,""    })});// Oct lastSun
+      }
+   }
+}
+
+class W_Eur
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1976:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+3600   ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({FIXED(274)  ,UO+3600   ,0    ,""    })});// Oct 1
+         case 1977:
+         case 1979..1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(97,7) ,UO+3600   ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({LDAYL(273,7),UO+3600   ,0    ,""    })});// Sep lastSun
+         case 1981..1995:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+3600   ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,""    })});// Sep lastSun
+         case 1996..:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+3600   ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,""    })});// Oct lastSun
+      }
+   }
+}
+
+class C_Eur
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1916:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(121)  ,UO+82800  ,3600 ,"S"   }),  // Apr 30
+                     ({FIXED(275)  ,UO+0      ,0    ,""    })});// Oct 1
+         case 1917..1918:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (111,1),UO+7200   ,3600 ,"S"   }),  // Apr Mon>=15
+                     ({LDAY (264,1),UO+7200   ,0    ,""    })});// Sep Mon>=15
+         case 1940:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(92)   ,UO+7200   ,3600 ,"S"   })});// Apr 1
+         case 1941:
+            return ({({0           ,0         ,3600 ,"S"   })});
+         case 1942:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(306)  ,UO+7200   ,0    ,""    })});// Nov 2
+         case 1943:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(88)   ,UO+7200   ,3600 ,"S"   }),  // Mar 29
+                     ({FIXED(277)  ,UO+7200   ,0    ,""    })});// Oct 4
+         case 1944:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(94)   ,UO+7200   ,3600 ,"S"   }),  // Apr 3
+                     ({FIXED(276)  ,UO+7200   ,0    ,""    })});// Oct 2
+         default: // ..1915:
+         case 1919..1939:
+         case 1945..1976:
+            return ({({0           ,0         ,0    ,""    })});
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+7200   ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({FIXED(274)  ,UO+7200   ,0    ,""    })});// Oct 1
+         case 1977:
+         case 1979..1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(97,7) ,UO+7200   ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({LDAYL(273,7),UO+7200   ,0    ,""    })});// Sep lastSun
+         case 1981..1995:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+7200   ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(273,7),UO+7200   ,0    ,""    })});// Sep lastSun
+         case 1996..:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+7200   ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(304,7),UO+7200   ,0    ,""    })});// Oct lastSun
+      }
+   }
+}
+
+class E_Eur
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1976:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+0      ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1977:
+         case 1979..1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(97,7) ,UO+0      ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({LDAYL(273,7),UO-3600   ,0    ,""    })});// Sep lastSun
+         case 1981..1995:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+0      ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(273,7),UO-3600   ,0    ,""    })});// Sep lastSun
+         case 1996..:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+0      ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(304,7),UO-3600   ,0    ,""    })});// Oct lastSun
+      }
+   }
+}
+
+class Russia
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1916:
+            return ({({0           ,0         ,0    ,"MMT" })});// ?
+         case 1917:
+            return ({({0           ,0         ,0    ,"MMT" }),  // ?
+                     ({FIXED(182)  ,UO+82800  ,3600 ,"MST" }),  // Jul 1
+                     ({FIXED(362)  ,UO-3600   ,0    ,"MMT" })});// Dec 28
+         case 1918:
+            return ({({0           ,0         ,0    ,"MMT" }),  
+                     ({FIXED(151)  ,UO+79200  ,7200 ,"MDST"}),  // May 31
+                     ({FIXED(259)  ,UO-3600   ,3600 ,"MST" })});// Sep 16
+         case 1919:
+            return ({({0           ,0         ,3600 ,"MST" }),  
+                     ({FIXED(151)  ,UO+79200  ,7200 ,"MDST"}),  // May 31
+                     ({FIXED(182)  ,UO+0      ,3600 ,"S"   }),  // Jul 1
+                     ({FIXED(228)  ,UO-3600   ,0    ,""    })});// Aug 16
+         case 1921:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(45)   ,UO+82800  ,3600 ,"S"   }),  // Feb 14
+                     ({FIXED(79)   ,UO+79200  ,7200 ,"M"   }),  // Mar 20
+                     ({FIXED(244)  ,UO-7200   ,3600 ,"S"   }),  // Sep 1
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1920:
+         case 1922..1980:
+            return ({({0           ,0         ,0    ,""    })});
+         case 1981..1983:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(91)   ,UO+0      ,3600 ,"S"   }),  // Apr 1
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1984:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(92)   ,UO+0      ,3600 ,"S"   }),  // Apr 1
+                     ({LDAY (274,7),UO+7200   ,0    ,""    })});// Sep lastSun
+         case 1992:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (91,6) ,UO+82800  ,3600 ,"S"   }),  // Mar lastSat
+                     ({LDAY (274,6),UO+79200  ,0    ,""    })});// Sep lastSat
+         case 1985..1991:
+         case 1993..1995:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+7200   ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(273,7),UO+7200   ,0    ,""    })});// Sep lastSun
+         case 1996..:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+7200   ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(304,7),UO+7200   ,0    ,""    })});// Oct lastSun
+      }
+   }
+}
+
+class Albania
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1940:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(168)  ,UO+0      ,3600 ,"S"   })});// Jun 16
+         case 1942:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(306)  ,UO+7200   ,0    ,""    })});// Nov 2
+         case 1943:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(88)   ,UO+7200   ,3600 ,"S"   }),  // Mar 29
+                     ({FIXED(100)  ,UO+7200   ,0    ,""    })});// Apr 10
+         default: // ..1939:
+         case 1944..1973:
+            return ({({0           ,0         ,0    ,""    })});
+         case 1974:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(124)  ,UO+0      ,3600 ,"S"   }),  // May 4
+                     ({FIXED(275)  ,UO-3600   ,0    ,""    })});// Oct 2
+         case 1975:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(121)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({FIXED(275)  ,UO-3600   ,0    ,""    })});// Oct 2
+         case 1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(128)  ,UO+0      ,3600 ,"S"   }),  // May 8
+                     ({FIXED(275)  ,UO-3600   ,0    ,""    })});// Oct 2
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(126)  ,UO+0      ,3600 ,"S"   }),  // May 6
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1979:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(125)  ,UO+0      ,3600 ,"S"   }),  // May 5
+                     ({FIXED(273)  ,UO-3600   ,0    ,""    })});// Sep 30
+         case 1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(124)  ,UO+0      ,3600 ,"S"   }),  // May 3
+                     ({FIXED(278)  ,UO-3600   ,0    ,""    })});// Oct 4
+         case 1981:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(116)  ,UO+0      ,3600 ,"S"   }),  // Apr 26
+                     ({FIXED(270)  ,UO-3600   ,0    ,""    })});// Sep 27
+         case 1976:
+         case 1982:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(122)  ,UO+0      ,3600 ,"S"   }),  // May 2
+                     ({FIX_L(276)  ,UO-3600   ,0    ,""    })});// Oct 3
+         case 1983:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(108)  ,UO+0      ,3600 ,"S"   }),  // Apr 18
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1984:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(92)   ,UO+0      ,3600 ,"S"   })});// Apr 1
+         case 1941:
+         case 1985..:
+            return ({({0           ,0         ,3600 ,"S"   })});
+      }
+   }
+}
+
+class Austria
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1920:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(96)   ,UO+7200   ,3600 ,"S"   }),  // Apr 5
+                     ({FIXED(257)  ,UO+7200   ,0    ,""    })});// Sep 13
+         case 1945:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(92)   ,UO+7200   ,3600 ,"S"   }),  // Apr 2
+                     ({FIXED(322)  ,UO+7200   ,0    ,""    })});// Nov 18
+         case 1946:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(104)  ,UO+7200   ,3600 ,"S"   }),  // Apr 14
+                     ({LDAY (280,7),UO+7200   ,0    ,""    })});// Oct Sun>=1
+         case 1947:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(96)   ,UO+7200   ,3600 ,"S"   }),  // Apr 6
+                     ({LDAY (280,7),UO+7200   ,0    ,""    })});// Oct Sun>=1
+         case 1948:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(109)  ,UO+7200   ,3600 ,"S"   }),  // Apr 18
+                     ({LDAY (281,7),UO+7200   ,0    ,""    })});// Oct Sun>=1
+         default: // ..1919 and 1949..
+         case 1921..1944:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Belgium
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1918:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(68)   ,UO+0      ,3600 ,"S"   }),  // Mar 9
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1919:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(60)   ,UO+82800  ,3600 ,"S"   }),  // Mar 1
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1920:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(45)   ,UO+82800  ,3600 ,"S"   }),  // Feb 14
+                     ({FIXED(297)  ,UO+82800  ,0    ,""    })});// Oct 23
+         case 1921:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(73)   ,UO+82800  ,3600 ,"S"   }),  // Mar 14
+                     ({FIXED(298)  ,UO+82800  ,0    ,""    })});// Oct 25
+         case 1922:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(84)   ,UO+82800  ,3600 ,"S"   }),  // Mar 25
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1923:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(111)  ,UO+82800  ,3600 ,"S"   }),  // Apr 21
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1924:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(89)   ,UO+82800  ,3600 ,"S"   }),  // Mar 29
+                     ({LDAY (281,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1925:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(94)   ,UO+82800  ,3600 ,"S"   }),  // Apr 4
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1926:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(107)  ,UO+82800  ,3600 ,"S"   }),  // Apr 17
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1927:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(99)   ,UO+82800  ,3600 ,"S"   }),  // Apr 9
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1928:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(105)  ,UO+82800  ,3600 ,"S"   }),  // Apr 14
+                     ({LDAY (282,7),UO+7200   ,0    ,""    })});// Oct Sun>=2
+         case 1929:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(111)  ,UO+7200   ,3600 ,"S"   }),  // Apr 21
+                     ({LDAY (281,7),UO+7200   ,0    ,""    })});// Oct Sun>=2
+         case 1930:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(103)  ,UO+7200   ,3600 ,"S"   }),  // Apr 13
+                     ({LDAY (281,7),UO+7200   ,0    ,""    })});// Oct Sun>=2
+         case 1932:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(94)   ,UO+7200   ,3600 ,"S"   }),  // Apr 3
+                     ({LDAY (282,7),UO+7200   ,0    ,""    })});// Oct Sun>=2
+         case 1933:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(85)   ,UO+7200   ,3600 ,"S"   }),  // Mar 26
+                     ({LDAY (281,7),UO+7200   ,0    ,""    })});// Oct Sun>=2
+         case 1934:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(98)   ,UO+7200   ,3600 ,"S"   }),  // Apr 8
+                     ({LDAY (281,7),UO+7200   ,0    ,""    })});// Oct Sun>=2
+         case 1935:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(90)   ,UO+7200   ,3600 ,"S"   }),  // Mar 31
+                     ({LDAY (281,7),UO+7200   ,0    ,""    })});// Oct Sun>=2
+         case 1931:
+         case 1936:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(109)  ,UO+7200   ,3600 ,"S"   }),  // Apr 19
+                     ({LDAYL(281,7),UO+7200   ,0    ,""    })});// Oct Sun>=2
+         case 1937:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(94)   ,UO+7200   ,3600 ,"S"   }),  // Apr 4
+                     ({LDAY (281,7),UO+7200   ,0    ,""    })});// Oct Sun>=2
+         case 1938:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(86)   ,UO+7200   ,3600 ,"S"   }),  // Mar 27
+                     ({LDAY (281,7),UO+7200   ,0    ,""    })});// Oct Sun>=2
+         case 1939:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(106)  ,UO+7200   ,3600 ,"S"   }),  // Apr 16
+                     ({FIXED(323)  ,UO+7200   ,0    ,""    })});// Nov 19
+         case 1940:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(56)   ,UO+7200   ,3600 ,"S"   })});// Feb 25
+         case 1941..1943:
+            return ({({0           ,0         ,3600 ,"S"   })});
+         case 1944:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(261)  ,UO+7200   ,0    ,""    })});// Sep 17
+         case 1945:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(92)   ,UO+7200   ,3600 ,"S"   }),  // Apr 2
+                     ({FIXED(259)  ,UO+7200   ,0    ,""    })});// Sep 16
+         case 1946:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(139)  ,UO+7200   ,3600 ,"S"   }),  // May 19
+                     ({FIXED(280)  ,UO+7200   ,0    ,""    })});// Oct 7
+         default: // ..1917 and 1947..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Bulg
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1978:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1979:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(90)   ,UO+82800  ,3600 ,"S"   }),  // Mar 31
+                     ({FIXED(274)  ,UO+0      ,0    ,""    })});// Oct 1
+         case 1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (98,6) ,UO+82800  ,3600 ,"S"   }),  // Apr Sat<=7
+                     ({FIXED(273)  ,UO+0      ,0    ,""    })});// Sep 29
+         case 1981:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,6) ,UO+82800  ,3600 ,"S"   }),  // Apr Sat<=7
+                     ({FIXED(270)  ,UO+3600   ,0    ,""    })});// Sep 27
+         case 1982:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,6) ,UO+82800  ,3600 ,"S"   })});// Apr Sat<=7
+         case 1983..:
+            return ({({0           ,0         ,3600 ,"S"   })});
+      }
+   }
+}
+
+class Czech
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1945:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(98)   ,UO+7200   ,3600 ,"S"   }),  // Apr 8
+                     ({FIXED(322)  ,UO+7200   ,0    ,""    })});// Nov 18
+         case 1946:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(126)  ,UO+7200   ,3600 ,"S"   }),  // May 6
+                     ({LDAY (280,7),UO+7200   ,0    ,""    })});// Oct Sun>=1
+         case 1947:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(110)  ,UO+7200   ,3600 ,"S"   }),  // Apr 20
+                     ({LDAY (280,7),UO+7200   ,0    ,""    })});// Oct Sun>=1
+         case 1948:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(109)  ,UO+7200   ,3600 ,"S"   }),  // Apr 18
+                     ({LDAY (281,7),UO+7200   ,0    ,""    })});// Oct Sun>=1
+         case 1949:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(99)   ,UO+7200   ,3600 ,"S"   }),  // Apr 9
+                     ({LDAY (280,7),UO+7200   ,0    ,""    })});// Oct Sun>=1
+         default: // ..1944 and 1950..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Denmark
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1916:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(135)  ,UO+82800  ,3600 ,"S"   }),  // May 14
+                     ({FIXED(274)  ,UO+79200  ,0    ,""    })});// Sep 30
+         case 1940:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(136)  ,UO+0      ,3600 ,"S"   })});// May 15
+         case 1941..1944:
+            return ({({0           ,0         ,3600 ,"S"   })});
+         case 1945:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(92)   ,UO+7200   ,3600 ,"S"   }),  // Apr 2
+                     ({FIXED(227)  ,UO+7200   ,0    ,""    })});// Aug 15
+         case 1946:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(121)  ,UO+7200   ,3600 ,"S"   }),  // May 1
+                     ({FIXED(244)  ,UO+7200   ,0    ,""    })});// Sep 1
+         case 1947:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(124)  ,UO+7200   ,3600 ,"S"   }),  // May 4
+                     ({FIXED(222)  ,UO+7200   ,0    ,""    })});// Aug 10
+         case 1948:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(130)  ,UO+7200   ,3600 ,"S"   }),  // May 9
+                     ({FIXED(221)  ,UO+7200   ,0    ,""    })});// Aug 8
+         default: // ..1915 and 1949..
+         case 1917..1939:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Thule
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1992:
+            return ({({0           ,0         ,0    ,"S"   })});// ?
+         case 1993..:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+7200   ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+      }
+   }
+}
+
+class Finland
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1942:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(93)   ,UO+0      ,3600 ,"S"   }),  // Apr 3
+                     ({FIXED(276)  ,UO-3600   ,0    ,""    })});// Oct 3
+         default: // ..1941 and 1943..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class France
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1916:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(166)  ,UO+82800  ,3600 ,"S"   }),  // Jun 14
+                     ({LDAY (281,7),UO+82800  ,0    ,""    })});// Oct Sun>=1
+         case 1917:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(83)   ,UO+82800  ,3600 ,"S"   }),  // Mar 24
+                     ({LDAY (280,7),UO+82800  ,0    ,""    })});// Oct Sun>=1
+         case 1918:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(68)   ,UO+82800  ,3600 ,"S"   }),  // Mar 9
+                     ({LDAY (280,7),UO+82800  ,0    ,""    })});// Oct Sun>=1
+         case 1919:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(60)   ,UO+82800  ,3600 ,"S"   }),  // Mar 1
+                     ({LDAY (280,7),UO+82800  ,0    ,""    })});// Oct Sun>=1
+         case 1920:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(45)   ,UO+82800  ,3600 ,"S"   }),  // Feb 14
+                     ({FIXED(297)  ,UO+82800  ,0    ,""    })});// Oct 23
+         case 1921:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(73)   ,UO+82800  ,3600 ,"S"   }),  // Mar 14
+                     ({FIXED(298)  ,UO+82800  ,0    ,""    })});// Oct 25
+         case 1923:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(146)  ,UO+82800  ,3600 ,"S"   }),  // May 26
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1924:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(89)   ,UO+82800  ,3600 ,"S"   }),  // Mar 29
+                     ({LDAY (281,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1925:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(94)   ,UO+82800  ,3600 ,"S"   }),  // Apr 4
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1926:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(107)  ,UO+82800  ,3600 ,"S"   }),  // Apr 17
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1927:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(99)   ,UO+82800  ,3600 ,"S"   }),  // Apr 9
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1928:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(105)  ,UO+82800  ,3600 ,"S"   }),  // Apr 14
+                     ({LDAY (281,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1929:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(110)  ,UO+82800  ,3600 ,"S"   }),  // Apr 20
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1930:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(102)  ,UO+82800  ,3600 ,"S"   }),  // Apr 12
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1932:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(93)   ,UO+82800  ,3600 ,"S"   }),  // Apr 2
+                     ({LDAY (281,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1922:
+         case 1933:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(84)   ,UO+82800  ,3600 ,"S"   }),  // Mar 25
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1934:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(97)   ,UO+82800  ,3600 ,"S"   }),  // Apr 7
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1935:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(89)   ,UO+82800  ,3600 ,"S"   }),  // Mar 30
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1931:
+         case 1936:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(108)  ,UO+82800  ,3600 ,"S"   }),  // Apr 18
+                     ({LDAYL(280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1937:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(93)   ,UO+82800  ,3600 ,"S"   }),  // Apr 3
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1938:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(85)   ,UO+82800  ,3600 ,"S"   }),  // Mar 26
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1939:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(105)  ,UO+82800  ,3600 ,"S"   }),  // Apr 15
+                     ({FIXED(322)  ,UO+82800  ,0    ,""    })});// Nov 18
+         case 1940:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(56)   ,UO+7200   ,3600 ,"S"   })});// Feb 25
+         case 1941:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(125)  ,UO-3600   ,7200 ,"M"   }),  // May 5
+                     ({FIXED(279)  ,UO-7200   ,3600 ,"S"   })});// Oct 6
+         case 1942:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(68)   ,UO-3600   ,7200 ,"M"   }),  // Mar 9
+                     ({FIXED(306)  ,UO+3600   ,3600 ,"S"   })});// Nov 2
+         case 1943:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(88)   ,UO+3600   ,7200 ,"M"   }),  // Mar 29
+                     ({FIXED(277)  ,UO+3600   ,3600 ,"S"   })});// Oct 4
+         case 1944:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(94)   ,UO+3600   ,7200 ,"M"   }),  // Apr 3
+                     ({FIXED(282)  ,UO-3600   ,3600 ,"S"   })});// Oct 8
+         case 1945:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(92)   ,UO+3600   ,7200 ,"M"   }),  // Apr 2
+                     ({FIXED(259)  ,UO+3600   ,0    ,""    })});// Sep 16
+         case 1976:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(88)   ,UO+3600   ,3600 ,"S"   }),  // Mar 28
+                     ({FIXED(270)  ,UO+0      ,0    ,""    })});// Sep 26
+         default: // ..1915 and 1977..
+         case 1946..1975:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Germany
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1945:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(92)   ,UO+7200   ,3600 ,"S"   }),  // Apr 2
+                     ({FIXED(151)  ,UO+7200   ,7200 ,"M"   }),  // May 31
+                     ({FIXED(266)  ,UO+3600   ,3600 ,"S"   }),  // Sep 23
+                     ({FIXED(322)  ,UO+7200   ,0    ,""    })});// Nov 18
+         case 1946:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(104)  ,UO+7200   ,3600 ,"S"   }),  // Apr 14
+                     ({FIXED(280)  ,UO+7200   ,0    ,""    })});// Oct 7
+         case 1947:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(96)   ,UO+7200   ,3600 ,"S"   }),  // Apr 6
+                     ({FIXED(131)  ,UO+7200   ,7200 ,"M"   }),  // May 11
+                     ({FIXED(180)  ,UO+3600   ,3600 ,"S"   }),  // Jun 29
+                     ({LDAY (280,7),UO+7200   ,0    ,""    })});// Oct Sun>=1
+         case 1948:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(109)  ,UO+7200   ,3600 ,"S"   }),  // Apr 18
+                     ({LDAY (281,7),UO+7200   ,0    ,""    })});// Oct Sun>=1
+         case 1949:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(100)  ,UO+7200   ,3600 ,"S"   }),  // Apr 10
+                     ({LDAY (280,7),UO+7200   ,0    ,""    })});// Oct Sun>=1
+         default: // ..1944 and 1950..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Greece
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1932:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(189)  ,UO+0      ,3600 ,"S"   }),  // Jul 7
+                     ({FIXED(245)  ,UO-3600   ,0    ,""    })});// Sep 1
+         case 1941:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(97)   ,UO+0      ,3600 ,"S"   })});// Apr 7
+         case 1942:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(306)  ,UO+7200   ,0    ,""    })});// Nov 2
+         case 1943:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(89)   ,UO+0      ,3600 ,"S"   }),  // Mar 30
+                     ({FIXED(277)  ,UO-3600   ,0    ,""    })});// Oct 4
+         case 1952:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(183)  ,UO+0      ,3600 ,"S"   }),  // Jul 1
+                     ({FIXED(307)  ,UO-3600   ,0    ,""    })});// Nov 2
+         case 1975:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(102)  ,UO+0      ,3600 ,"S"   }),  // Apr 12
+                     ({FIXED(330)  ,UO+0      ,0    ,""    })});// Nov 26
+         case 1976:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(102)  ,UO+7200   ,3600 ,"S"   }),  // Apr 11
+                     ({FIXED(284)  ,UO+7200   ,0    ,""    })});// Oct 10
+         case 1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+7200   ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({FIXED(269)  ,UO+7200   ,0    ,""    })});// Sep 26
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+7200   ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({FIXED(267)  ,UO+10800  ,0    ,""    })});// Sep 24
+         case 1979:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(91)   ,UO+32400  ,3600 ,"S"   }),  // Apr 1
+                     ({FIXED(272)  ,UO+3600   ,0    ,""    })});// Sep 29
+         case 1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(92)   ,UO+0      ,3600 ,"S"   }),  // Apr 1
+                     ({FIXED(272)  ,UO-3600   ,0    ,""    })});// Sep 28
+         default: // ..1931 and 1981..
+         case 1933..1940:
+         case 1944..1951:
+         case 1953..1974:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Hungary
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1918:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(91)   ,UO+10800  ,3600 ,"S"   }),  // Apr 1
+                     ({FIXED(272)  ,UO+7200   ,0    ,""    })});// Sep 29
+         case 1919:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(105)  ,UO+10800  ,3600 ,"S"   }),  // Apr 15
+                     ({FIXED(258)  ,UO+7200   ,0    ,""    })});// Sep 15
+         case 1920:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(96)   ,UO+10800  ,3600 ,"S"   }),  // Apr 5
+                     ({FIXED(274)  ,UO+7200   ,0    ,""    })});// Sep 30
+         case 1945:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(121)  ,UO+82800  ,3600 ,"S"   }),  // May 1
+                     ({FIXED(307)  ,UO-3600   ,0    ,""    })});// Nov 3
+         case 1946:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(90)   ,UO+7200   ,3600 ,"S"   }),  // Mar 31
+                     ({LDAY (280,7),UO+7200   ,0    ,""    })});// Oct Sun>=1
+         case 1947..1949:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(100,7),UO+7200   ,3600 ,"S"   }),  // Apr Sun>=4
+                     ({LDAYL(280,7),UO+7200   ,0    ,""    })});// Oct Sun>=1
+         case 1950:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(107)  ,UO+7200   ,3600 ,"S"   }),  // Apr 17
+                     ({FIXED(296)  ,UO+7200   ,0    ,""    })});// Oct 23
+         case 1954..1955:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(143)  ,UO+0      ,3600 ,"S"   }),  // May 23
+                     ({FIXED(276)  ,UO-3600   ,0    ,""    })});// Oct 3
+         case 1956:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (159,7),UO+0      ,3600 ,"S"   }),  // Jun Sun>=1
+                     ({LDAY (274,7),UO-3600   ,0    ,""    })});// Sep lastSun
+         case 1957:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (158,7),UO+3600   ,3600 ,"S"   }),  // Jun Sun>=1
+                     ({LDAY (273,7),UO+7200   ,0    ,""    })});// Sep lastSun
+         default: // ..1917:
+         case 1921..1944:
+         case 1951..1953:
+         case 1958..1979:
+            return ({({0           ,0         ,0    ,""    })});
+         case 1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(97)   ,UO+3600   ,3600 ,"S"   })});// Apr 6
+         case 1981..:
+            return ({({0           ,0         ,3600 ,"S"   })});
+      }
+   }
+}
+
+class Iceland
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1917:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(50)   ,UO+82800  ,3600 ,"S"   }),  // Feb 19
+                     ({FIXED(294)  ,UO+0      ,0    ,""    })});// Oct 21
+         case 1918:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(50)   ,UO+82800  ,3600 ,"S"   }),  // Feb 19
+                     ({FIXED(320)  ,UO+0      ,0    ,""    })});// Nov 16
+         case 1939:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(119)  ,UO+82800  ,3600 ,"S"   }),  // Apr 29
+                     ({FIXED(333)  ,UO+3600   ,0    ,""    })});// Nov 29
+         case 1940:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(56)   ,UO+7200   ,3600 ,"S"   }),  // Feb 25
+                     ({FIXED(308)  ,UO+3600   ,0    ,""    })});// Nov 3
+         case 1941:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(61)   ,UO+3600   ,3600 ,"S"   }),  // Mar 2
+                     ({FIXED(306)  ,UO+3600   ,0    ,""    })});// Nov 2
+         case 1942:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(67)   ,UO+3600   ,3600 ,"S"   }),  // Mar 8
+                     ({FIXED(298)  ,UO+3600   ,0    ,""    })});// Oct 25
+         case 1943..1946:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(66,7) ,UO+3600   ,3600 ,"S"   }),  // Mar Sun>=1
+                     ({LDAYL(301,7),UO+3600   ,0    ,""    })});// Oct Sun>=22
+         case 1949:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+3600   ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({FIXED(303)  ,UO+3600   ,0    ,""    })});// Oct 30
+         case 1947..1948:
+         case 1950..1966:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(97,7) ,UO+3600   ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({LDAYL(301,7),UO+3600   ,0    ,""    })});// Oct Sun>=22
+         case 1967:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+3600   ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({FIXED(302)  ,UO+3600   ,0    ,""    })});// Oct 29
+         default: // ..1916 and 1968..
+         case 1919..1938:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Italy
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1916:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(155)  ,UO+0      ,3600 ,"S"   }),  // Jun 3
+                     ({FIXED(275)  ,UO+0      ,0    ,""    })});// Oct 1
+         case 1917:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(91)   ,UO+0      ,3600 ,"S"   }),  // Apr 1
+                     ({FIXED(273)  ,UO+0      ,0    ,""    })});// Sep 30
+         case 1918:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(69)   ,UO+0      ,3600 ,"S"   }),  // Mar 10
+                     ({LDAY (280,7),UO+0      ,0    ,""    })});// Oct Sun>=1
+         case 1919:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(61)   ,UO+0      ,3600 ,"S"   }),  // Mar 2
+                     ({LDAY (280,7),UO+0      ,0    ,""    })});// Oct Sun>=1
+         case 1920:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(81)   ,UO+0      ,3600 ,"S"   }),  // Mar 21
+                     ({FIXED(263)  ,UO+0      ,0    ,""    })});// Sep 19
+         case 1940:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(167)  ,UO+0      ,3600 ,"S"   })});// Jun 15
+         case 1941..1943:
+            return ({({0           ,0         ,3600 ,"S"   })});
+         case 1944:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(261)  ,UO+0      ,0    ,""    })});// Sep 17
+         case 1945:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(92)   ,UO+7200   ,3600 ,"S"   }),  // Apr 2
+                     ({FIXED(258)  ,UO+0      ,0    ,""    })});// Sep 15
+         case 1946:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(76)   ,UO+7200   ,3600 ,"S"   }),  // Mar 17
+                     ({FIXED(279)  ,UO+7200   ,0    ,""    })});// Oct 6
+         case 1947:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(75)   ,UO+0      ,3600 ,"S"   }),  // Mar 16
+                     ({FIXED(278)  ,UO+0      ,0    ,""    })});// Oct 5
+         case 1948:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(60)   ,UO+7200   ,3600 ,"S"   }),  // Feb 29
+                     ({FIXED(277)  ,UO+7200   ,0    ,""    })});// Oct 3
+         case 1966..1968:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(148,7),UO+0      ,3600 ,"S"   }),  // May Sun>=22
+                     ({LDAYL(271,7),UO-3600   ,0    ,""    })});// Sep Sun>=22
+         case 1969:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(152)  ,UO+0      ,3600 ,"S"   }),  // Jun 1
+                     ({LDAY (271,7),UO-3600   ,0    ,""    })});// Sep Sun>=22
+         case 1970:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(151)  ,UO+0      ,3600 ,"S"   }),  // May 31
+                     ({LDAY (273,7),UO-3600   ,0    ,""    })});// Sep lastSun
+         case 1971:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (148,7),UO+0      ,3600 ,"S"   }),  // May Sun>=22
+                     ({LDAY (273,7),UO+0      ,0    ,""    })});// Sep lastSun
+         case 1972:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (149,7),UO+0      ,3600 ,"S"   }),  // May Sun>=22
+                     ({FIXED(275)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1973:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(154)  ,UO+0      ,3600 ,"S"   }),  // Jun 3
+                     ({LDAY (273,7),UO-3600   ,0    ,""    })});// Sep lastSun
+         case 1974:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(146)  ,UO+0      ,3600 ,"S"   }),  // May 26
+                     ({LDAY (273,7),UO-3600   ,0    ,""    })});// Sep lastSun
+         case 1975:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(152)  ,UO+0      ,3600 ,"S"   }),  // Jun 1
+                     ({LDAY (273,7),UO+0      ,0    ,""    })});// Sep lastSun
+         case 1976:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(151)  ,UO+0      ,3600 ,"S"   }),  // May 30
+                     ({LDAY (274,7),UO+0      ,0    ,""    })});// Sep lastSun
+         case 1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (148,7),UO+0      ,3600 ,"S"   }),  // May Sun>=22
+                     ({LDAY (273,7),UO+0      ,0    ,""    })});// Sep lastSun
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (148,7),UO+0      ,3600 ,"S"   }),  // May Sun>=22
+                     ({FIXED(274)  ,UO+0      ,0    ,""    })});// Oct 1
+         case 1979:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (148,7),UO+0      ,3600 ,"S"   }),  // May Sun>=22
+                     ({FIXED(273)  ,UO+0      ,0    ,""    })});// Sep 30
+         default: // ..1915 and 1980..
+         case 1921..1939:
+         case 1949..1965:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Latvia
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1989..1996:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+7200   ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(273,7),UO+7200   ,0    ,""    })});// Sep lastSun
+         default: // ..1988 and 1997..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Lux
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1915:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1916:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(135)  ,UO+82800  ,3600 ,"S"   }),  // May 14
+                     ({FIXED(275)  ,UO+0      ,0    ,""    })});// Oct 1
+         case 1917:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(118)  ,UO+82800  ,3600 ,"S"   }),  // Apr 28
+                     ({FIXED(260)  ,UO+0      ,0    ,""    })});// Sep 17
+         case 1918:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (111,1),UO+7200   ,3600 ,"S"   }),  // Apr Mon>=15
+                     ({LDAY (264,1),UO+7200   ,0    ,""    })});// Sep Mon>=15
+         case 1919:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(60)   ,UO+82800  ,3600 ,"S"   }),  // Mar 1
+                     ({FIXED(278)  ,UO+7200   ,0    ,""    })});// Oct 5
+         case 1920:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(45)   ,UO+82800  ,3600 ,"S"   }),  // Feb 14
+                     ({FIXED(298)  ,UO+3600   ,0    ,""    })});// Oct 24
+         case 1921:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(73)   ,UO+82800  ,3600 ,"S"   }),  // Mar 14
+                     ({FIXED(299)  ,UO+3600   ,0    ,""    })});// Oct 26
+         case 1922:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(84)   ,UO+82800  ,3600 ,"S"   }),  // Mar 25
+                     ({LDAY (281,7),UO+0      ,0    ,""    })});// Oct Sun>=2
+         case 1923:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(111)  ,UO+82800  ,3600 ,"S"   }),  // Apr 21
+                     ({LDAY (281,7),UO+3600   ,0    ,""    })});// Oct Sun>=2
+         case 1924:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(89)   ,UO+82800  ,3600 ,"S"   }),  // Mar 29
+                     ({LDAY (282,7),UO+0      ,0    ,""    })});// Oct Sun>=2
+         case 1925:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(95)   ,UO+82800  ,3600 ,"S"   }),  // Apr 5
+                     ({LDAY (281,7),UO+0      ,0    ,""    })});// Oct Sun>=2
+         case 1926:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(107)  ,UO+82800  ,3600 ,"S"   }),  // Apr 17
+                     ({LDAY (281,7),UO+0      ,0    ,""    })});// Oct Sun>=2
+         case 1927:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(99)   ,UO+82800  ,3600 ,"S"   }),  // Apr 9
+                     ({LDAY (281,7),UO+0      ,0    ,""    })});// Oct Sun>=2
+         case 1928:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(105)  ,UO+82800  ,3600 ,"S"   }),  // Apr 14
+                     ({LDAY (282,7),UO+0      ,0    ,""    })});// Oct Sun>=2
+         case 1929:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(110)  ,UO+82800  ,3600 ,"S"   })});// Apr 20
+         case 1930..:
+            return ({({0           ,0         ,3600 ,"S"   })});
+      }
+   }
+}
+
+class Malta
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1973:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(90)   ,UO+0      ,3600 ,"S"   }),  // Mar 31
+                     ({FIXED(272)  ,UO+0      ,0    ,""    })});// Sep 29
+         case 1974:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(111)  ,UO+0      ,3600 ,"S"   }),  // Apr 21
+                     ({FIXED(259)  ,UO+0      ,0    ,""    })});// Sep 16
+         case 1975..1979:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(111,7),UO+7200   ,3600 ,"S"   }),  // Apr Sun>=15
+                     ({LDAYL(264,7),UO+3600   ,0    ,""    })});// Sep Sun>=15
+         case 1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(91)   ,UO+7200   ,3600 ,"S"   }),  // Mar 31
+                     ({LDAY (265,7),UO+3600   ,0    ,""    })});// Sep Sun>=15
+         default: // ..1972 and 1981..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Neth
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1915:
+            return ({({0           ,0         ,0    ,"AMT" })});// ?
+         case 1916:
+            return ({({0           ,0         ,0    ,"AMT" }),  // ?
+                     ({FIXED(122)  ,UO+7200   ,3600 ,"NST" }),  // May 1
+                     ({FIXED(276)  ,UO+7200   ,0    ,"AMT" })});// Oct 2
+         case 1917:
+            return ({({0           ,0         ,0    ,"AMT" }),  
+                     ({FIXED(106)  ,UO+7200   ,3600 ,"NST" }),  // Apr 16
+                     ({FIXED(260)  ,UO+7200   ,0    ,"AMT" })});// Sep 17
+         case 1918..1921:
+            return ({({0           ,0         ,0    ,"AMT" }),  
+                     ({LDAYL(97,1) ,UO+7200   ,3600 ,"NST" }),  // Apr Mon>=1
+                     ({LDAYL(273,1),UO+7200   ,0    ,"AMT" })});// Sep Mon>=24
+         case 1922:
+            return ({({0           ,0         ,0    ,"AMT" }),  
+                     ({FIXED(85)   ,UO+7200   ,3600 ,"NST" }),  // Mar 26
+                     ({LDAY (281,7),UO+7200   ,0    ,"AMT" })});// Oct Sun>=2
+         case 1923:
+            return ({({0           ,0         ,0    ,"AMT" }),  
+                     ({FIXED(152)  ,UO+7200   ,3600 ,"NST" }),  // Jun 1
+                     ({LDAY (281,7),UO+7200   ,0    ,"AMT" })});// Oct Sun>=2
+         case 1924:
+            return ({({0           ,0         ,0    ,"AMT" }),  
+                     ({FIXED(90)   ,UO+7200   ,3600 ,"NST" }),  // Mar 30
+                     ({LDAY (282,7),UO+7200   ,0    ,"AMT" })});// Oct Sun>=2
+         case 1925:
+            return ({({0           ,0         ,0    ,"AMT" }),  
+                     ({FIXED(156)  ,UO+7200   ,3600 ,"NST" }),  // Jun 5
+                     ({LDAY (281,7),UO+7200   ,0    ,"AMT" })});// Oct Sun>=2
+         case 1932:
+            return ({({0           ,0         ,0    ,"AMT" }),  
+                     ({FIXED(143)  ,UO+7200   ,3600 ,"NST" }),  // May 22
+                     ({LDAY (282,7),UO+7200   ,0    ,"AMT" })});// Oct Sun>=2
+         case 1926..1931:
+         case 1933..1936:
+            return ({({0           ,0         ,0    ,"AMT" }),  
+                     ({FIX_L(135)  ,UO+7200   ,3600 ,"NST" }),  // May 15
+                     ({LDAYL(281,7),UO+7200   ,0    ,"AMT" })});// Oct Sun>=2
+         case 1937:
+            return ({({0           ,0         ,0    ,"AMT" }),  
+                     ({FIXED(142)  ,UO+7200   ,3600 ,"NST" }),  // May 22
+                     ({FIXED(182)  ,UO-3600   ,3600 ,"S"   }),  // Jul 1
+                     ({LDAY (281,7),UO+7200   ,0    ,""    })});// Oct Sun>=2
+         case 1938..1939:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(135)  ,UO+7200   ,3600 ,"S"   }),  // May 15
+                     ({LDAY (281,7),UO+7200   ,0    ,""    })});// Oct Sun>=2
+         case 1945:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(92)   ,UO+7200   ,3600 ,"S"   }),  // Apr 2
+                     ({FIXED(140)  ,UO+7200   ,0    ,""    })});// May 20
+         case 1940..1944:
+         case 1946..:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Norway
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1916:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(143)  ,UO+3600   ,3600 ,"S"   }),  // May 22
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Sep 30
+         case 1945:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(92)   ,UO+7200   ,3600 ,"S"   }),  // Apr 2
+                     ({FIXED(274)  ,UO+7200   ,0    ,""    })});// Oct 1
+         case 1959..1964:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(80,7) ,UO+7200   ,3600 ,"S"   }),  // Mar Sun>=15
+                     ({LDAYL(264,7),UO+7200   ,0    ,""    })});// Sep Sun>=15
+         case 1965:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(115)  ,UO+7200   ,3600 ,"S"   }),  // Apr 25
+                     ({LDAY (264,7),UO+7200   ,0    ,""    })});// Sep Sun>=15
+         default: // ..1915 and 1966..
+         case 1917..1944:
+         case 1946..1958:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Poland
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1918:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(259)  ,UO+7200   ,0    ,""    })});// Sep 16
+         case 1919:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(105)  ,UO+7200   ,3600 ,"S"   }),  // Apr 15
+                     ({FIXED(259)  ,UO+7200   ,0    ,""    })});// Sep 16
+         case 1944:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(278)  ,UO+7200   ,0    ,""    })});// Oct 4
+         case 1945:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(119)  ,UO+0      ,3600 ,"S"   }),  // Apr 29
+                     ({FIXED(305)  ,UO-3600   ,0    ,""    })});// Nov 1
+         case 1946:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(104)  ,UO+0      ,3600 ,"S"   }),  // Apr 14
+                     ({FIXED(250)  ,UO-3600   ,0    ,""    })});// Sep 7
+         case 1947:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(124)  ,UO+0      ,3600 ,"S"   }),  // May 4
+                     ({LDAY (280,7),UO-3600   ,0    ,""    })});// Oct Sun>=1
+         case 1948:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(109)  ,UO+0      ,3600 ,"S"   }),  // Apr 18
+                     ({LDAY (281,7),UO-3600   ,0    ,""    })});// Oct Sun>=1
+         case 1957:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(153)  ,UO+3600   ,3600 ,"S"   }),  // Jun 2
+                     ({LDAY (273,7),UO+3600   ,0    ,""    })});// Sep lastSun
+         case 1958:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(89)   ,UO+3600   ,3600 ,"S"   }),  // Mar 30
+                     ({LDAY (273,7),UO+3600   ,0    ,""    })});// Sep lastSun
+         case 1959:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(151)  ,UO+3600   ,3600 ,"S"   }),  // May 31
+                     ({LDAY (280,7),UO+3600   ,0    ,""    })});// Oct Sun>=1
+         case 1960:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(94)   ,UO+3600   ,3600 ,"S"   }),  // Apr 3
+                     ({LDAY (281,7),UO+3600   ,0    ,""    })});// Oct Sun>=1
+         case 1961:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (151,7),UO+3600   ,3600 ,"S"   }),  // May Sun>=25
+                     ({LDAY (280,7),UO+3600   ,0    ,""    })});// Oct Sun>=1
+         case 1962..1964:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(151,7),UO+3600   ,3600 ,"S"   }),  // May Sun>=25
+                     ({LDAYL(273,7),UO+3600   ,0    ,""    })});// Sep lastSun
+         default: // ..1917 and 1965..
+         case 1920..1943:
+         case 1949..1956:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Port
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1916:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(169)  ,UO+82800  ,3600 ,"S"   }),  // Jun 17
+                     ({FIXED(306)  ,UO+0      ,0    ,""    })});// Nov 1
+         case 1918:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(60)   ,UO+82800  ,3600 ,"S"   }),  // Mar 1
+                     ({FIXED(287)  ,UO+82800  ,0    ,""    })});// Oct 14
+         case 1920:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(60)   ,UO+82800  ,3600 ,"S"   }),  // Feb 29
+                     ({FIXED(288)  ,UO+82800  ,0    ,""    })});// Oct 14
+         case 1917:
+         case 1919:
+         case 1921:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(59)   ,UO+82800  ,3600 ,"S"   }),  // Feb 28
+                     ({FIXED(287)  ,UO+82800  ,0    ,""    })});// Oct 14
+         case 1924:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(107)  ,UO+82800  ,3600 ,"S"   }),  // Apr 16
+                     ({FIXED(288)  ,UO+82800  ,0    ,""    })});// Oct 14
+         case 1926:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(107)  ,UO+82800  ,3600 ,"S"   }),  // Apr 17
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1927:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(99)   ,UO+82800  ,3600 ,"S"   }),  // Apr 9
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1928:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(105)  ,UO+82800  ,3600 ,"S"   }),  // Apr 14
+                     ({LDAY (281,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1929:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(110)  ,UO+82800  ,3600 ,"S"   }),  // Apr 20
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1932:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(93)   ,UO+82800  ,3600 ,"S"   }),  // Apr 2
+                     ({LDAY (281,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1934:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(97)   ,UO+82800  ,3600 ,"S"   }),  // Apr 7
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1935:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(89)   ,UO+82800  ,3600 ,"S"   }),  // Mar 30
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1931:
+         case 1936:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(108)  ,UO+82800  ,3600 ,"S"   }),  // Apr 18
+                     ({LDAYL(280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1937:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(93)   ,UO+82800  ,3600 ,"S"   }),  // Apr 3
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1938:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(85)   ,UO+82800  ,3600 ,"S"   }),  // Mar 26
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1939:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(105)  ,UO+82800  ,3600 ,"S"   }),  // Apr 15
+                     ({FIXED(322)  ,UO+82800  ,0    ,""    })});// Nov 18
+         case 1940:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(55)   ,UO+82800  ,3600 ,"S"   }),  // Feb 24
+                     ({FIXED(279)  ,UO+82800  ,0    ,""    })});// Oct 5
+         case 1941:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(95)   ,UO+82800  ,3600 ,"S"   }),  // Apr 5
+                     ({FIXED(278)  ,UO+82800  ,0    ,""    })});// Oct 5
+         case 1942:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (73,6) ,UO+82800  ,3600 ,"S"   }),  // Mar Sat>=8
+                     ({FIXED(115)  ,UO+79200  ,7200 ,"M"   }),  // Apr 25
+                     ({FIXED(227)  ,UO+79200  ,3600 ,"S"   }),  // Aug 15
+                     ({LDAY (303,6),UO+82800  ,0    ,""    })});// Oct Sat>=24
+         case 1943:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (73,6) ,UO+82800  ,3600 ,"S"   }),  // Mar Sat>=8
+                     ({FIXED(107)  ,UO+79200  ,7200 ,"M"   }),  // Apr 17
+                     ({LDAY (243,6),UO+79200  ,3600 ,"S"   }),  // Aug Sat>=25
+                     ({LDAY (303,6),UO+82800  ,0    ,""    })});// Oct Sat>=24
+         case 1944..1945:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(73,6) ,UO+82800  ,3600 ,"S"   }),  // Mar Sat>=8
+                     ({LDAYL(117,6),UO+79200  ,7200 ,"M"   }),  // Apr Sat>=21
+                     ({LDAYL(243,6),UO+79200  ,3600 ,"S"   }),  // Aug Sat>=25
+                     ({LDAYL(303,6),UO+82800  ,0    ,""    })});// Oct Sat>=24
+         case 1946:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,6) ,UO+82800  ,3600 ,"S"   }),  // Apr Sat>=1
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1947..1949:
+         case 1951..1965:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(97,7) ,UO+7200   ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({LDAYL(280,7),UO+7200   ,0    ,""    })});// Oct Sun>=1
+         default: // ..1915:
+         case 1922..1923:
+         case 1925:
+         case 1930:
+         case 1933:
+         case 1950:
+         case 1966..1976:
+            return ({({0           ,0         ,0    ,""    })});
+         case 1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(86)   ,UO+0      ,3600 ,"S"   }),  // Mar 27
+                     ({FIXED(268)  ,UO+0      ,0    ,""    })});// Sep 25
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+0      ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({FIXED(274)  ,UO+0      ,0    ,""    })});// Oct 1
+         case 1979:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+0      ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({LDAY (273,7),UO+3600   ,0    ,""    })});// Sep lastSun
+         case 1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (91,7) ,UO+0      ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAY (274,7),UO+3600   ,0    ,""    })});// Sep lastSun
+         case 1981..1982:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (90,7) ,UO+3600   ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAY (273,7),UO+3600   ,0    ,""    })});// Sep lastSun
+         case 1983:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (90,7) ,UO+7200   ,3600 ,"S"   })});// Mar lastSun
+         case 1984..:
+            return ({({0           ,0         ,3600 ,"S"   })});
+      }
+   }
+}
+
+class Romania
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1932:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(142)  ,UO+0      ,3600 ,"S"   }),  // May 21
+                     ({LDAY (281,7),UO+0      ,0    ,""    })});// Oct Sun>=1
+         case 1933..1939:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(98,7) ,UO+0      ,3600 ,"S"   }),  // Apr Sun>=2
+                     ({LDAYL(280,7),UO+0      ,0    ,""    })});// Oct Sun>=1
+         case 1979:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(147)  ,UO+0      ,3600 ,"S"   }),  // May 27
+                     ({LDAY (273,7),UO-3600   ,0    ,""    })});// Sep lastSun
+         case 1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(96)   ,UO+82800  ,3600 ,"S"   }),  // Apr 5
+                     ({LDAY (274,7),UO+0      ,0    ,""    })});// Sep lastSun
+         case 1991..1993:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(90,7) ,UO+0      ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAYL(273,7),UO+0      ,0    ,""    })});// Sep lastSun
+         default: // ..1931 and 1994..
+         case 1940..1978:
+         case 1981..1990:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Spain
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1917:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(125)  ,UO+82800  ,3600 ,"S"   }),  // May 5
+                     ({FIXED(279)  ,UO+82800  ,0    ,""    })});// Oct 6
+         case 1918:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(105)  ,UO+82800  ,3600 ,"S"   }),  // Apr 15
+                     ({FIXED(279)  ,UO+82800  ,0    ,""    })});// Oct 6
+         case 1919:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(95)   ,UO+82800  ,3600 ,"S"   }),  // Apr 5
+                     ({FIXED(279)  ,UO+82800  ,0    ,""    })});// Oct 6
+         case 1924:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(107)  ,UO+82800  ,3600 ,"S"   }),  // Apr 16
+                     ({FIXED(278)  ,UO+82800  ,0    ,""    })});// Oct 4
+         case 1926:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(107)  ,UO+82800  ,3600 ,"S"   }),  // Apr 17
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1927:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(99)   ,UO+82800  ,3600 ,"S"   }),  // Apr 9
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1928:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(105)  ,UO+82800  ,3600 ,"S"   }),  // Apr 14
+                     ({LDAY (281,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1929:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(110)  ,UO+82800  ,3600 ,"S"   }),  // Apr 20
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1937:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(142)  ,UO+82800  ,3600 ,"S"   }),  // May 22
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1938:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(81)   ,UO+82800  ,3600 ,"S"   }),  // Mar 22
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1939:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(105)  ,UO+82800  ,3600 ,"S"   }),  // Apr 15
+                     ({LDAY (280,6),UO+82800  ,0    ,""    })});// Oct Sat>=1
+         case 1940:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(76)   ,UO+82800  ,3600 ,"S"   })});// Mar 16
+         case 1941:
+            return ({({0           ,0         ,3600 ,"S"   })});
+         case 1942:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(122)  ,UO+79200  ,7200 ,"M"   }),  // May 2
+                     ({FIXED(244)  ,UO+79200  ,3600 ,"S"   })});// Sep 1
+         case 1943:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (109,6),UO+79200  ,7200 ,"M"   }),  // Apr Sat>=13
+                     ({FIXED(276)  ,UO+79200  ,3600 ,"S"   })});// Oct 3
+         case 1944:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (110,6),UO+79200  ,7200 ,"M"   }),  // Apr Sat>=13
+                     ({FIXED(284)  ,UO+79200  ,3600 ,"S"   })});// Oct 10
+         case 1945:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (109,6),UO+79200  ,7200 ,"M"   }),  // Apr Sat>=13
+                     ({FIXED(273)  ,UO-3600   ,3600 ,"S"   })});// Sep 30
+         case 1946:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (109,6),UO+79200  ,7200 ,"M"   }),  // Apr Sat>=13
+                     ({FIXED(273)  ,UO-7200   ,0    ,""    })});// Sep 30
+         case 1949:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(120)  ,UO+82800  ,3600 ,"S"   }),  // Apr 30
+                     ({FIXED(273)  ,UO+0      ,0    ,""    })});// Sep 30
+         case 1974..1975:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (109,6),UO+82800  ,3600 ,"S"   }),  // Apr Sat>=13
+                     ({LDAY (280,7),UO+0      ,0    ,""    })});// Oct Sun>=1
+         case 1976:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(87)   ,UO+82800  ,3600 ,"S"   }),  // Mar 27
+                     ({LDAY (274,7),UO+0      ,0    ,""    })});// Sep lastSun
+         case 1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(92)   ,UO+82800  ,3600 ,"S"   }),  // Apr 2
+                     ({LDAY (273,7),UO+0      ,0    ,""    })});// Sep lastSun
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(92)   ,UO+82800  ,3600 ,"S"   }),  // Apr 2
+                     ({FIXED(274)  ,UO+0      ,0    ,""    })});// Oct 1
+         default: // ..1916 and 1979..
+         case 1920..1923:
+         case 1925:
+         case 1930..1936:
+         case 1947..1948:
+         case 1950..1973:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class SpainAfrica
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1967:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(154)  ,UO+43200  ,3600 ,"S"   }),  // Jun 3
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1974:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(175)  ,UO+0      ,3600 ,"S"   }),  // Jun 24
+                     ({FIXED(244)  ,UO-3600   ,0    ,""    })});// Sep 1
+         case 1976:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(122)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({FIXED(214)  ,UO-3600   ,0    ,""    })});// Aug 1
+         case 1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(121)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({FIXED(271)  ,UO-3600   ,0    ,""    })});// Sep 28
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(152)  ,UO+0      ,3600 ,"S"   }),  // Jun 1
+                     ({FIXED(216)  ,UO-3600   ,0    ,""    })});// Aug 4
+         default: // ..1966 and 1979..
+         case 1968..1973:
+         case 1975:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Swiss
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1940:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(307)  ,UO+0      ,3600 ,"S"   }),  // Nov 2
+                     ({FIXED(366)  ,UO-3600   ,0    ,""    })});// Dec 31
+         case 1941..1942:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (127,7),UO+7200   ,3600 ,"S"   }),  // May Sun>=1
+                     ({LDAY (280,7),UO-3600   ,0    ,""    })});// Oct Sun>=1
+         default: // ..1939 and 1943..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Turkey
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1920:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(88)   ,UO+0      ,3600 ,"S"   }),  // Mar 28
+                     ({FIXED(299)  ,UO-3600   ,0    ,""    })});// Oct 25
+         case 1921:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(93)   ,UO+0      ,3600 ,"S"   }),  // Apr 3
+                     ({FIXED(276)  ,UO-3600   ,0    ,""    })});// Oct 3
+         case 1922:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(85)   ,UO+0      ,3600 ,"S"   }),  // Mar 26
+                     ({FIXED(281)  ,UO-3600   ,0    ,""    })});// Oct 8
+         case 1924:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(134)  ,UO+0      ,3600 ,"S"   }),  // May 13
+                     ({FIXED(275)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1916:
+         case 1925:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(121)  ,UO+0      ,3600 ,"S"   }),  // May 1
+                     ({FIX_L(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1940:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(182)  ,UO+0      ,3600 ,"S"   }),  // Jun 30
+                     ({FIXED(279)  ,UO-3600   ,0    ,""    }),  // Oct 5
+                     ({FIXED(336)  ,UO+0      ,3600 ,"S"   })});// Dec 1
+         case 1941:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(264)  ,UO-3600   ,0    ,""    })});// Sep 21
+         case 1942:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(91)   ,UO+0      ,3600 ,"S"   }),  // Apr 1
+                     ({FIXED(305)  ,UO-3600   ,0    ,""    })});// Nov 1
+         case 1945:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(92)   ,UO+0      ,3600 ,"S"   }),  // Apr 2
+                     ({FIXED(281)  ,UO-3600   ,0    ,""    })});// Oct 8
+         case 1946:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(152)  ,UO+0      ,3600 ,"S"   }),  // Jun 1
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1947..1948:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(112,7),UO+0      ,3600 ,"S"   }),  // Apr Sun>=16
+                     ({LDAYL(281,7),UO-3600   ,0    ,""    })});// Oct Sun>=2
+         case 1949:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(100)  ,UO+0      ,3600 ,"S"   }),  // Apr 10
+                     ({LDAY (281,7),UO-3600   ,0    ,""    })});// Oct Sun>=2
+         case 1950:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(109)  ,UO+0      ,3600 ,"S"   }),  // Apr 19
+                     ({LDAY (281,7),UO-3600   ,0    ,""    })});// Oct Sun>=2
+         case 1951:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(112)  ,UO+0      ,3600 ,"S"   }),  // Apr 22
+                     ({FIXED(281)  ,UO-3600   ,0    ,""    })});// Oct 8
+         case 1962:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(196)  ,UO+0      ,3600 ,"S"   }),  // Jul 15
+                     ({FIXED(281)  ,UO-3600   ,0    ,""    })});// Oct 8
+         case 1964:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(136)  ,UO+0      ,3600 ,"S"   }),  // May 15
+                     ({FIXED(275)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1970..1972:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAYL(128,7),UO+0      ,3600 ,"S"   }),  // May Sun>=2
+                     ({LDAYL(281,7),UO-3600   ,0    ,""    })});// Oct Sun>=2
+         case 1973:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(154)  ,UO+3600   ,3600 ,"S"   }),  // Jun 3
+                     ({FIXED(308)  ,UO+7200   ,0    ,""    })});// Nov 4
+         case 1974:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(90)   ,UO+7200   ,3600 ,"S"   }),  // Mar 31
+                     ({FIXED(307)  ,UO+14400  ,0    ,""    })});// Nov 3
+         case 1975:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(89)   ,UO+0      ,3600 ,"S"   }),  // Mar 30
+                     ({LDAY (304,7),UO-3600   ,0    ,""    })});// Oct lastSun
+         case 1976:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(153)  ,UO+0      ,3600 ,"S"   }),  // Jun 1
+                     ({LDAY (305,7),UO-3600   ,0    ,""    })});// Oct lastSun
+         case 1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+0      ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({FIXED(289)  ,UO-3600   ,0    ,""    })});// Oct 16
+         case 1978:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+0      ,3600 ,"S"   })});// Apr Sun>=1
+         case 1979:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (97,7) ,UO+7200   ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({LDAY (290,1),UO-3600   ,0    ,""    })});// Oct Mon>=11
+         case 1980:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (98,7) ,UO+10800  ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({LDAY (291,1),UO-3600   ,0    ,""    })});// Oct Mon>=11
+         case 1981..1982:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (90,7) ,UO+10800  ,3600 ,"S"   }),  // Mar lastSun
+                     ({LDAY (290,1),UO-3600   ,0    ,""    })});// Oct Mon>=11
+         case 1983:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(212)  ,UO+0      ,3600 ,"S"   }),  // Jul 31
+                     ({FIXED(275)  ,UO-3600   ,0    ,""    })});// Oct 2
+         case 1985:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(110)  ,UO+0      ,3600 ,"S"   }),  // Apr 20
+                     ({FIXED(271)  ,UO-3600   ,0    ,""    })});// Sep 28
+         default: // ..1915 and 1986..
+         case 1917..1919:
+         case 1923:
+         case 1926..1939:
+         case 1943..1944:
+         case 1952..1961:
+         case 1963:
+         case 1965..1969:
+         case 1984:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class US
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1918..1919:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (90,7) ,UO+7200   ,3600 ,"W"   }),  // Mar lastSun
+                     ({LDAY (304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1942:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(40)   ,UO+7200   ,3600 ,"W"   })});// Feb 9
+         case 1943..1944:
+            return ({({0           ,0         ,3600 ,"W"   })});
+         case 1945:
+            return ({({0           ,0         ,3600 ,"W"   }),  
+                     ({FIXED(273)  ,UO+3600   ,0    ,"S"   })});// Sep 30
+         default: // ..1917:
+         case 1920..1941:
+         case 1946..1966:
+            return ({({0           ,0         ,0    ,"S"   })});
+         case 1974:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(6)    ,UO+7200   ,3600 ,"D"   }),  // Jan 6
+                     ({LDAY (304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1975:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(54)   ,UO+7200   ,3600 ,"D"   }),  // Feb 23
+                     ({LDAY (304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1967..1973:
+         case 1976..1986:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1987..:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+7200   ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+      }
+   }
+}
+
+class NYC
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1920:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({LDAY (91,7) ,UO+7200   ,3600 ,"D"   }),  // Mar lastSun
+                     ({LDAY (305,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1921..1954:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1955..1966:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         default: // ..1919 and 1967..
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Chicago
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1920:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(165)  ,UO+7200   ,3600 ,"D"   }),  // Jun 13
+                     ({LDAY (305,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1921:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (90,7) ,UO+7200   ,3600 ,"D"   }),  // Mar lastSun
+                     ({LDAY (304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1922..1954:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1955..1966:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         default: // ..1919 and 1967..
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Denver
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1920:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({LDAY (91,7) ,UO+7200   ,3600 ,"D"   }),  // Mar lastSun
+                     ({LDAY (305,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1921:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (90,7) ,UO+7200   ,3600 ,"D"   }),  // Mar lastSun
+                     ({FIXED(142)  ,UO+3600   ,0    ,"S"   })});// May 22
+         case 1965..1966:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAY (304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         default: // ..1919 and 1967..
+         case 1922..1964:
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class CA
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1948:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(74)   ,UO+7200   ,3600 ,"D"   })});// Mar 14
+         case 1949:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({FIXED(1)    ,UO+3600   ,0    ,"S"   })});// Jan 1
+         case 1950..1961:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1962..1966:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         default: // ..1947 and 1967..
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Indianapolis
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1941:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(173)  ,UO+7200   ,3600 ,"D"   }),  // Jun 22
+                     ({LDAY (273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1942..1945:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(273,7),UO+7200   ,0    ,"S"   })});// Sep lastSun
+         case 1946..1954:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         default: // ..1940 and 1955..
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Marengo
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1951:
+         case 1954..1960:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         default: // ..1950 and 1961..
+         case 1952..1953:
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Starke
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1947..1954:
+         case 1957..1958:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1955..1956:
+         case 1959..1961:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         default: // ..1946 and 1962..
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Louisville
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1921:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(121)  ,UO+7200   ,3600 ,"D"   }),  // May 1
+                     ({FIXED(244)  ,UO+3600   ,0    ,"S"   })});// Sep 1
+         default: // ..1920:
+         case 1922..1940:
+            return ({({0           ,0         ,0    ,"S"   })});
+         case 1946:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({LDAY (120,7),UO+3600   ,3600 ,"D"   }),  // Apr lastSun
+                     ({FIXED(153)  ,UO+3600   ,0    ,"S"   })});// Jun 2
+         case 1943..1945:
+         case 1948..1949:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({LDAYL(120,7),UO+3600   ,3600 ,"D"   })});// Apr lastSun
+         case 1950:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({LDAY (120,7),UO+3600   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAY (273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1941:
+         case 1951..1955:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1956..1960:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1942:
+         case 1947:
+         case 1961:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (120,7),UO+7200   ,3600 ,"D"   })});// Apr lastSun
+         case 1962..:
+            return ({({0           ,0         ,3600 ,"D"   })});
+      }
+   }
+}
+
+class Detroit
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1948:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({LDAY (121,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAY (274,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1967:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(165)  ,UO+7200   ,3600 ,"D"   }),  // Jun 14
+                     ({LDAY (304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         default: // ..1947 and 1968..
+         case 1949..1966:
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Menominee
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1946:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({LDAY (120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAY (273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1966:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAY (304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         default: // ..1945 and 1967..
+         case 1947..1965:
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Canada
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1918:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(104)  ,UO+7200   ,3600 ,"D"   }),  // Apr 14
+                     ({FIXED(304)  ,UO+3600   ,0    ,"S"   })});// Oct 31
+         case 1942:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(40)   ,UO+7200   ,3600 ,"D"   })});// Feb 9
+         case 1943..1944:
+            return ({({0           ,0         ,3600 ,"D"   })});
+         case 1945:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({FIXED(273)  ,UO+3600   ,0    ,"S"   })});// Sep 30
+         default: // ..1917:
+         case 1919..1941:
+         case 1946..1973:
+            return ({({0           ,0         ,0    ,"S"   })});
+         case 1974..1986:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1987..:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+7200   ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+      }
+   }
+}
+
+class StJohns
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1916:
+            return ({({0           ,0         ,0    ,"S"   })});// ?
+         case 1917:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({LDAY (104,7),UO+7200   ,3600 ,"D"   }),  // Apr Sun>=8
+                     ({FIXED(260)  ,UO+3600   ,0    ,"S"   })});// Sep 17
+         case 1918:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (104,7),UO+7200   ,3600 ,"D"   }),  // Apr Sun>=8
+                     ({FIXED(304)  ,UO+3600   ,0    ,"S"   })});// Oct 31
+         case 1919:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(125)  ,UO+82800  ,3600 ,"D"   }),  // May 5
+                     ({FIXED(224)  ,UO+79200  ,0    ,"S"   })});// Aug 12
+         case 1920..1935:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(127,7),UO+82800  ,3600 ,"D"   }),  // May Sun>=1
+                     ({LDAYL(304,7),UO+79200  ,0    ,"S"   })});// Oct lastSun
+         case 1936..1941:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(134,7),UO+0      ,3600 ,"D"   }),  // May Sun>=8
+                     ({LDAYL(280,7),UO-3600   ,0    ,"S"   })});// Oct Sun>=1
+         case 1942:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(60)   ,UO+0      ,3600 ,"D"   }),  // Mar 1
+                     ({FIXED(365)  ,UO-3600   ,0    ,"S"   })});// Dec 31
+         case 1943:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(150)  ,UO+0      ,3600 ,"D"   }),  // May 30
+                     ({FIXED(248)  ,UO-3600   ,0    ,"S"   })});// Sep 5
+         case 1944:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(192)  ,UO+0      ,3600 ,"D"   }),  // Jul 10
+                     ({FIXED(246)  ,UO-3600   ,0    ,"S"   })});// Sep 2
+         case 1945:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(1)    ,UO+0      ,3600 ,"D"   }),  // Jan 1
+                     ({FIXED(280)  ,UO+3600   ,0    ,"S"   })});// Oct 7
+         case 1946..1950:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(134,7),UO+7200   ,3600 ,"D"   }),  // May Sun>=8
+                     ({LDAYL(281,7),UO+3600   ,0    ,"S"   })});// Oct Sun>=2
+         case 1951..1959:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1960..1986:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1988:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (98,7) ,UO+7200   ,7200 ,"DD"  }),  // Apr Sun>=1
+                     ({LDAY (305,7),UO+0      ,0    ,"S"   })});// Oct lastSun
+         case 1987:
+         case 1989..:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+7200   ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+      }
+   }
+}
+
+class Halifax
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1916:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(92)   ,UO+0      ,3600 ,"D"   }),  // Apr 1
+                     ({FIXED(275)  ,UO-3600   ,0    ,"S"   })});// Oct 1
+         case 1918:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(104)  ,UO+7200   ,3600 ,"D"   }),  // Apr 14
+                     ({FIXED(304)  ,UO+3600   ,0    ,"S"   })});// Oct 31
+         case 1920:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(130)  ,UO+0      ,3600 ,"D"   }),  // May 9
+                     ({FIXED(242)  ,UO-3600   ,0    ,"S"   })});// Aug 29
+         case 1921:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(126)  ,UO+0      ,3600 ,"D"   }),  // May 6
+                     ({FIXED(248)  ,UO-3600   ,0    ,"S"   })});// Sep 5
+         case 1922:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(120)  ,UO+0      ,3600 ,"D"   }),  // Apr 30
+                     ({FIXED(248)  ,UO-3600   ,0    ,"S"   })});// Sep 5
+         case 1923:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (127,7),UO+0      ,3600 ,"D"   }),  // May Sun>=1
+                     ({FIXED(247)  ,UO-3600   ,0    ,"S"   })});// Sep 4
+         case 1924:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (128,7),UO+0      ,3600 ,"D"   }),  // May Sun>=1
+                     ({FIXED(259)  ,UO-3600   ,0    ,"S"   })});// Sep 15
+         case 1925:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (127,7),UO+0      ,3600 ,"D"   }),  // May Sun>=1
+                     ({FIXED(271)  ,UO-3600   ,0    ,"S"   })});// Sep 28
+         case 1926:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(136)  ,UO+0      ,3600 ,"D"   }),  // May 16
+                     ({FIXED(256)  ,UO-3600   ,0    ,"S"   })});// Sep 13
+         case 1927:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(121)  ,UO+0      ,3600 ,"D"   }),  // May 1
+                     ({FIXED(269)  ,UO-3600   ,0    ,"S"   })});// Sep 26
+         case 1928:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (135,7),UO+0      ,3600 ,"D"   }),  // May Sun>=8
+                     ({FIXED(253)  ,UO-3600   ,0    ,"S"   })});// Sep 9
+         case 1929:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (134,7),UO+0      ,3600 ,"D"   }),  // May Sun>=8
+                     ({FIXED(246)  ,UO-3600   ,0    ,"S"   })});// Sep 3
+         case 1930:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (134,7),UO+0      ,3600 ,"D"   }),  // May Sun>=8
+                     ({FIXED(258)  ,UO-3600   ,0    ,"S"   })});// Sep 15
+         case 1931:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (134,7),UO+0      ,3600 ,"D"   }),  // May Sun>=8
+                     ({LDAY (273,1),UO-3600   ,0    ,"S"   })});// Sep Mon>=24
+         case 1932:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (274,1),UO+0      ,0    ,"S"   })});// Sep Mon>=24
+         case 1933:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(120)  ,UO+0      ,3600 ,"D"   }),  // Apr 30
+                     ({FIXED(275)  ,UO-3600   ,0    ,"S"   })});// Oct 2
+         case 1934:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(140)  ,UO+0      ,3600 ,"D"   }),  // May 20
+                     ({FIXED(259)  ,UO-3600   ,0    ,"S"   })});// Sep 16
+         case 1935:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(153)  ,UO+0      ,3600 ,"D"   }),  // Jun 2
+                     ({FIXED(273)  ,UO-3600   ,0    ,"S"   })});// Sep 30
+         case 1936:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(153)  ,UO+0      ,3600 ,"D"   }),  // Jun 1
+                     ({FIXED(258)  ,UO-3600   ,0    ,"S"   })});// Sep 14
+         case 1939:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(148)  ,UO+0      ,3600 ,"D"   }),  // May 28
+                     ({LDAY (273,1),UO-3600   ,0    ,"S"   })});// Sep Mon>=24
+         case 1937..1938:
+         case 1940..1941:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(127,7),UO+0      ,3600 ,"D"   }),  // May Sun>=1
+                     ({LDAYL(273,1),UO-3600   ,0    ,"S"   })});// Sep Mon>=24
+         case 1942:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(40)   ,UO+7200   ,3600 ,"D"   })});// Feb 9
+         case 1943..1944:
+            return ({({0           ,0         ,3600 ,"D"   })});
+         case 1945:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({LDAY (273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1946..1959:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         default: // ..1915:
+         case 1917:
+         case 1919:
+         case 1960..1961:
+            return ({({0           ,0         ,0    ,"S"   })});
+         case 1962..1986:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1987..:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+7200   ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+      }
+   }
+}
+
+class Mont
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1917:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(84)   ,UO+7200   ,3600 ,"D"   }),  // Mar 25
+                     ({FIXED(114)  ,UO-3600   ,0    ,"S"   })});// Apr 24
+         case 1918:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(104)  ,UO+7200   ,3600 ,"D"   }),  // Apr 14
+                     ({FIXED(304)  ,UO+3600   ,0    ,"S"   })});// Oct 31
+         case 1919:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(90)   ,UO+9000   ,3600 ,"D"   }),  // Mar 31
+                     ({FIXED(298)  ,UO+5400   ,0    ,"S"   })});// Oct 25
+         case 1920:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(123)  ,UO+9000   ,3600 ,"D"   }),  // May 2
+                     ({FIXED(277)  ,UO+5400   ,0    ,"S"   })});// Oct 3
+         case 1921:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(121)  ,UO+7200   ,3600 ,"D"   }),  // May 1
+                     ({FIXED(275)  ,UO+5400   ,0    ,"S"   })});// Oct 2
+         case 1922:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(120)  ,UO+7200   ,3600 ,"D"   }),  // Apr 30
+                     ({FIXED(274)  ,UO+5400   ,0    ,"S"   })});// Oct 1
+         default: // ..1916:
+         case 1923:
+            return ({({0           ,0         ,0    ,"S"   })});
+         case 1924:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(138)  ,UO+7200   ,3600 ,"D"   }),  // May 17
+                     ({LDAY (274,7),UO+5400   ,0    ,"S"   })});// Sep lastSun
+         case 1925..1926:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (127,7),UO+7200   ,3600 ,"D"   }),  // May Sun>=1
+                     ({LDAY (273,7),UO+5400   ,0    ,"S"   })});// Sep lastSun
+         case 1928..1931:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(121,7),UO+0      ,3600 ,"D"   }),  // Apr Sun>=25
+                     ({LDAYL(274,7),UO-3600   ,0    ,"S"   })});// Sep Sun>=25
+         case 1927:
+         case 1932:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIX_L(121)  ,UO+0      ,3600 ,"D"   }),  // May 1
+                     ({LDAYL(274,7),UO-3600   ,0    ,"S"   })});// Sep Sun>=25
+         case 1933:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (120,7),UO+0      ,3600 ,"D"   }),  // Apr Sun>=24
+                     ({FIXED(274)  ,UO-3600   ,0    ,"S"   })});// Oct 1
+         case 1934..1939:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+0      ,3600 ,"D"   }),  // Apr Sun>=24
+                     ({LDAYL(273,7),UO-3600   ,0    ,"S"   })});// Sep Sun>=24
+         case 1940:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (121,7),UO+0      ,3600 ,"D"   })});// Apr Sun>=24
+         case 1941..1944:
+            return ({({0           ,0         ,3600 ,"D"   })});
+         case 1945:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({LDAY (273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1946..1948:
+         case 1951..1956:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1949..1950:
+         case 1957..1986:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1987..:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+7200   ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+      }
+   }
+}
+
+class Winn
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1916:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(114)  ,UO+0      ,3600 ,"D"   }),  // Apr 23
+                     ({FIXED(261)  ,UO-3600   ,0    ,"S"   })});// Sep 17
+         case 1918:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(104)  ,UO+7200   ,3600 ,"D"   }),  // Apr 14
+                     ({FIXED(304)  ,UO+3600   ,0    ,"S"   })});// Oct 31
+         case 1937:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(136)  ,UO+7200   ,3600 ,"D"   }),  // May 16
+                     ({FIXED(269)  ,UO+3600   ,0    ,"S"   })});// Sep 26
+         case 1942:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(40)   ,UO+7200   ,3600 ,"D"   })});// Feb 9
+         case 1943..1944:
+            return ({({0           ,0         ,3600 ,"D"   })});
+         case 1945:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({LDAY (273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1946:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(132)  ,UO+7200   ,3600 ,"D"   }),  // May 12
+                     ({FIXED(286)  ,UO+3600   ,0    ,"S"   })});// Oct 13
+         case 1950:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(121)  ,UO+7200   ,3600 ,"D"   }),  // May 1
+                     ({FIXED(273)  ,UO+3600   ,0    ,"S"   })});// Sep 30
+         case 1947..1949:
+         case 1951..1958:
+         case 1960:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1963:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({FIXED(265)  ,UO+3600   ,0    ,"S"   })});// Sep 22
+         default: // ..1915:
+         case 1917:
+         case 1919..1936:
+         case 1938..1941:
+         case 1961..1962:
+         case 1964..1965:
+            return ({({0           ,0         ,0    ,"S"   })});
+         case 1959:
+         case 1966..1986:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1987..:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+7200   ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+      }
+   }
+}
+
+class Regina
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1918:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(104)  ,UO+7200   ,3600 ,"D"   }),  // Apr 14
+                     ({FIXED(304)  ,UO+3600   ,0    ,"S"   })});// Oct 31
+         case 1930..1934:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(127,7),UO+0      ,3600 ,"D"   }),  // May Sun>=1
+                     ({LDAYL(280,7),UO-3600   ,0    ,"S"   })});// Oct Sun>=1
+         case 1938:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (104,7),UO+0      ,3600 ,"D"   }),  // Apr Sun>=8
+                     ({LDAY (280,7),UO-3600   ,0    ,"S"   })});// Oct Sun>=1
+         case 1937:
+         case 1939..1941:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(104,7),UO+0      ,3600 ,"D"   }),  // Apr Sun>=8
+                     ({LDAYL(287,7),UO-3600   ,0    ,"S"   })});// Oct Sun>=8
+         case 1942:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(40)   ,UO+7200   ,3600 ,"D"   })});// Feb 9
+         case 1943..1944:
+            return ({({0           ,0         ,3600 ,"D"   })});
+         case 1945:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({LDAY (273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1946:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (104,7),UO+7200   ,3600 ,"D"   }),  // Apr Sun>=8
+                     ({LDAY (287,7),UO+3600   ,0    ,"S"   })});// Oct Sun>=8
+         case 1947..1958:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1959:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAY (304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         default: // ..1917 and 1960..
+         case 1919..1929:
+         case 1935..1936:
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Swift
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1957:
+         case 1959:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAY (304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1960..1961:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         default: // ..1956 and 1962..
+         case 1958:
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Edm
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1918:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({LDAY (104,7),UO+7200   ,3600 ,"D"   }),  // Apr Sun>=8
+                     ({FIXED(304)  ,UO+3600   ,0    ,"S"   })});// Oct 31
+         case 1919:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (104,7),UO+7200   ,3600 ,"D"   }),  // Apr Sun>=8
+                     ({FIXED(147)  ,UO+3600   ,0    ,"S"   })});// May 27
+         case 1942:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(40)   ,UO+7200   ,3600 ,"D"   })});// Feb 9
+         case 1943..1944:
+            return ({({0           ,0         ,3600 ,"D"   })});
+         case 1945:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({LDAY (273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1921..1923:
+         case 1947:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAY (273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         default: // ..1917:
+         case 1924..1941:
+         case 1946:
+         case 1948..1966:
+         case 1968:
+         case 1970..1971:
+            return ({({0           ,0         ,0    ,"S"   })});
+         case 1920:
+         case 1967:
+         case 1969:
+         case 1972..1986:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1987..:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+7200   ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+      }
+   }
+}
+
+class Vanc
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1918:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(104)  ,UO+7200   ,3600 ,"D"   }),  // Apr 14
+                     ({FIXED(304)  ,UO+3600   ,0    ,"S"   })});// Oct 31
+         default: // ..1917:
+         case 1919..1941:
+            return ({({0           ,0         ,0    ,"S"   })});
+         case 1942:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(40)   ,UO+7200   ,3600 ,"D"   })});// Feb 9
+         case 1943..1944:
+            return ({({0           ,0         ,3600 ,"D"   })});
+         case 1945:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({FIXED(273)  ,UO+3600   ,0    ,"S"   })});// Sep 30
+         case 1946:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({FIXED(286)  ,UO+3600   ,0    ,"S"   })});// Oct 13
+         case 1947..1961:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         case 1962..1986:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1987..:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+7200   ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+      }
+   }
+}
+
+class NT_YK
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1918:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(104)  ,UO+7200   ,3600 ,"D"   }),  // Apr 14
+                     ({FIXED(300)  ,UO+3600   ,0    ,"S"   })});// Oct 27
+         case 1919:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(145)  ,UO+7200   ,3600 ,"D"   }),  // May 25
+                     ({FIXED(305)  ,UO-3600   ,0    ,"S"   })});// Nov 1
+         case 1942:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(40)   ,UO+7200   ,3600 ,"D"   })});// Feb 9
+         case 1943..1944:
+            return ({({0           ,0         ,3600 ,"D"   })});
+         case 1945:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({FIXED(273)  ,UO+3600   ,0    ,"S"   })});// Sep 30
+         case 1965:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (120,7),UO+0      ,7200 ,"DD"  }),  // Apr lastSun
+                     ({LDAY (304,7),UO+0      ,0    ,"S"   })});// Oct lastSun
+         default: // ..1917:
+         case 1920..1941:
+         case 1946..1964:
+         case 1966..1979:
+            return ({({0           ,0         ,0    ,"S"   })});
+         case 1980..1986:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1987..:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+7200   ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+      }
+   }
+}
+
+class Mexico
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1939:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(36)   ,UO+0      ,3600 ,"D"   }),  // Feb 5
+                     ({FIXED(176)  ,UO-3600   ,0    ,"S"   })});// Jun 25
+         case 1940:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(344)  ,UO+0      ,3600 ,"D"   })});// Dec 9
+         case 1941:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({FIXED(91)   ,UO-3600   ,0    ,"S"   })});// Apr 1
+         case 1943:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(350)  ,UO+0      ,3600 ,"D"   })});// Dec 16
+         case 1944:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({FIXED(122)  ,UO-3600   ,0    ,"S"   })});// May 1
+         case 1950:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(43)   ,UO+0      ,3600 ,"D"   }),  // Feb 12
+                     ({FIXED(211)  ,UO-3600   ,0    ,"S"   })});// Jul 30
+         default: // ..1938:
+         case 1942:
+         case 1945..1949:
+         case 1951..1995:
+            return ({({0           ,0         ,0    ,"S"   })});
+         case 1996..:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+7200   ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+      }
+   }
+}
+
+class BajaN
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1954..1961:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(273,7),UO+3600   ,0    ,"S"   })});// Sep lastSun
+         default: // ..1953 and 1962..
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Bahamas
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1963:
+            return ({({0           ,0         ,0    ,"S"   })});// ?
+         case 1964..1986:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         case 1987..:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+7200   ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+      }
+   }
+}
+
+class Barb
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1977:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(163)  ,UO+7200   ,3600 ,"D"   }),  // Jun 12
+                     ({LDAY (280,7),UO+3600   ,0    ,"S"   })});// Oct Sun>=1
+         case 1978:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (111,7),UO+7200   ,3600 ,"D"   }),  // Apr Sun>=15
+                     ({LDAY (280,7),UO+3600   ,0    ,"S"   })});// Oct Sun>=1
+         case 1979:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (111,7),UO+7200   ,3600 ,"D"   }),  // Apr Sun>=15
+                     ({FIXED(273)  ,UO+3600   ,0    ,"S"   })});// Sep 30
+         case 1980:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (112,7),UO+7200   ,3600 ,"D"   }),  // Apr Sun>=15
+                     ({FIXED(269)  ,UO+3600   ,0    ,"S"   })});// Sep 25
+         default: // ..1976 and 1981..
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Belize
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1918:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({LDAY (281,7),UO+0      ,1800 ,"HD"  })});// Oct Sun>=2
+         case 1919..1942:
+            return ({({0           ,0         ,1800 ,"HD"  }),  
+                     ({LDAYL(46,7) ,UO-1800   ,0    ,"S"   }),  // Feb Sun>=9
+                     ({LDAYL(281,7),UO+0      ,1800 ,"HD"  })});// Oct Sun>=2
+         case 1943:
+            return ({({0           ,0         ,1800 ,"HD"  }),  
+                     ({LDAY (46,7) ,UO-1800   ,0    ,"S"   })});// Feb Sun>=9
+         case 1973:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(339)  ,UO+0      ,3600 ,"D"   })});// Dec 5
+         case 1974:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({FIXED(40)   ,UO-3600   ,0    ,"S"   })});// Feb 9
+         case 1982:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(352)  ,UO+0      ,3600 ,"D"   })});// Dec 18
+         case 1983:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({FIXED(43)   ,UO-3600   ,0    ,"S"   })});// Feb 12
+         default: // ..1917 and 1984..
+         case 1944..1972:
+         case 1975..1981:
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class CR
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1979..1980:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(59,7) ,UO+0      ,3600 ,"D"   }),  // Feb lastSun
+                     ({LDAYL(158,7),UO-3600   ,0    ,"S"   })});// Jun Sun>=1
+         case 1991:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (21,6) ,UO+0      ,3600 ,"D"   }),  // Jan Sat>=15
+                     ({FIXED(182)  ,UO-3600   ,0    ,"S"   })});// Jul 1
+         case 1992:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (21,6) ,UO+0      ,3600 ,"D"   }),  // Jan Sat>=15
+                     ({FIXED(75)   ,UO-3600   ,0    ,"S"   })});// Mar 15
+         default: // ..1978 and 1993..
+         case 1981..1990:
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Cuba
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1928:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(162)  ,UO+0      ,3600 ,"D"   }),  // Jun 10
+                     ({FIXED(284)  ,UO-3600   ,0    ,"S"   })});// Oct 10
+         case 1940..1942:
+         case 1945..1946:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(158,7),UO+0      ,3600 ,"D"   }),  // Jun Sun>=1
+                     ({LDAYL(250,7),UO-3600   ,0    ,"S"   })});// Sep Sun>=1
+         default: // ..1927:
+         case 1929..1939:
+         case 1943..1944:
+         case 1947..1964:
+            return ({({0           ,0         ,0    ,"S"   })});
+         case 1965:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(152)  ,UO+0      ,3600 ,"D"   }),  // Jun 1
+                     ({FIXED(273)  ,UO-3600   ,0    ,"S"   })});// Sep 30
+         case 1966:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(149)  ,UO+0      ,3600 ,"D"   }),  // May 29
+                     ({FIXED(275)  ,UO-3600   ,0    ,"S"   })});// Oct 2
+         case 1967:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(98)   ,UO+0      ,3600 ,"D"   }),  // Apr 8
+                     ({LDAY (257,7),UO-3600   ,0    ,"S"   })});// Sep Sun>=8
+         case 1968:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(105)  ,UO+0      ,3600 ,"D"   }),  // Apr 14
+                     ({LDAY (258,7),UO-3600   ,0    ,"S"   })});// Sep Sun>=8
+         case 1972..1974:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+0      ,3600 ,"D"   }),  // Apr lastSun
+                     ({FIX_L(281)  ,UO-3600   ,0    ,"S"   })});// Oct 8
+         case 1969..1971:
+         case 1975..1977:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+0      ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO-3600   ,0    ,"S"   })});// Oct lastSun
+         case 1978:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(127)  ,UO+0      ,3600 ,"D"   }),  // May 7
+                     ({LDAY (287,7),UO-3600   ,0    ,"S"   })});// Oct Sun>=8
+         case 1979..1980:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(80,7) ,UO+0      ,3600 ,"D"   }),  // Mar Sun>=15
+                     ({LDAYL(287,7),UO-3600   ,0    ,"S"   })});// Oct Sun>=8
+         case 1981..1985:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(131,7),UO+0      ,3600 ,"D"   }),  // May Sun>=5
+                     ({LDAYL(287,7),UO-3600   ,0    ,"S"   })});// Oct Sun>=8
+         case 1986..1989:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(79,7) ,UO+0      ,3600 ,"D"   }),  // Mar Sun>=14
+                     ({LDAYL(287,7),UO-3600   ,0    ,"S"   })});// Oct Sun>=8
+         case 1990:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (97,7) ,UO+0      ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAY (287,7),UO-3600   ,0    ,"S"   })});// Oct Sun>=8
+         case 1991..1995:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+0      ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(287,7),UO+0      ,0    ,"S"   })});// Oct Sun>=8
+         case 1996:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (98,7) ,UO+0      ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({FIXED(280)  ,UO+0      ,0    ,"S"   })});// Oct 6
+         case 1997:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (97,7) ,UO+0      ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({FIXED(285)  ,UO+0      ,0    ,"S"   })});// Oct 12
+         case 1998..1999:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (90,7) ,UO+0      ,3600 ,"D"   }),  // Mar lastSun
+                     ({LDAY (304,7),UO+0      ,0    ,"S"   })});// Oct lastSun
+         case 2000..:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+0      ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO+0      ,0    ,"S"   })});// Oct lastSun
+      }
+   }
+}
+
+class DR
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1966:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(303)  ,UO+0      ,3600 ,"D"   })});// Oct 30
+         case 1967:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({FIXED(59)   ,UO-3600   ,0    ,"S"   })});// Feb 28
+         case 1969:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAY (304,7),UO+0      ,1800 ,"HD"  })});// Oct lastSun
+         case 1970:
+            return ({({0           ,0         ,1800 ,"HD"  }),  
+                     ({FIXED(52)   ,UO-1800   ,0    ,"S"   }),  // Feb 21
+                     ({LDAY (304,7),UO+0      ,1800 ,"HD"  })});// Oct lastSun
+         case 1971:
+            return ({({0           ,0         ,1800 ,"HD"  }),  
+                     ({FIXED(20)   ,UO-1800   ,0    ,"S"   }),  // Jan 20
+                     ({LDAY (304,7),UO+0      ,1800 ,"HD"  })});// Oct lastSun
+         case 1972..1973:
+            return ({({0           ,0         ,1800 ,"HD"  }),  
+                     ({FIXED(21)   ,UO-1800   ,0    ,"S"   }),  // Jan 21
+                     ({LDAYL(304,7),UO+0      ,1800 ,"HD"  })});// Oct lastSun
+         case 1974:
+            return ({({0           ,0         ,1800 ,"HD"  }),  
+                     ({FIXED(21)   ,UO-1800   ,0    ,"S"   })});// Jan 21
+         default: // ..1965 and 1975..
+         case 1968:
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Salv
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1987..1988:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(127,7),UO+0      ,3600 ,"D"   }),  // May Sun>=1
+                     ({LDAYL(273,7),UO-3600   ,0    ,"S"   })});// Sep lastSun
+         default: // ..1986 and 1989..
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Guat
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1973:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(329)  ,UO+0      ,3600 ,"D"   })});// Nov 25
+         case 1974:
+            return ({({0           ,0         ,3600 ,"D"   }),  
+                     ({FIXED(55)   ,UO-3600   ,0    ,"S"   })});// Feb 24
+         case 1983:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(141)  ,UO+0      ,3600 ,"D"   }),  // May 21
+                     ({FIXED(265)  ,UO-3600   ,0    ,"S"   })});// Sep 22
+         case 1991:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(82)   ,UO+0      ,3600 ,"D"   }),  // Mar 23
+                     ({FIXED(250)  ,UO-3600   ,0    ,"S"   })});// Sep 7
+         default: // ..1972 and 1992..
+         case 1975..1982:
+         case 1984..1990:
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Haiti
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1983:
+            return ({({0           ,0         ,0    ,"S"   }),  // ?
+                     ({FIXED(128)  ,UO+0      ,3600 ,"D"   }),  // May 8
+                     ({LDAY (304,7),UO-3600   ,0    ,"S"   })});// Oct lastSun
+         case 1984..1987:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+0      ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO-3600   ,0    ,"S"   })});// Oct lastSun
+         case 1988..1997:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+3600   ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         default: // ..1982 and 1998..
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class Nic
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1979..1980:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(81,7) ,UO+0      ,3600 ,"D"   }),  // Mar Sun>=16
+                     ({LDAYL(180,1),UO-3600   ,0    ,"S"   })});// Jun Mon>=23
+         case 1992:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(1)    ,UO+14400  ,3600 ,"D"   }),  // Jan 1
+                     ({FIXED(268)  ,UO-3600   ,0    ,"S"   })});// Sep 24
+         default: // ..1978 and 1993..
+         case 1981..1991:
+            return ({({0           ,0         ,0    ,"S"   })});
+      }
+   }
+}
+
+class TC
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1978:
+            return ({({0           ,0         ,0    ,"S"   })});// ?
+         case 1979..1986:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+0      ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO-3600   ,0    ,"S"   })});// Oct lastSun
+         case 1987..:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(97,7) ,UO+0      ,3600 ,"D"   }),  // Apr Sun>=1
+                     ({LDAYL(304,7),UO-3600   ,0    ,"S"   })});// Oct lastSun
+      }
+   }
+}
+
+class Arg
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1930:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(335)  ,UO+0      ,3600 ,"S"   })});// Dec 1
+         case 1931:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(91)   ,UO-3600   ,0    ,""    }),  // Apr 1
+                     ({FIXED(288)  ,UO+0      ,3600 ,"S"   })});// Oct 15
+         case 1932..1939:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIX_L(60)   ,UO-3600   ,0    ,""    }),  // Mar 1
+                     ({FIX_L(305)  ,UO+0      ,3600 ,"S"   })});// Nov 1
+         case 1940:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(61)   ,UO-3600   ,0    ,""    }),  // Mar 1
+                     ({FIXED(183)  ,UO+0      ,3600 ,"S"   })});// Jul 1
+         case 1941:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(166)  ,UO-3600   ,0    ,""    }),  // Jun 15
+                     ({FIXED(288)  ,UO+0      ,3600 ,"S"   })});// Oct 15
+         case 1943:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(213)  ,UO-3600   ,0    ,""    }),  // Aug 1
+                     ({FIXED(288)  ,UO+0      ,3600 ,"S"   })});// Oct 15
+         case 1946:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(60)   ,UO-3600   ,0    ,""    }),  // Mar 1
+                     ({FIXED(274)  ,UO+0      ,3600 ,"S"   })});// Oct 1
+         case 1942:
+         case 1944..1945:
+         case 1947..1962:
+            return ({({0           ,0         ,3600 ,"S"   })});
+         case 1963:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(274)  ,UO-3600   ,0    ,""    }),  // Oct 1
+                     ({FIXED(349)  ,UO+0      ,3600 ,"S"   })});// Dec 15
+         case 1964..1966:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIX_L(60)   ,UO-3600   ,0    ,""    }),  // Mar 1
+                     ({FIX_L(288)  ,UO+0      ,3600 ,"S"   })});// Oct 15
+         case 1967:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(91)   ,UO-3600   ,0    ,""    }),  // Apr 1
+                     ({LDAY (280,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=1
+         case 1974:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(23)   ,UO+0      ,3600 ,"S"   }),  // Jan 23
+                     ({FIXED(121)  ,UO-3600   ,0    ,""    }),  // May 1
+                     ({LDAY (280,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=1
+         case 1968:
+         case 1975..1976:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAYL(97,7) ,UO-3600   ,0    ,""    }),  // Apr Sun>=1
+                     ({LDAYL(280,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=1
+         case 1969:
+         case 1977:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (97,7) ,UO-3600   ,0    ,""    })});// Apr Sun>=1
+         case 1985:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(306)  ,UO+0      ,3600 ,"S"   })});// Nov 2
+         case 1986:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(73)   ,UO-3600   ,0    ,""    }),  // Mar 14
+                     ({FIXED(298)  ,UO+0      ,3600 ,"S"   })});// Oct 25
+         case 1987:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(44)   ,UO-3600   ,0    ,""    }),  // Feb 13
+                     ({FIXED(298)  ,UO+0      ,3600 ,"S"   })});// Oct 25
+         case 1988:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(38)   ,UO-3600   ,0    ,""    }),  // Feb 7
+                     ({FIXED(336)  ,UO+0      ,3600 ,"S"   })});// Dec 1
+         case 1989..1992:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAYL(66,7) ,UO-3600   ,0    ,""    }),  // Mar Sun>=1
+                     ({LDAYL(294,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=15
+         case 1993:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (66,7) ,UO-3600   ,0    ,""    })});// Mar Sun>=1
+         default: // ..1929 and 1994..
+         case 1970..1973:
+         case 1978..1984:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Brazil
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1931:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(276)  ,UO+39600  ,3600 ,"S"   })});// Oct 3
+         case 1932:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(92)   ,UO-3600   ,0    ,""    }),  // Apr 1
+                     ({FIXED(277)  ,UO+0      ,3600 ,"S"   })});// Oct 3
+         case 1933:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(91)   ,UO-3600   ,0    ,""    })});// Apr 1
+         case 1949:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(335)  ,UO+0      ,3600 ,"S"   })});// Dec 1
+         case 1950:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(106)  ,UO+0      ,0    ,""    }),  // Apr 16
+                     ({FIXED(335)  ,UO+0      ,3600 ,"S"   })});// Dec 1
+         case 1951..1952:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIX_L(91)   ,UO-3600   ,0    ,""    }),  // Apr 1
+                     ({FIX_L(335)  ,UO+0      ,3600 ,"S"   })});// Dec 1
+         case 1963:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(343)  ,UO+0      ,3600 ,"S"   })});// Dec 9
+         case 1965:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(31)   ,UO+0      ,3600 ,"S"   }),  // Jan 31
+                     ({FIXED(90)   ,UO-3600   ,0    ,""    }),  // Mar 31
+                     ({FIXED(335)  ,UO+0      ,3600 ,"S"   })});// Dec 1
+         case 1966..1967:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(60)   ,UO-3600   ,0    ,""    }),  // Mar 1
+                     ({FIXED(305)  ,UO+0      ,3600 ,"S"   })});// Nov 1
+         case 1953:
+         case 1964:
+         case 1968:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIX_L(60)   ,UO-3600   ,0    ,""    })});// Mar 1
+         default: // ..1930:
+         case 1934..1948:
+         case 1954..1962:
+         case 1969..1984:
+            return ({({0           ,0         ,0    ,""    })});
+         case 1985:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(306)  ,UO+0      ,3600 ,"S"   })});// Nov 2
+         case 1986:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(74)   ,UO-3600   ,0    ,""    }),  // Mar 15
+                     ({FIXED(298)  ,UO+0      ,3600 ,"S"   })});// Oct 25
+         case 1987:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(45)   ,UO-3600   ,0    ,""    }),  // Feb 14
+                     ({FIXED(298)  ,UO+0      ,3600 ,"S"   })});// Oct 25
+         case 1988:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(38)   ,UO-3600   ,0    ,""    }),  // Feb 7
+                     ({FIXED(290)  ,UO+0      ,3600 ,"S"   })});// Oct 16
+         case 1989:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(29)   ,UO-3600   ,0    ,""    }),  // Jan 29
+                     ({FIXED(288)  ,UO+0      ,3600 ,"S"   })});// Oct 15
+         case 1990:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(42)   ,UO-3600   ,0    ,""    }),  // Feb 11
+                     ({FIXED(294)  ,UO+0      ,3600 ,"S"   })});// Oct 21
+         case 1991:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(48)   ,UO-3600   ,0    ,""    }),  // Feb 17
+                     ({FIXED(293)  ,UO+0      ,3600 ,"S"   })});// Oct 20
+         case 1992:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(40)   ,UO-3600   ,0    ,""    }),  // Feb 9
+                     ({FIXED(299)  ,UO+0      ,3600 ,"S"   })});// Oct 25
+         case 1993:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(31)   ,UO-3600   ,0    ,""    }),  // Jan 31
+                     ({LDAY (290,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=11
+         case 1994..1995:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (52,7) ,UO-3600   ,0    ,""    }),  // Feb Sun>=15
+                     ({LDAY (290,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=11
+         case 1996:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(42)   ,UO-3600   ,0    ,""    }),  // Feb 11
+                     ({FIXED(280)  ,UO+0      ,3600 ,"S"   })});// Oct 6
+         case 1997:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(47)   ,UO-3600   ,0    ,""    }),  // Feb 16
+                     ({FIXED(279)  ,UO+0      ,3600 ,"S"   })});// Oct 6
+         case 1998:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(60)   ,UO-3600   ,0    ,""    }),  // Mar 1
+                     ({FIXED(284)  ,UO+0      ,3600 ,"S"   })});// Oct 11
+         case 1999:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(52)   ,UO-3600   ,0    ,""    }),  // Feb 21
+                     ({LDAY (280,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=1
+         case 2000..:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAYL(59,7) ,UO-3600   ,0    ,""    }),  // Feb lastSun
+                     ({LDAYL(280,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=1
+      }
+   }
+}
+
+class Chile
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1919:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(183)  ,UO-3600   ,0    ,""    })});// Jul 2
+         case 1918:
+         case 1927:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(244)  ,UO+0      ,3600 ,"S"   })});// Sep 1
+         case 1928..1931:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIX_L(91)   ,UO-3600   ,0    ,""    }),  // Apr 1
+                     ({FIX_L(244)  ,UO+0      ,3600 ,"S"   })});// Sep 1
+         case 1932:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(92)   ,UO-3600   ,0    ,""    })});// Apr 1
+         default: // ..1917:
+         case 1920..1926:
+         case 1933..1968:
+            return ({({0           ,0         ,0    ,""    })});
+         case 1969:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (288,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=9
+         case 1998:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (74,7) ,UO-3600   ,0    ,""    }),  // Mar Sun>=9
+                     ({FIXED(270)  ,UO+0      ,3600 ,"S"   })});// Sep 27
+         case 1999:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(94)   ,UO-3600   ,0    ,""    }),  // Apr 4
+                     ({LDAY (288,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=9
+         case 1970..1997:
+         case 2000..:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAYL(74,7) ,UO-3600   ,0    ,""    }),  // Mar Sun>=9
+                     ({LDAYL(288,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=9
+      }
+   }
+}
+
+class CO
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1992:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(123)  ,UO+0      ,3600 ,"S"   }),  // May 2
+                     ({FIXED(366)  ,UO-3600   ,0    ,""    })});// Dec 31
+         default: // ..1991 and 1993..
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Falk
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1939:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (84,7) ,UO-3600   ,0    ,""    }),  // Mar Sun>=19
+                     ({FIXED(274)  ,UO+0      ,3600 ,"S"   })});// Oct 1
+         case 1938:
+         case 1940..1942:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAYL(84,7) ,UO-3600   ,0    ,""    }),  // Mar Sun>=19
+                     ({LDAYL(273,7),UO+0      ,3600 ,"S"   })});// Sep lastSun
+         case 1943:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(1)    ,UO-3600   ,0    ,""    })});// Jan 1
+         default: // ..1936:
+         case 1944..1982:
+            return ({({0           ,0         ,0    ,""    })});
+         case 1937:
+         case 1983:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (273,7),UO+0      ,3600 ,"S"   })});// Sep lastSun
+         case 1984:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (121,7),UO-3600   ,0    ,""    }),  // Apr lastSun
+                     ({FIXED(260)  ,UO+0      ,3600 ,"S"   })});// Sep 16
+         case 1985:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (120,7),UO-3600   ,0    ,""    }),  // Apr lastSun
+                     ({LDAY (258,7),UO+0      ,3600 ,"S"   })});// Sep Sun>=9
+         case 1986..1995:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAYL(112,7),UO-3600   ,0    ,""    }),  // Apr Sun>=16
+                     ({LDAYL(258,7),UO+0      ,3600 ,"S"   })});// Sep Sun>=9
+         case 1996..:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAYL(112,7),UO-3600   ,0    ,""    }),  // Apr Sun>=16
+                     ({LDAYL(257,7),UO+0      ,3600 ,"S"   })});// Sep Sun>=8
+      }
+   }
+}
+
+class Para
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         default: // ..1974:
+            return ({({0           ,0         ,0    ,""    })});// ?
+         case 1975:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(60)   ,UO+0      ,0    ,""    }),  // Mar 1
+                     ({FIXED(274)  ,UO+0      ,3600 ,"S"   })});// Oct 1
+         case 1976..1978:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIX_L(60)   ,UO-3600   ,0    ,""    }),  // Mar 1
+                     ({FIX_L(274)  ,UO+0      ,3600 ,"S"   })});// Oct 1
+         case 1989:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(91)   ,UO-3600   ,0    ,""    }),  // Apr 1
+                     ({FIXED(295)  ,UO+0      ,3600 ,"S"   })});// Oct 22
+         case 1979..1988:
+         case 1990:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIX_L(91)   ,UO-3600   ,0    ,""    }),  // Apr 1
+                     ({FIX_L(274)  ,UO+0      ,3600 ,"S"   })});// Oct 1
+         case 1991:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(91)   ,UO-3600   ,0    ,""    }),  // Apr 1
+                     ({FIXED(279)  ,UO+0      ,3600 ,"S"   })});// Oct 6
+         case 1992:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(61)   ,UO-3600   ,0    ,""    }),  // Mar 1
+                     ({FIXED(279)  ,UO+0      ,3600 ,"S"   })});// Oct 5
+         case 1993:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(90)   ,UO-3600   ,0    ,""    }),  // Mar 31
+                     ({FIXED(274)  ,UO+0      ,3600 ,"S"   })});// Oct 1
+         case 1994..1995:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (59,7) ,UO-3600   ,0    ,""    }),  // Feb lastSun
+                     ({FIXED(274)  ,UO+0      ,3600 ,"S"   })});// Oct 1
+         case 1997:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (59,7) ,UO-3600   ,0    ,""    }),  // Feb lastSun
+                     ({LDAY (280,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=1
+         case 1996:
+         case 1998:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIX_L(60)   ,UO-3600   ,0    ,""    }),  // Mar 1
+                     ({LDAYL(280,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=1
+         case 1999..:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAYL(59,7) ,UO-3600   ,0    ,""    }),  // Feb lastSun
+                     ({LDAYL(287,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=8
+      }
+   }
+}
+
+class Peru
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1938:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(1)    ,UO+0      ,3600 ,"S"   }),  // Jan 1
+                     ({FIXED(91)   ,UO-3600   ,0    ,""    }),  // Apr 1
+                     ({LDAY (273,7),UO+0      ,3600 ,"S"   })});// Sep lastSun
+         case 1939:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (89,7) ,UO-3600   ,0    ,""    }),  // Mar Sun>=24
+                     ({LDAY (273,7),UO+0      ,3600 ,"S"   })});// Sep lastSun
+         case 1940:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (90,7) ,UO-3600   ,0    ,""    })});// Mar Sun>=24
+         case 1987:
+         case 1990:
+         case 1994:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(1)    ,UO+0      ,3600 ,"S"   }),  // Jan 1
+                     ({FIXED(91)   ,UO-3600   ,0    ,""    })});// Apr 1
+         default: // ..1937 and 1995..
+         case 1941..1986:
+         case 1988..1989:
+         case 1991..1993:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class Uruguay
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1923:
+            return ({({0           ,0         ,0    ,""    }),  // ?
+                     ({FIXED(275)  ,UO+0      ,1800 ,"HS"  })});// Oct 2
+         case 1924..1925:
+            return ({({0           ,0         ,1800 ,"HS"  }),  
+                     ({FIX_L(91)   ,UO-1800   ,0    ,""    }),  // Apr 1
+                     ({FIX_L(274)  ,UO+0      ,1800 ,"HS"  })});// Oct 1
+         case 1926:
+            return ({({0           ,0         ,1800 ,"HS"  }),  
+                     ({FIXED(91)   ,UO-1800   ,0    ,""    })});// Apr 1
+         case 1933:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (304,7),UO+0      ,1800 ,"HS"  })});// Oct lastSun
+         case 1934..1935:
+            return ({({0           ,0         ,1800 ,"HS"  }),  
+                     ({LDAY (90,6) ,UO+84600  ,0    ,""    }),  // Mar Sat>=25
+                     ({LDAY (304,7),UO+0      ,1800 ,"HS"  })});// Oct lastSun
+         case 1936:
+            return ({({0           ,0         ,1800 ,"HS"  }),  
+                     ({LDAY (91,6) ,UO+84600  ,0    ,""    }),  // Mar Sat>=25
+                     ({FIXED(306)  ,UO+0      ,1800 ,"HS"  })});// Nov 1
+         case 1937..1940:
+            return ({({0           ,0         ,1800 ,"HS"  }),  
+                     ({LDAYL(90,7) ,UO-1800   ,0    ,""    }),  // Mar lastSun
+                     ({LDAYL(304,7),UO+0      ,1800 ,"HS"  })});// Oct lastSun
+         case 1941:
+            return ({({0           ,0         ,1800 ,"HS"  }),  
+                     ({LDAY (90,7) ,UO-1800   ,0    ,""    }),  // Mar lastSun
+                     ({FIXED(213)  ,UO+0      ,0    ,""    })});// Aug 1
+         case 1942:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(1)    ,UO+0      ,1800 ,"HS"  }),  // Jan 1
+                     ({FIXED(348)  ,UO-1800   ,3600 ,"S"   })});// Dec 14
+         case 1943:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(73)   ,UO-3600   ,0    ,""    })});// Mar 14
+         case 1959:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(144)  ,UO+0      ,3600 ,"S"   }),  // May 24
+                     ({FIXED(319)  ,UO-3600   ,0    ,""    })});// Nov 15
+         case 1960:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(17)   ,UO+0      ,3600 ,"S"   }),  // Jan 17
+                     ({FIXED(66)   ,UO-3600   ,0    ,""    })});// Mar 6
+         case 1965:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+0      ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({FIXED(269)  ,UO-3600   ,0    ,""    })});// Sep 26
+         case 1966..1967:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({LDAY (97,7) ,UO+0      ,3600 ,"S"   }),  // Apr Sun>=1
+                     ({FIXED(304)  ,UO-3600   ,0    ,""    })});// Oct 31
+         case 1968..1970:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIX_L(147)  ,UO+0      ,1800 ,"HS"  }),  // May 27
+                     ({FIX_L(336)  ,UO-1800   ,0    ,""    })});// Dec 2
+         case 1972:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(115)  ,UO+0      ,3600 ,"S"   }),  // Apr 24
+                     ({FIXED(228)  ,UO-3600   ,0    ,""    })});// Aug 15
+         case 1974:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(69)   ,UO+0      ,1800 ,"HS"  }),  // Mar 10
+                     ({FIXED(356)  ,UO-1800   ,3600 ,"S"   })});// Dec 22
+         case 1975:
+            return ({({0           ,0         ,3600 ,"S"   })});
+         case 1976:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(275)  ,UO-3600   ,0    ,""    })});// Oct 1
+         case 1977:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(338)  ,UO+0      ,3600 ,"S"   })});// Dec 4
+         case 1978:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(91)   ,UO-3600   ,0    ,""    })});// Apr 1
+         case 1979:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(274)  ,UO+0      ,3600 ,"S"   })});// Oct 1
+         case 1980:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(122)  ,UO-3600   ,0    ,""    })});// May 1
+         case 1987:
+            return ({({0           ,0         ,0    ,""    }),  
+                     ({FIXED(348)  ,UO+0      ,3600 ,"S"   })});// Dec 14
+         case 1988:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(74)   ,UO-3600   ,0    ,""    }),  // Mar 14
+                     ({FIXED(346)  ,UO+0      ,3600 ,"S"   })});// Dec 11
+         case 1989:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(71)   ,UO-3600   ,0    ,""    }),  // Mar 12
+                     ({FIXED(302)  ,UO+0      ,3600 ,"S"   })});// Oct 29
+         case 1990..1991:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (66,7) ,UO-3600   ,0    ,""    }),  // Mar Sun>=1
+                     ({LDAY (300,7),UO+0      ,3600 ,"S"   })});// Oct Sun>=21
+         case 1992:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({LDAY (67,7) ,UO-3600   ,0    ,""    }),  // Mar Sun>=1
+                     ({FIXED(292)  ,UO+0      ,3600 ,"S"   })});// Oct 18
+         case 1993:
+            return ({({0           ,0         ,3600 ,"S"   }),  
+                     ({FIXED(59)   ,UO-3600   ,0    ,""    })});// Feb 28
+         default: // ..1922 and 1994..
+         case 1927..1932:
+         case 1944..1958:
+         case 1961..1964:
+         case 1971:
+         case 1973:
+         case 1981..1986:
+            return ({({0           ,0         ,0    ,""    })});
+      }
+   }
+}
+
+class SystemV
+{
+   inherit TZRules;
+   static array(array(string|int)) jd_year_periods(int jd)
+   {
+      [int y,int yjd,int leap]=gregorian_yjd(jd);
+      switch (y)
+      {
+         case 1974:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(6)    ,UO+7200   ,3600 ,"D"   }),  // Jan 6
+                     ({LDAY (334,7),UO+3600   ,0    ,"S"   })});// Nov lastSun
+         case 1975:
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({FIXED(54)   ,UO+7200   ,3600 ,"D"   }),  // Feb 23
+                     ({LDAY (304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+         default: // ..1973 and 1976..
+            return ({({0           ,0         ,0    ,"S"   }),  
+                     ({LDAYL(120,7),UO+7200   ,3600 ,"D"   }),  // Apr lastSun
+                     ({LDAYL(304,7),UO+3600   ,0    ,"S"   })});// Oct lastSun
+      }
+   }
+}
+
diff --git a/lib/modules/Calendar.pmod/TZs.h b/lib/modules/Calendar.pmod/TZs.h
new file mode 100644
index 0000000000000000000000000000000000000000..0bf033cef8a332cf8e7a029ccb1ba7c9db93d136
--- /dev/null
+++ b/lib/modules/Calendar.pmod/TZs.h
@@ -0,0 +1,6096 @@
+// ----------------------------------------------------------------
+// Timezones
+//
+// NOTE: this file is generated by mkrules.pike;
+//       please do not edit manually /Mirar
+// ----------------------------------------------------------------
+
+import ".";
+
+// ----------------------------------------------------------------------
+// Timezones
+// ----------------------------------------------------------------------
+
+Ruleset.Timezone Indian_Chagos=Ruleset.Timezone(-18000,"IOT");
+Ruleset.Timezone Indian_Cocos=Ruleset.Timezone(-23400,"CCT");
+Ruleset.Timezone Pacific_Chatham=TZrules.Chatham(-45900,"CHA%sT");
+Ruleset.Timezone NZ_CHAT=Pacific_Chatham;
+Ruleset.Timezone Pacific_Johnston=Ruleset.Timezone(36000,"HST");
+Ruleset.Timezone Etc_GMT=Ruleset.Timezone(0,"GMT");
+Ruleset.Timezone GMT=Etc_GMT;
+Ruleset.Timezone Etc_Greenwich=Etc_GMT;
+Ruleset.Timezone Etc_GMT_0=Etc_GMT;
+Ruleset.Timezone Etc_GMTp0=Etc_GMT;
+Ruleset.Timezone Etc_GMT0=Etc_GMT;
+Ruleset.Timezone Etc_UTC=Ruleset.Timezone(0,"UTC");
+Ruleset.Timezone UTC=Etc_UTC;
+Ruleset.Timezone Etc_Universal=Etc_UTC;
+Ruleset.Timezone Etc_Zulu=Etc_UTC;
+Ruleset.Timezone Etc_UCT=Ruleset.Timezone(0,"UCT");
+Ruleset.Timezone UCT=Etc_UCT;
+Ruleset.Timezone Etc_GMT_14=Ruleset.Timezone(-50400,"GMT-14");
+Ruleset.Timezone Etc_GMT_13=Ruleset.Timezone(-46800,"GMT-13");
+Ruleset.Timezone Etc_GMT_12=Ruleset.Timezone(-43200,"GMT-12");
+Ruleset.Timezone Etc_GMT_11=Ruleset.Timezone(-39600,"GMT-11");
+Ruleset.Timezone Etc_GMT_10=Ruleset.Timezone(-36000,"GMT-10");
+Ruleset.Timezone Etc_GMT_9=Ruleset.Timezone(-32400,"GMT-9");
+Ruleset.Timezone Etc_GMT_8=Ruleset.Timezone(-28800,"GMT-8");
+Ruleset.Timezone Etc_GMT_7=Ruleset.Timezone(-25200,"GMT-7");
+Ruleset.Timezone Etc_GMT_6=Ruleset.Timezone(-21600,"GMT-6");
+Ruleset.Timezone Etc_GMT_5=Ruleset.Timezone(-18000,"GMT-5");
+Ruleset.Timezone Etc_GMT_4=Ruleset.Timezone(-14400,"GMT-4");
+Ruleset.Timezone Etc_GMT_3=Ruleset.Timezone(-10800,"GMT-3");
+Ruleset.Timezone Etc_GMT_2=Ruleset.Timezone(-7200,"GMT-2");
+Ruleset.Timezone Etc_GMT_1=Ruleset.Timezone(-3600,"GMT-1");
+Ruleset.Timezone Etc_GMTp1=Ruleset.Timezone(3600,"GMT+1");
+Ruleset.Timezone Etc_GMTp2=Ruleset.Timezone(7200,"GMT+2");
+Ruleset.Timezone Etc_GMTp3=Ruleset.Timezone(10800,"GMT+3");
+Ruleset.Timezone Etc_GMTp4=Ruleset.Timezone(14400,"GMT+4");
+Ruleset.Timezone Etc_GMTp5=Ruleset.Timezone(18000,"GMT+5");
+Ruleset.Timezone Etc_GMTp6=Ruleset.Timezone(21600,"GMT+6");
+Ruleset.Timezone Etc_GMTp7=Ruleset.Timezone(25200,"GMT+7");
+Ruleset.Timezone Etc_GMTp8=Ruleset.Timezone(28800,"GMT+8");
+Ruleset.Timezone Etc_GMTp9=Ruleset.Timezone(32400,"GMT+9");
+Ruleset.Timezone Etc_GMTp10=Ruleset.Timezone(36000,"GMT+10");
+Ruleset.Timezone Etc_GMTp11=Ruleset.Timezone(39600,"GMT+11");
+Ruleset.Timezone Etc_GMTp12=Ruleset.Timezone(43200,"GMT+12");
+Ruleset.Timezone WET=TZrules.EU(0,"WE%sT");
+Ruleset.Timezone CET=TZrules.C_Eur(-3600,"CE%sT");
+Ruleset.Timezone MET=TZrules.C_Eur(-3600,"ME%sT");
+Ruleset.Timezone EET=TZrules.EU(-7200,"EE%sT");
+Ruleset.Timezone Atlantic_Jan_Mayen=Ruleset.Timezone(3600,"EGT");
+Ruleset.Timezone SystemV_AST4ADT=TZrules.SystemV(14400,"A%sT");
+Ruleset.Timezone SystemV_EST5EDT=TZrules.SystemV(18000,"E%sT");
+Ruleset.Timezone SystemV_CST6CDT=TZrules.SystemV(21600,"C%sT");
+Ruleset.Timezone SystemV_MST7MDT=TZrules.SystemV(25200,"M%sT");
+Ruleset.Timezone SystemV_PST8PDT=TZrules.SystemV(28800,"P%sT");
+Ruleset.Timezone SystemV_YST9YDT=TZrules.SystemV(32400,"Y%sT");
+Ruleset.Timezone SystemV_AST4=Ruleset.Timezone(14400,"AST");
+Ruleset.Timezone SystemV_EST5=Ruleset.Timezone(18000,"EST");
+Ruleset.Timezone SystemV_CST6=Ruleset.Timezone(21600,"CST");
+Ruleset.Timezone SystemV_MST7=Ruleset.Timezone(25200,"MST");
+Ruleset.Timezone SystemV_PST8=Ruleset.Timezone(28800,"PST");
+Ruleset.Timezone SystemV_YST9=Ruleset.Timezone(32400,"YST");
+Ruleset.Timezone SystemV_HST10=Ruleset.Timezone(36000,"HST");
+
+// ----------------------------------------------------------------------
+// Timezones with an attitude
+// ----------------------------------------------------------------------
+
+class Africa_Algiers
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=357523200) // from 1981 May 
+         return tz6 || (tz6=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=309747600) // from 1979 Oct 26 
+         return tz3 || (tz3=TZrules.Algeria(0,"WE%sT"));
+      if (ux>=246240000) // from 1977 Oct 21 
+         return tz4 || (tz4=TZrules.Algeria(-3600,"CE%sT"));
+      if (ux>=-212029200) // from 1963 Apr 14 
+         return tz3 || (tz3=TZrules.Algeria(0,"WE%sT"));
+      if (ux>=-439430400) // from 1956 Jan 29 
+         return tz6 || (tz6=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=-733273200) // from 1946 Oct  7 
+         return tz5 || (tz5=Ruleset.Timezone(0,"WET"));
+      if (ux>=-942012000) // from 1940 Feb 25 2:00 
+         return tz4 || (tz4=TZrules.Algeria(-3600,"CE%sT"));
+      if (ux>=-1855958961) // from 1911 Mar 11 
+         return tz3 || (tz3=TZrules.Algeria(0,"WE%sT"));
+      if (ux>=-2486679072) // from 1891 Mar 15 0:01 Paris Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-561,"PMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-732,"LMT"));
+   }
+}
+
+class Africa_Luanda
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1849395124) // from 1911 May 26 
+         return tz3 || (tz3=Ruleset.Timezone(-3600,"WAT"));
+      if (ux>=-2461452776) // from 1892 Luanda Mean Time?
+         return tz2 || (tz2=Ruleset.Timezone(-3124,"LMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-3176,"LMT"));
+   }
+}
+
+class Africa_Porto_Novo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1131235200) // from 1934 Feb 26 
+         return tz3 || (tz3=Ruleset.Timezone(-3600,"WAT"));
+      if (ux>=-1830384628) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(0,"GMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-628,"LMT"));
+   }
+}
+
+class Africa_Gaborone
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-813805200) // from 1944 Mar 19 2:00 
+         return tz2 || (tz2=Ruleset.Timezone(-7200,"CAT"));
+      if (ux>=-829526400) // from 1943 Sep 19 2:00 
+         return tz3 || (tz3=Ruleset.Timezone(-10800,"CAST"));
+      if (ux>=-2682294220) // from 1885 
+         return tz2 || (tz2=Ruleset.Timezone(-7200,"CAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-6220,"LMT"));
+   }
+}
+
+class Africa_Ouagadougou
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1830383636) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(0,"GMT"));
+      return tz1 || (tz1=Ruleset.Timezone(364,"LMT"));
+   }
+}
+
+class Africa_Bujumbura
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2524528648) // from 1890 
+         return tz2 || (tz2=Ruleset.Timezone(-7200,"CAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-7048,"LMT"));
+   }
+}
+
+class Africa_Douala
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1830386328) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(-3600,"WAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-2328,"LMT"));
+   }
+}
+
+class Atlantic_Cape_Verde
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=186120000) // from 1975 Nov 25 2:00 
+         return tz4 || (tz4=Ruleset.Timezone(3600,"CVT"));
+      if (ux>=-764118000) // from 1945 Oct 15 
+         return tz2 || (tz2=Ruleset.Timezone(7200,"CVT"));
+      if (ux>=-862610400) // from 1942 Sep 
+         return tz3 || (tz3=Ruleset.Timezone(3600,"CVST"));
+      if (ux>=-1988144756) // from 1907 
+         return tz2 || (tz2=Ruleset.Timezone(7200,"CVT"));
+      // Praia
+      return tz1 || (tz1=Ruleset.Timezone(5644,"LMT"));
+   }
+}
+
+class Africa_Bangui
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1830388460) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(-3600,"WAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-4460,"LMT"));
+   }
+}
+
+class Africa_Ndjamena
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=321314400) // from 1980 Mar  8 
+         return tz2 || (tz2=Ruleset.Timezone(-3600,"WAT"));
+      if (ux>=308703600) // from 1979 Oct 14 
+         return tz3 || (tz3=Ruleset.Timezone(-7200,"WAST"));
+      if (ux>=-1830387612) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(-3600,"WAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-3612,"LMT"));
+   }
+}
+
+class Indian_Comoro
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1846291984) // from 1911 Jul 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"EAT"));
+      // Moroni, Gran Comoro
+      return tz1 || (tz1=Ruleset.Timezone(-10384,"LMT"));
+   }
+}
+
+class Africa_Kinshasa
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2276643672) // from 1897 Nov 9 
+         return tz2 || (tz2=Ruleset.Timezone(-3600,"WAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-3672,"LMT"));
+   }
+}
+
+class Africa_Lubumbashi
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2276646592) // from 1897 Nov 9 
+         return tz2 || (tz2=Ruleset.Timezone(-7200,"CAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-6592,"LMT"));
+   }
+}
+
+class Africa_Brazzaville
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1830387668) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(-3600,"WAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-3668,"LMT"));
+   }
+}
+
+class Africa_Abidjan
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1830383032) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(0,"GMT"));
+      return tz1 || (tz1=Ruleset.Timezone(968,"LMT"));
+   }
+}
+
+class Africa_Djibouti
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1846291956) // from 1911 Jul 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"EAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-10356,"LMT"));
+   }
+}
+
+class Africa_Cairo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2185409100) // from 1900 Oct 
+         return tz2 || (tz2=TZrules.Egypt(-7200,"EE%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-7500,"LMT"));
+   }
+}
+constant Egypt=Africa_Cairo;
+
+class Africa_Malabo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-190857600) // from 1963 Dec 15 
+         return tz3 || (tz3=Ruleset.Timezone(-3600,"WAT"));
+      if (ux>=-1830386108) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(0,"GMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-2108,"LMT"));
+   }
+}
+
+class Africa_Asmera
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1062210920) // from 1936 May 5 
+         return tz4 || (tz4=Ruleset.Timezone(-10800,"EAT"));
+      if (ux>=-2524530932) // from 1890 Adis Dera MT
+         return tz3 || (tz3=Ruleset.Timezone(-9320,"ADMT"));
+      if (ux>=-3155682932) // from 1870 Asmera Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-9332,"AMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-9332,"LMT"));
+   }
+}
+
+class Africa_Addis_Ababa
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1062210920) // from 1936 May 5 
+         return tz3 || (tz3=Ruleset.Timezone(-10800,"EAT"));
+      if (ux>=-3155682888) // from 1870 Adis Dera MT
+         return tz2 || (tz2=Ruleset.Timezone(-9320,"ADMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-9288,"LMT"));
+   }
+}
+
+class Africa_Libreville
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1830386268) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(-3600,"WAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-2268,"LMT"));
+   }
+}
+
+class Africa_Banjul
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-189385200) // from 1964 
+         return tz4 || (tz4=Ruleset.Timezone(0,"GMT"));
+      if (ux>=-1104533604) // from 1935 
+         return tz3 || (tz3=Ruleset.Timezone(3600,"WAT"));
+      if (ux>=-1830380004) // from 1912 Banjul Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(3996,"BMT"));
+      return tz1 || (tz1=Ruleset.Timezone(3996,"LMT"));
+   }
+}
+
+class Africa_Accra
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1640995148) // from 1918 
+         return tz2 || (tz2=TZrules.Ghana(0,"%s"));
+      return tz1 || (tz1=Ruleset.Timezone(52,"LMT"));
+   }
+}
+
+class Africa_Conakry
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-315615600) // from 1960 
+         return tz2 || (tz2=Ruleset.Timezone(0,"GMT"));
+      if (ux>=-1131235200) // from 1934 Feb 26 
+         return tz3 || (tz3=Ruleset.Timezone(3600,"WAT"));
+      if (ux>=-1830380708) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(0,"GMT"));
+      return tz1 || (tz1=Ruleset.Timezone(3292,"LMT"));
+   }
+}
+
+class Africa_Bissau
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=157770000) // from 1975 
+         return tz3 || (tz3=Ruleset.Timezone(0,"GMT"));
+      if (ux>=-1849388260) // from 1911 May 26 
+         return tz2 || (tz2=Ruleset.Timezone(3600,"WAT"));
+      return tz1 || (tz1=Ruleset.Timezone(3740,"LMT"));
+   }
+}
+
+class Africa_Nairobi
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-315629100) // from 1960 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"EAT"));
+      if (ux>=-946780200) // from 1940 
+         return tz4 || (tz4=Ruleset.Timezone(-9900,"BEAUT"));
+      if (ux>=-1262314800) // from 1930 
+         return tz3 || (tz3=Ruleset.Timezone(-9000,"BEAT"));
+      if (ux>=-1309746436) // from 1928 Jul 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"EAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-8836,"LMT"));
+   }
+}
+
+class Africa_Maseru
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-813805200) // from 1944 Mar 19 2:00 
+         return tz2 || (tz2=Ruleset.Timezone(-7200,"SAST"));
+      if (ux>=-829526400) // from 1943 Sep 19 2:00 
+         return tz3 || (tz3=Ruleset.Timezone(-10800,"SAST"));
+      if (ux>=-2109289800) // from 1903 Mar 
+         return tz2 || (tz2=Ruleset.Timezone(-7200,"SAST"));
+      return tz1 || (tz1=Ruleset.Timezone(-6600,"LMT"));
+   }
+}
+
+class Africa_Monrovia
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=73529070) // from 1972 May 
+         return tz4 || (tz4=Ruleset.Timezone(0,"GMT"));
+      if (ux>=-1604359012) // from 1919 Mar Liberia Time
+         return tz3 || (tz3=Ruleset.Timezone(2670,"LRT"));
+      if (ux>=-2776979812) // from 1882 Monrovia Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(2588,"MMT"));
+      return tz1 || (tz1=Ruleset.Timezone(2588,"LMT"));
+   }
+}
+
+class Africa_Tripoli
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=875916000) // from 1997 Oct  4 
+         return tz3 || (tz3=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=860108400) // from 1997 Apr  4 
+         return tz5 || (tz5=Ruleset.Timezone(-7200,"CEST"));
+      if (ux>=844034400) // from 1996 Sep 30 
+         return tz4 || (tz4=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=641782800) // from 1990 May  4 
+         return tz3 || (tz3=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=378684000) // from 1982 
+         return tz2 || (tz2=TZrules.Libya(-3600,"CE%sT"));
+      if (ux>=-347151600) // from 1959 
+         return tz3 || (tz3=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=-1577926364) // from 1920 
+         return tz2 || (tz2=TZrules.Libya(-3600,"CE%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-3164,"LMT"));
+   }
+}
+constant Libya=Africa_Tripoli;
+
+class Indian_Antananarivo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-492062400) // from 1954 May 29 23:00s 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"EAT"));
+      if (ux>=-499924800) // from 1954 Feb 27 23:00s 
+         return tz3 || (tz3=Ruleset.Timezone(-14400,"EAST"));
+      if (ux>=-1846293004) // from 1911 Jul 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"EAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-11404,"LMT"));
+   }
+}
+
+class Africa_Blantyre
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2109291600) // from 1903 Mar 
+         return tz2 || (tz2=Ruleset.Timezone(-7200,"CAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-8400,"LMT"));
+   }
+}
+
+class Africa_Bamako
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-300841200) // from 1960 Jun 20 
+         return tz2 || (tz2=Ruleset.Timezone(0,"GMT"));
+      if (ux>=-1131235200) // from 1934 Feb 26 
+         return tz3 || (tz3=Ruleset.Timezone(3600,"WAT"));
+      if (ux>=-1830382080) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(0,"GMT"));
+      return tz1 || (tz1=Ruleset.Timezone(1920,"LMT"));
+   }
+}
+
+class Africa_Timbuktu
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1830383276) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(0,"GMT"));
+      return tz1 || (tz1=Ruleset.Timezone(724,"LMT"));
+   }
+}
+
+class Africa_Nouakchott
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-286930800) // from 1960 Nov 28 
+         return tz2 || (tz2=Ruleset.Timezone(0,"GMT"));
+      if (ux>=-1131235200) // from 1934 Feb 26 
+         return tz3 || (tz3=Ruleset.Timezone(3600,"WAT"));
+      if (ux>=-1830380172) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(0,"GMT"));
+      return tz1 || (tz1=Ruleset.Timezone(3828,"LMT"));
+   }
+}
+
+class Indian_Mauritius
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1988164200) // from 1907 Mauritius Time
+         return tz2 || (tz2=Ruleset.Timezone(-14400,"MUT"));
+      // Port Louis
+      return tz1 || (tz1=Ruleset.Timezone(-13800,"LMT"));
+   }
+}
+
+class Indian_Mayotte
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1846292456) // from 1911 Jul 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"EAT"));
+      // Mamoutzou
+      return tz1 || (tz1=Ruleset.Timezone(-10856,"LMT"));
+   }
+}
+
+class Africa_Casablanca
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=504918000) // from 1986 
+         return tz4 || (tz4=Ruleset.Timezone(0,"WET"));
+      if (ux>=448243200) // from 1984 Mar 16 
+         return tz3 || (tz3=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=-1773012580) // from 1913 Oct 26 
+         return tz2 || (tz2=TZrules.Morocco(0,"WE%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(1820,"LMT"));
+   }
+}
+
+class Africa_El_Aaiun
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=198291600) // from 1976 Apr 14 
+         return tz3 || (tz3=Ruleset.Timezone(0,"WET"));
+      if (ux>=-1136070432) // from 1934 Jan 
+         return tz2 || (tz2=Ruleset.Timezone(3600,"WAT"));
+      return tz1 || (tz1=Ruleset.Timezone(3168,"LMT"));
+   }
+}
+
+class Africa_Maputo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2109291020) // from 1903 Mar 
+         return tz2 || (tz2=Ruleset.Timezone(-7200,"CAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-7820,"LMT"));
+   }
+}
+
+class Africa_Windhoek
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=765324000) // from 1994 Apr  3 
+         return tz6 || (tz6=TZrules.Namibia(-3600,"WA%sT"));
+      if (ux>=637970400) // from 1990 Mar 21 
+         return tz5 || (tz5=Ruleset.Timezone(-7200,"CAT"));
+      if (ux>=-845254800) // from 1943 Mar 21 2:00 independence
+         return tz3 || (tz3=Ruleset.Timezone(-7200,"SAST"));
+      if (ux>=-860976000) // from 1942 Sep 20 2:00 
+         return tz4 || (tz4=Ruleset.Timezone(-10800,"SAST"));
+      if (ux>=-2109288600) // from 1903 Mar 
+         return tz3 || (tz3=Ruleset.Timezone(-7200,"SAST"));
+      if (ux>=-2458170504) // from 1892 Feb 8 SW Africa Time
+         return tz2 || (tz2=Ruleset.Timezone(-5400,"SWAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-4104,"LMT"));
+   }
+}
+
+class Africa_Niamey
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-315619200) // from 1960 
+         return tz4 || (tz4=Ruleset.Timezone(-3600,"WAT"));
+      if (ux>=-1131231600) // from 1934 Feb 26 
+         return tz3 || (tz3=Ruleset.Timezone(0,"GMT"));
+      if (ux>=-1830384508) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(3600,"WAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-508,"LMT"));
+   }
+}
+
+class Africa_Lagos
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1588464816) // from 1919 Sep 
+         return tz2 || (tz2=Ruleset.Timezone(-3600,"WAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-816,"LMT"));
+   }
+}
+
+class Indian_Reunion
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1848886912) // from 1911 Jun Reunion Time
+         return tz2 || (tz2=Ruleset.Timezone(-14400,"RET"));
+      // Saint-Denis
+      return tz1 || (tz1=Ruleset.Timezone(-13312,"LMT"));
+   }
+}
+
+class Africa_Kigali
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1091498416) // from 1935 Jun 
+         return tz2 || (tz2=Ruleset.Timezone(-7200,"CAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-7216,"LMT"));
+   }
+}
+
+class Atlantic_St_Helena
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-599614632) // from 1951 
+         return tz3 || (tz3=Ruleset.Timezone(0,"GMT"));
+      if (ux>=-2524520232) // from 1890 Jamestown Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(1368,"JMT"));
+      // Jamestown
+      return tz1 || (tz1=Ruleset.Timezone(1368,"LMT"));
+   }
+}
+
+class Africa_Sao_Tome
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1830381808) // from 1912 
+         return tz3 || (tz3=Ruleset.Timezone(0,"GMT"));
+      if (ux>=-2713912016) // from 1884 Lisbon Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(2192,"LMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-1616,"LMT"));
+   }
+}
+
+class Africa_Dakar
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-902098800) // from 1941 Jun 
+         return tz3 || (tz3=Ruleset.Timezone(0,"GMT"));
+      if (ux>=-1830379816) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(3600,"WAT"));
+      return tz1 || (tz1=Ruleset.Timezone(4184,"LMT"));
+   }
+}
+
+class Indian_Mahe
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2006653308) // from 1906 Jun Seychelles Time
+         return tz2 || (tz2=Ruleset.Timezone(-14400,"SCT"));
+      // Victoria
+      return tz1 || (tz1=Ruleset.Timezone(-13308,"LMT"));
+   }
+}
+
+class Africa_Freetown
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-410230800) // from 1957 
+         return tz4 || (tz4=TZrules.SL(0,"%s"));
+      if (ux>=-1785712020) // from 1913 Jun 
+         return tz3 || (tz3=TZrules.SL(3600,"%s"));
+      if (ux>=-2776979220) // from 1882 Freetown Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(3180,"FMT"));
+      return tz1 || (tz1=Ruleset.Timezone(3180,"LMT"));
+   }
+}
+
+class Africa_Mogadishu
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-410236200) // from 1957 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"EAT"));
+      if (ux>=-1230778800) // from 1931 
+         return tz3 || (tz3=Ruleset.Timezone(-9000,"BEAT"));
+      if (ux>=-2403572488) // from 1893 Nov 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"EAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-10888,"LMT"));
+   }
+}
+
+class Africa_Johannesburg
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2109288600) // from 1903 Mar 
+         return tz3 || (tz3=TZrules.SA(-7200,"SAST"));
+      if (ux>=-2458173120) // from 1892 Feb 8 
+         return tz2 || (tz2=Ruleset.Timezone(-5400,"SAST"));
+      return tz1 || (tz1=Ruleset.Timezone(-6720,"LMT"));
+   }
+}
+
+class Africa_Khartoum
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=947944800) // from 2000 Jan 15 12:00 
+         return tz3 || (tz3=Ruleset.Timezone(-10800,"EAT"));
+      if (ux>=-1230775808) // from 1931 
+         return tz2 || (tz2=TZrules.Sudan(-7200,"CA%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-7808,"LMT"));
+   }
+}
+
+class Africa_Mbabane
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2109290664) // from 1903 Mar 
+         return tz2 || (tz2=Ruleset.Timezone(-7200,"SAST"));
+      return tz1 || (tz1=Ruleset.Timezone(-7464,"LMT"));
+   }
+}
+
+class Africa_Dar_es_Salaam
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-284006700) // from 1961 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"EAT"));
+      if (ux>=-694321200) // from 1948 
+         return tz3 || (tz3=Ruleset.Timezone(-9900,"BEAUT"));
+      if (ux>=-1230777428) // from 1931 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"EAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-9428,"LMT"));
+   }
+}
+
+class Africa_Lome
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2429827492) // from 1893 
+         return tz2 || (tz2=Ruleset.Timezone(0,"GMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-292,"LMT"));
+   }
+}
+
+class Africa_Tunis
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1855958961) // from 1911 Mar 11 
+         return tz3 || (tz3=TZrules.Tunisia(-3600,"CE%sT"));
+      if (ux>=-2797202444) // from 1881 May 12 Paris Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-561,"PMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-2444,"LMT"));
+   }
+}
+
+class Africa_Kampala
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-410237100) // from 1957 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"EAT"));
+      if (ux>=-694319400) // from 1948 
+         return tz4 || (tz4=Ruleset.Timezone(-9900,"BEAUT"));
+      if (ux>=-1262314800) // from 1930 
+         return tz3 || (tz3=Ruleset.Timezone(-9000,"BEAT"));
+      if (ux>=-1309745380) // from 1928 Jul 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"EAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-7780,"LMT"));
+   }
+}
+
+class Africa_Lusaka
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2109289988) // from 1903 Mar 
+         return tz2 || (tz2=Ruleset.Timezone(-7200,"CAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-6788,"LMT"));
+   }
+}
+
+class Africa_Harare
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2109290652) // from 1903 Mar 
+         return tz2 || (tz2=Ruleset.Timezone(-7200,"CAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-7452,"LMT"));
+   }
+}
+
+class Antarctica_Casey
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-31536000) // from 1969 Western (Aus) Standard Time
+         return tz2 || (tz2=Ruleset.Timezone(-28800,"WST"));
+      return tz1 || (tz1=Ruleset.Timezone(0,"___"));
+   }
+}
+
+class Antarctica_Davis
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-28857600) // from 1969 Feb 
+         return tz2 || (tz2=Ruleset.Timezone(-25200,"DAVT"));
+      if (ux>=-163062000) // from 1964 Nov 
+         return tz1 || (tz1=Ruleset.Timezone(0,"___"));
+      if (ux>=-409190400) // from 1957 Jan 13 Davis Time
+         return tz2 || (tz2=Ruleset.Timezone(-25200,"DAVT"));
+      return tz1 || (tz1=Ruleset.Timezone(0,"___"));
+   }
+}
+
+class Antarctica_Mawson
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-501206400) // from 1954 Feb 13 Mawson Time
+         return tz2 || (tz2=Ruleset.Timezone(-21600,"MAWT"));
+      return tz1 || (tz1=Ruleset.Timezone(0,"___"));
+   }
+}
+
+class Indian_Kerguelen
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-631152000) // from 1950 ISO code TF Time
+         return tz2 || (tz2=Ruleset.Timezone(-18000,"TFT"));
+      // Port-aux-Francais
+      return tz1 || (tz1=Ruleset.Timezone(0,"___"));
+   }
+}
+
+class Antarctica_DumontDUrville
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-415497600) // from 1956 Nov Dumont-d'Urville Time
+         return tz3 || (tz3=Ruleset.Timezone(-36000,"DDUT"));
+      if (ux>=-566992800) // from 1952 Jan 14 
+         return tz1 || (tz1=Ruleset.Timezone(0,"___"));
+      if (ux>=-725846400) // from 1947 Port-Martin Time
+         return tz2 || (tz2=Ruleset.Timezone(-36000,"PMT"));
+      return tz1 || (tz1=Ruleset.Timezone(0,"___"));
+   }
+}
+
+class Antarctica_Syowa
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-407808000) // from 1957 Jan 29 Syowa Time
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"SYOT"));
+      return tz1 || (tz1=Ruleset.Timezone(0,"___"));
+   }
+}
+
+class Antarctica_Palmer
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=389048400) // from 1982 May 
+         return tz4 || (tz4=TZrules.ChileAQ(14400,"CL%sT"));
+      if (ux>=-7617600) // from 1969 Oct 5 
+         return tz3 || (tz3=TZrules.ArgAQ(10800,"AR%sT"));
+      if (ux>=-157766400) // from 1965 
+         return tz2 || (tz2=TZrules.ArgAQ(14400,"AR%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(0,"___"));
+   }
+}
+
+class Antarctica_McMurdo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-441849600) // from 1956 
+         return tz2 || (tz2=TZrules.NZAQ(-43200,"NZ%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(0,"___"));
+   }
+}
+constant Antarctica_South_Pole=Antarctica_McMurdo;
+
+class Asia_Kabul
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-788932800) // from 1945 
+         return tz3 || (tz3=Ruleset.Timezone(-16200,"AFT"));
+      if (ux>=-2524538208) // from 1890 
+         return tz2 || (tz2=Ruleset.Timezone(-14400,"AFT"));
+      return tz1 || (tz1=Ruleset.Timezone(-16608,"LMT"));
+   }
+}
+
+class Asia_Yerevan
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=852062400) // from 1997 
+         return tz7 || (tz7=TZrules.RussiaAsia(-14400,"AM%sT"));
+      if (ux>=811897200) // from 1995 Sep 24 2:00s 
+         return tz6 || (tz6=Ruleset.Timezone(-14400,"AMT"));
+      if (ux>=685569600) // from 1991 Sep 23 
+         return tz5 || (tz5=TZrules.RussiaAsia(-10800,"AM%sT"));
+      if (ux>=670370400) // from 1991 Mar 31 2:00s independence
+         return tz4 || (tz4=Ruleset.Timezone(-14400,"YERST"));
+      if (ux>=-405140400) // from 1957 Mar 
+         return tz3 || (tz3=TZrules.RussiaAsia(-14400,"YER%sT"));
+      if (ux>=-1441162680) // from 1924 May  2 Yerevan Time
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"YERT"));
+      return tz1 || (tz1=Ruleset.Timezone(-10680,"LMT"));
+   }
+}
+
+class Asia_Baku
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7,tz8;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=852091200) // from 1997 
+         return tz8 || (tz8=TZrules.Azer(-14400,"AZ%sT"));
+      if (ux>=820440000) // from 1996 
+         return tz7 || (tz7=TZrules.EUAsia(-14400,"AZ%sT"));
+      if (ux>=715320000) // from 1992 Sep lastSun 2:00s Azerbaijan time
+         return tz6 || (tz6=Ruleset.Timezone(-14400,"AZT"));
+      if (ux>=683496000) // from 1991 Aug 30 
+         return tz5 || (tz5=TZrules.RussiaAsia(-10800,"AZ%sT"));
+      if (ux>=670370400) // from 1991 Mar 31 2:00s independence
+         return tz4 || (tz4=Ruleset.Timezone(-14400,"BAKST"));
+      if (ux>=-405140400) // from 1957 Mar 
+         return tz3 || (tz3=TZrules.RussiaAsia(-14400,"BAK%sT"));
+      if (ux>=-1441163964) // from 1924 May  2 Baku Time
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"BAKT"));
+      return tz1 || (tz1=Ruleset.Timezone(-11964,"LMT"));
+   }
+}
+
+class Asia_Bahrain
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=76190400) // from 1972 Jun 
+         return tz3 || (tz3=Ruleset.Timezone(-10800,"AST"));
+      if (ux>=-1577935340) // from 1920 
+         return tz2 || (tz2=Ruleset.Timezone(-14400,"GST"));
+      // Al-Manamah
+      return tz1 || (tz1=Ruleset.Timezone(-12140,"LMT"));
+   }
+}
+
+class Asia_Dacca
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=38772000) // from 1971 Mar 26 Bangladesh Time
+         return tz6 || (tz6=Ruleset.Timezone(-21600,"BDT"));
+      if (ux>=-576138600) // from 1951 Sep 30 Dacca Time
+         return tz5 || (tz5=Ruleset.Timezone(-21600,"DACT"));
+      if (ux>=-862637400) // from 1942 Sep 
+         return tz3 || (tz3=Ruleset.Timezone(-23400,"BURT"));
+      if (ux>=-872058600) // from 1942 May 15 
+         return tz4 || (tz4=Ruleset.Timezone(-19800,"IST"));
+      if (ux>=-891582800) // from 1941 Oct Burma Time
+         return tz3 || (tz3=Ruleset.Timezone(-23400,"BURT"));
+      if (ux>=-2524543300) // from 1890 Howrah Mean Time?
+         return tz2 || (tz2=Ruleset.Timezone(-21200,"HMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-21700,"LMT"));
+   }
+}
+
+class Asia_Thimbu
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=560025000) // from 1987 Oct Bhutan Time
+         return tz3 || (tz3=Ruleset.Timezone(-21600,"BTT"));
+      if (ux>=-706341516) // from 1947 Aug 15 
+         return tz2 || (tz2=Ruleset.Timezone(-19800,"IST"));
+      return tz1 || (tz1=Ruleset.Timezone(-21516,"LMT"));
+   }
+}
+
+class Asia_Brunei
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1167636600) // from 1933 
+         return tz3 || (tz3=Ruleset.Timezone(-28800,"BNT"));
+      if (ux>=-1383464380) // from 1926 Mar 
+         return tz2 || (tz2=Ruleset.Timezone(-27000,"BNT"));
+      // Bandar Seri Begawan
+      return tz1 || (tz1=Ruleset.Timezone(-27580,"LMT"));
+   }
+}
+
+class Asia_Rangoon
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-778410000) // from 1945 May 3 Myanmar Time
+         return tz5 || (tz5=Ruleset.Timezone(-23400,"MMT"));
+      if (ux>=-873268200) // from 1942 May 
+         return tz4 || (tz4=Ruleset.Timezone(-32400,"JST"));
+      if (ux>=-1577946276) // from 1920 Burma Time
+         return tz3 || (tz3=Ruleset.Timezone(-23400,"BURT"));
+      if (ux>=-2840163880) // from 1880 Rangoon Mean Time?
+         return tz2 || (tz2=Ruleset.Timezone(-23076,"RMT"));
+      // or Yangon
+      return tz1 || (tz1=Ruleset.Timezone(-23080,"LMT"));
+   }
+}
+
+class Asia_Phnom_Penh
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1220428800) // from 1931 May 
+         return tz3 || (tz3=Ruleset.Timezone(-25200,"ICT"));
+      if (ux>=-1819954800) // from 1912 May 
+         return tz4 || (tz4=Ruleset.Timezone(-28800,"ICT"));
+      if (ux>=-1855983920) // from 1911 Mar 11 0:01 
+         return tz3 || (tz3=Ruleset.Timezone(-25200,"ICT"));
+      if (ux>=-2005973980) // from 1906 Jun  9 Saigon MT?
+         return tz2 || (tz2=Ruleset.Timezone(-25580,"SMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-25180,"LMT"));
+   }
+}
+
+class Asia_Harbin
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=325956600) // from 1980 May 
+         return tz5 || (tz5=TZrules.PRC(-28800,"C%sT"));
+      if (ux>=-115894800) // from 1966 May 
+         return tz2 || (tz2=Ruleset.Timezone(-30600,"HART"));
+      if (ux>=-946800000) // from 1940 
+         return tz4 || (tz4=Ruleset.Timezone(-32400,"HART"));
+      if (ux>=-1194078600) // from 1932 Mar 
+         return tz3 || (tz3=Ruleset.Timezone(-28800,"CST"));
+      if (ux>=-1325492804) // from 1928 Harbin Time
+         return tz2 || (tz2=Ruleset.Timezone(-30600,"HART"));
+      return tz1 || (tz1=Ruleset.Timezone(-30404,"LMT"));
+   }
+}
+
+class Asia_Shanghai
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-662659200) // from 1949 
+         return tz3 || (tz3=TZrules.PRC(-28800,"C%sT"));
+      if (ux>=-1325491552) // from 1928 
+         return tz2 || (tz2=TZrules.Shang(-28800,"C%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-29152,"LMT"));
+   }
+}
+constant PRC=Asia_Shanghai;
+
+class Asia_Chungking
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=325962000) // from 1980 May 
+         return tz3 || (tz3=TZrules.PRC(-28800,"C%sT"));
+      if (ux>=-1325487980) // from 1928 Chungking Time
+         return tz2 || (tz2=Ruleset.Timezone(-25200,"CHUT"));
+      return tz1 || (tz1=Ruleset.Timezone(-25580,"LMT"));
+   }
+}
+
+class Asia_Urumqi
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=325965600) // from 1980 May 
+         return tz3 || (tz3=TZrules.PRC(-28800,"C%sT"));
+      if (ux>=-1325483420) // from 1928 Urumqi Time
+         return tz2 || (tz2=Ruleset.Timezone(-21600,"URUT"));
+      return tz1 || (tz1=Ruleset.Timezone(-21020,"LMT"));
+   }
+}
+
+class Asia_Kashgar
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=325969200) // from 1980 May 
+         return tz4 || (tz4=TZrules.PRC(-28800,"C%sT"));
+      if (ux>=-946791000) // from 1940 
+         return tz3 || (tz3=Ruleset.Timezone(-18000,"KAST"));
+      if (ux>=-1325480636) // from 1928 Kashgar Time
+         return tz2 || (tz2=Ruleset.Timezone(-19800,"KAST"));
+      return tz1 || (tz1=Ruleset.Timezone(-18236,"LMT"));
+   }
+}
+
+class Asia_Hong_Kong
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2056692996) // from 1904 Oct 30 
+         return tz2 || (tz2=TZrules.HK(-28800,"HK%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-27396,"LMT"));
+   }
+}
+constant Hongkong=Asia_Hong_Kong;
+
+class Asia_Taipei
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2335248360) // from 1896 
+         return tz2 || (tz2=TZrules.Taiwan(-28800,"C%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-29160,"LMT"));
+   }
+}
+constant ROC=Asia_Taipei;
+
+class Asia_Macao
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=945676800) // from 1999 Dec 20 
+         return tz3 || (tz3=TZrules.PRC(-28800,"C%sT"));
+      if (ux>=-1830411260) // from 1912 return to China
+         return tz2 || (tz2=TZrules.Macao(-28800,"MO%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-27260,"LMT"));
+   }
+}
+
+class Asia_Nicosia
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=904618800) // from 1998 Sep 
+         return tz3 || (tz3=TZrules.EUAsia(-7200,"EE%sT"));
+      if (ux>=-1518920008) // from 1921 Nov 14 
+         return tz2 || (tz2=TZrules.Cyprus(-7200,"EE%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-8008,"LMT"));
+   }
+}
+
+class Asia_Tbilisi
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7,tz8,tz9;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=857156400) // from 1997 Mar lastSun 
+         return tz8 || (tz8=TZrules.E_EurAsia(-14400,"GE%sT"));
+      if (ux>=844146000) // from 1996 Oct lastSun 
+         return tz9 || (tz9=Ruleset.Timezone(-18000,"GEST"));
+      if (ux>=778392000) // from 1994 Sep lastSun 
+         return tz8 || (tz8=TZrules.E_EurAsia(-14400,"GE%sT"));
+      if (ux>=694234800) // from 1992 
+         return tz7 || (tz7=TZrules.E_EurAsia(-10800,"GE%sT"));
+      if (ux>=671140800) // from 1991 Apr  9 Georgia Time
+         return tz6 || (tz6=TZrules.RussiaAsia(-10800,"GE%sT"));
+      if (ux>=670370400) // from 1991 Mar 31 2:00s independence
+         return tz5 || (tz5=Ruleset.Timezone(-14400,"TBIST"));
+      if (ux>=-405140400) // from 1957 Mar 
+         return tz4 || (tz4=TZrules.RussiaAsia(-14400,"TBI%sT"));
+      if (ux>=-1441162756) // from 1924 May  2 Tbilisi Time
+         return tz3 || (tz3=Ruleset.Timezone(-10800,"TBIT"));
+      if (ux>=-2840151556) // from 1880 Tbilisi Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-10756,"TBMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-10756,"LMT"));
+   }
+}
+
+class Asia_Dili
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=199897200) // from 1976 May  3 East Timor Time
+         return tz2 || (tz2=Ruleset.Timezone(-28800,"TPT"));
+      if (ux>=-770634000) // from 1945 Aug 
+         return tz4 || (tz4=Ruleset.Timezone(-32400,"TPT"));
+      if (ux>=-879152400) // from 1942 Feb 21 23:00 
+         return tz3 || (tz3=Ruleset.Timezone(-32400,"JST"));
+      if (ux>=-1830414140) // from 1912 
+         return tz2 || (tz2=Ruleset.Timezone(-28800,"TPT"));
+      return tz1 || (tz1=Ruleset.Timezone(-30140,"LMT"));
+   }
+}
+
+class Asia_Calcutta
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-764145000) // from 1945 Oct 15 
+         return tz4 || (tz4=Ruleset.Timezone(-19800,"IST"));
+      if (ux>=-862637400) // from 1942 Sep 
+         return tz5 || (tz5=Ruleset.Timezone(-23400,"IST"));
+      if (ux>=-872058600) // from 1942 May 15 
+         return tz4 || (tz4=Ruleset.Timezone(-19800,"IST"));
+      if (ux>=-891582800) // from 1941 Oct Burma Time
+         return tz3 || (tz3=Ruleset.Timezone(-23400,"BURT"));
+      if (ux>=-2840162008) // from 1880 Howrah Mean Time?
+         return tz2 || (tz2=Ruleset.Timezone(-21200,"HMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-21208,"LMT"));
+   }
+}
+
+class Asia_Jakarta
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-189415800) // from 1964 
+         return tz7 || (tz7=Ruleset.Timezone(-25200,"JAVT"));
+      if (ux>=-620812800) // from 1950 May 
+         return tz4 || (tz4=Ruleset.Timezone(-27000,"JAVT"));
+      if (ux>=-683883000) // from 1948 May 
+         return tz6 || (tz6=Ruleset.Timezone(-28800,"JAVT"));
+      if (ux>=-770634000) // from 1945 Aug 
+         return tz4 || (tz4=Ruleset.Timezone(-27000,"JAVT"));
+      if (ux>=-876641400) // from 1942 Mar 23 
+         return tz5 || (tz5=Ruleset.Timezone(-32400,"JST"));
+      if (ux>=-1172906400) // from 1932 Nov 
+         return tz4 || (tz4=Ruleset.Timezone(-27000,"JAVT"));
+      if (ux>=-1451719200) // from 1923 Dec 31 23:47:12 Java Time
+         return tz3 || (tz3=Ruleset.Timezone(-26400,"JAVT"));
+      if (ux>=-3231299232) // from 1867 Aug 10 Jakarta
+         return tz2 || (tz2=Ruleset.Timezone(-25632,"JMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-25632,"LMT"));
+   }
+}
+
+class Asia_Ujung_Pandang
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-770634000) // from 1945 Aug 
+         return tz3 || (tz3=Ruleset.Timezone(-28800,"BORT"));
+      if (ux>=-880272000) // from 1942 Feb  9 
+         return tz4 || (tz4=Ruleset.Timezone(-32400,"JST"));
+      if (ux>=-1172908656) // from 1932 Nov Borneo Time
+         return tz3 || (tz3=Ruleset.Timezone(-28800,"BORT"));
+      if (ux>=-1577951856) // from 1920 Macassar MT
+         return tz2 || (tz2=Ruleset.Timezone(-28656,"MMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-28656,"LMT"));
+   }
+}
+
+class Asia_Jayapura
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-189423000) // from 1964 
+         return tz2 || (tz2=Ruleset.Timezone(-32400,"JAYT"));
+      if (ux>=-820573200) // from 1944 
+         return tz3 || (tz3=Ruleset.Timezone(-34200,"CST"));
+      if (ux>=-1172913768) // from 1932 Nov Jayapura Time
+         return tz2 || (tz2=Ruleset.Timezone(-32400,"JAYT"));
+      return tz1 || (tz1=Ruleset.Timezone(-33768,"LMT"));
+   }
+}
+
+class Asia_Tehran
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=284011200) // from 1979 
+         return tz5 || (tz5=TZrules.Iran(-12600,"IR%sT"));
+      if (ux>=247177800) // from 1977 Nov 
+         return tz4 || (tz4=TZrules.Iran(-14400,"IR%sT"));
+      if (ux>=-757394744) // from 1946 
+         return tz3 || (tz3=Ruleset.Timezone(-12600,"IRT"));
+      if (ux>=-1704165944) // from 1916 Tehran Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-12344,"TMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-12344,"LMT"));
+   }
+}
+constant Iran=Asia_Tehran;
+
+class Asia_Baghdad
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=389048400) // from 1982 May 
+         return tz4 || (tz4=TZrules.Iraq(-10800,"A%sT"));
+      if (ux>=-1641005856) // from 1918 
+         return tz3 || (tz3=Ruleset.Timezone(-10800,"AST"));
+      if (ux>=-2524532260) // from 1890 Baghdad Mean Time?
+         return tz2 || (tz2=Ruleset.Timezone(-10656,"BMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-10660,"LMT"));
+   }
+}
+
+class Asia_Jerusalem
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1641003640) // from 1918 
+         return tz3 || (tz3=TZrules.Zion(-7200,"I%sT"));
+      if (ux>=-2840149256) // from 1880 Jerusalem Mean Time?
+         return tz2 || (tz2=Ruleset.Timezone(-8440,"JMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-8456,"LMT"));
+   }
+}
+constant Asia_Tel_Aviv=Asia_Jerusalem;
+constant Israel=Asia_Jerusalem;
+
+class Asia_Tokyo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1009875600) // from 1938 
+         return tz2 || (tz2=Ruleset.Timezone(-32400,"JST"));
+      if (ux>=-2335251600) // from 1896 
+         return tz3 || (tz3=Ruleset.Timezone(-32400,"CJT"));
+      if (ux>=-2587712400) // from 1887 Dec 31 15:00u 
+         return tz2 || (tz2=Ruleset.Timezone(-32400,"JST"));
+      return tz1 || (tz1=Ruleset.Timezone(-33539,"LMT"));
+   }
+}
+constant Japan=Asia_Tokyo;
+
+class Asia_Amman
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1230776624) // from 1931 
+         return tz2 || (tz2=TZrules.Jordan(-7200,"EE%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-8624,"LMT"));
+   }
+}
+
+class Asia_Almaty
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=695768400) // from 1992 Jan 19 2:00s 
+         return tz5 || (tz5=TZrules.E_EurAsia(-21600,"ALM%sT"));
+      if (ux>=686091600) // from 1991 Sep 29 2:00s 
+         return tz2 || (tz2=Ruleset.Timezone(-18000,"ALMT"));
+      if (ux>=670363200) // from 1991 Mar 31 2:00s 
+         return tz4 || (tz4=Ruleset.Timezone(-21600,"ALMST"));
+      if (ux>=-405147600) // from 1957 Mar 
+         return tz3 || (tz3=TZrules.RussiaAsia(-21600,"ALM%sT"));
+      if (ux>=-1441170468) // from 1924 May  2 Alma-Ata Time
+         return tz2 || (tz2=Ruleset.Timezone(-18000,"ALMT"));
+      // or Alma-Ata
+      return tz1 || (tz1=Ruleset.Timezone(-18468,"LMT"));
+   }
+}
+
+class Asia_Aqtobe
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=695772000) // from 1992 Jan 19 2:00s 
+         return tz6 || (tz6=TZrules.E_EurAsia(-18000,"AQT%sT"));
+      if (ux>=686095200) // from 1991 Sep 29 2:00s Aqtobe Time
+         return tz5 || (tz5=Ruleset.Timezone(-14400,"AQTT"));
+      if (ux>=670366800) // from 1991 Mar 31 2:00s 
+         return tz4 || (tz4=Ruleset.Timezone(-18000,"AKTST"));
+      if (ux>=-405144000) // from 1957 Mar 
+         return tz3 || (tz3=TZrules.RussiaAsia(-18000,"AK%sT"));
+      if (ux>=-1441165720) // from 1924 May  2 Aktyubinsk Time
+         return tz2 || (tz2=Ruleset.Timezone(-14400,"AKT"));
+      return tz1 || (tz1=Ruleset.Timezone(-13720,"LMT"));
+   }
+}
+
+class Asia_Aqtau
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=809935200) // from 1995 Sep lastSun 
+         return tz7 || (tz7=TZrules.E_EurAsia(-14400,"AQT%sT"));
+      if (ux>=695772000) // from 1992 Jan 19 2:00s 
+         return tz6 || (tz6=TZrules.E_EurAsia(-18000,"AQT%sT"));
+      if (ux>=686095200) // from 1991 Sep 29 2:00s Aqtau Time
+         return tz5 || (tz5=Ruleset.Timezone(-14400,"AQTT"));
+      if (ux>=670366800) // from 1991 Mar 31 2:00s 
+         return tz4 || (tz4=Ruleset.Timezone(-18000,"AQTST"));
+      if (ux>=-405144000) // from 1957 Mar 
+         return tz3 || (tz3=TZrules.RussiaAsia(-18000,"SHE%sT"));
+      if (ux>=-1441164064) // from 1924 May  2 Fort Shevchenko Time
+         return tz2 || (tz2=Ruleset.Timezone(-14400,"SHET"));
+      // or Aktau
+      return tz1 || (tz1=Ruleset.Timezone(-12064,"LMT"));
+   }
+}
+
+class Asia_Bishkek
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=683582400) // from 1991 Aug 31 2:00 Kirgizstan Time
+         return tz5 || (tz5=TZrules.Kirgiz(-18000,"KG%sT"));
+      if (ux>=670363200) // from 1991 Mar 31 2:00s independence
+         return tz4 || (tz4=Ruleset.Timezone(-21600,"FRUST"));
+      if (ux>=-1247547600) // from 1930 Jun 21 
+         return tz3 || (tz3=TZrules.RussiaAsia(-21600,"FRU%sT"));
+      if (ux>=-1441169904) // from 1924 May  2 Frunze Time
+         return tz2 || (tz2=Ruleset.Timezone(-18000,"FRUT"));
+      return tz1 || (tz1=Ruleset.Timezone(-17904,"LMT"));
+   }
+}
+
+class Asia_Seoul
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-39515400) // from 1968 Oct 
+         return tz5 || (tz5=TZrules.ROK(-32400,"K%sT"));
+      if (ux>=-264873600) // from 1961 Aug 10 
+         return tz2 || (tz2=Ruleset.Timezone(-30600,"KST"));
+      if (ux>=-498128400) // from 1954 Mar 21 
+         return tz4 || (tz4=TZrules.ROK(-28800,"K%sT"));
+      if (ux>=-1199262600) // from 1932 
+         return tz3 || (tz3=Ruleset.Timezone(-32400,"KST"));
+      if (ux>=-1325494800) // from 1928 
+         return tz2 || (tz2=Ruleset.Timezone(-30600,"KST"));
+      if (ux>=-2053931400) // from 1904 Dec 
+         return tz3 || (tz3=Ruleset.Timezone(-32400,"KST"));
+      if (ux>=-2524552072) // from 1890 
+         return tz2 || (tz2=Ruleset.Timezone(-30600,"KST"));
+      return tz1 || (tz1=Ruleset.Timezone(-30472,"LMT"));
+   }
+}
+constant ROK=Asia_Seoul;
+
+class Asia_Pyongyang
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-264931200) // from 1961 Aug 10 
+         return tz3 || (tz3=Ruleset.Timezone(-32400,"KST"));
+      if (ux>=-498128400) // from 1954 Mar 21 
+         return tz4 || (tz4=Ruleset.Timezone(-28800,"KST"));
+      if (ux>=-1199262600) // from 1932 
+         return tz3 || (tz3=Ruleset.Timezone(-32400,"KST"));
+      if (ux>=-1325494800) // from 1928 
+         return tz2 || (tz2=Ruleset.Timezone(-30600,"KST"));
+      if (ux>=-2053931400) // from 1904 Dec 
+         return tz3 || (tz3=Ruleset.Timezone(-32400,"KST"));
+      if (ux>=-2524551780) // from 1890 
+         return tz2 || (tz2=Ruleset.Timezone(-30600,"KST"));
+      return tz1 || (tz1=Ruleset.Timezone(-30180,"LMT"));
+   }
+}
+
+class Asia_Kuwait
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-631163516) // from 1950 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"AST"));
+      return tz1 || (tz1=Ruleset.Timezone(-11516,"LMT"));
+   }
+}
+
+class Asia_Vientiane
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1220428800) // from 1931 May 
+         return tz3 || (tz3=Ruleset.Timezone(-25200,"ICT"));
+      if (ux>=-1819954800) // from 1912 May 
+         return tz4 || (tz4=Ruleset.Timezone(-28800,"ICT"));
+      if (ux>=-1855983920) // from 1911 Mar 11 0:01 
+         return tz3 || (tz3=Ruleset.Timezone(-25200,"ICT"));
+      if (ux>=-2005973424) // from 1906 Jun  9 Saigon MT?
+         return tz2 || (tz2=Ruleset.Timezone(-25580,"SMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-24624,"LMT"));
+   }
+}
+
+class Asia_Beirut
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2840149320) // from 1880 
+         return tz2 || (tz2=TZrules.Lebanon(-7200,"EE%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-8520,"LMT"));
+   }
+}
+
+class Asia_Kuala_Lumpur
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=389032200) // from 1982 May Malaysia Time
+         return tz7 || (tz7=Ruleset.Timezone(-28800,"MYT"));
+      if (ux>=-631178400) // from 1950 
+         return tz6 || (tz6=Ruleset.Timezone(-27000,"MALT"));
+      if (ux>=-767869200) // from 1945 Sep 2 
+         return tz4 || (tz4=Ruleset.Timezone(-26400,"MALT"));
+      if (ux>=-879751200) // from 1942 Feb 15 
+         return tz5 || (tz5=Ruleset.Timezone(-32400,"JST"));
+      if (ux>=-1167634800) // from 1933 
+         return tz4 || (tz4=Ruleset.Timezone(-26400,"MALT"));
+      if (ux>=-2038200924) // from 1905 Jun Malaya Time
+         return tz3 || (tz3=Ruleset.Timezone(-25200,"MALT"));
+      if (ux>=-2840165208) // from 1880 Singapore Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-24924,"SMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-24408,"LMT"));
+   }
+}
+
+class Asia_Kuching
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=389030400) // from 1982 May 
+         return tz6 || (tz6=Ruleset.Timezone(-28800,"MYT"));
+      if (ux>=-767869200) // from 1945 Sep 2 
+         return tz5 || (tz5=Ruleset.Timezone(-28800,"BORT"));
+      if (ux>=-883584000) // from 1942 
+         return tz4 || (tz4=Ruleset.Timezone(-32400,"JST"));
+      if (ux>=-1167636600) // from 1933 
+         return tz3 || (tz3=TZrules.NBorneo(-28800,"BOR%sT"));
+      if (ux>=-1383463280) // from 1926 Mar Borneo Time
+         return tz2 || (tz2=Ruleset.Timezone(-27000,"BORT"));
+      return tz1 || (tz1=Ruleset.Timezone(-26480,"LMT"));
+   }
+}
+
+class Indian_Maldives
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-315636840) // from 1960 Maldives Time
+         return tz3 || (tz3=Ruleset.Timezone(-18000,"MVT"));
+      if (ux>=-2840158440) // from 1880 Male Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-17640,"MMT"));
+      // Male
+      return tz1 || (tz1=Ruleset.Timezone(-17640,"LMT"));
+   }
+}
+
+class Asia_Hovd
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=252439200) // from 1978 
+         return tz3 || (tz3=TZrules.Mongol(-25200,"HOV%sT"));
+      if (ux>=-2032927596) // from 1905 Aug Hovd Time
+         return tz2 || (tz2=Ruleset.Timezone(-21600,"HOVT"));
+      return tz1 || (tz1=Ruleset.Timezone(-21996,"LMT"));
+   }
+}
+
+class Asia_Ulaanbaatar
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=252435600) // from 1978 
+         return tz3 || (tz3=TZrules.Mongol(-28800,"ULA%sT"));
+      if (ux>=-2032931252) // from 1905 Aug Ulaanbaatar Time
+         return tz2 || (tz2=Ruleset.Timezone(-25200,"ULAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-25652,"LMT"));
+   }
+}
+constant Asia_Ulan_Bator=Asia_Ulaanbaatar;
+
+class Asia_Katmandu
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=504901800) // from 1986 Nepal Time
+         return tz3 || (tz3=Ruleset.Timezone(-20700,"NPT"));
+      if (ux>=-1577943676) // from 1920 
+         return tz2 || (tz2=Ruleset.Timezone(-19800,"IST"));
+      return tz1 || (tz1=Ruleset.Timezone(-20476,"LMT"));
+   }
+}
+
+class Asia_Muscat
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1577937260) // from 1920 
+         return tz2 || (tz2=Ruleset.Timezone(-14400,"GST"));
+      return tz1 || (tz1=Ruleset.Timezone(-14060,"LMT"));
+   }
+}
+
+class Asia_Karachi
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=38775600) // from 1971 Mar 26 Pakistan Time
+         return tz5 || (tz5=Ruleset.Timezone(-18000,"PKT"));
+      if (ux>=-576135000) // from 1951 Sep 30 Karachi Time
+         return tz4 || (tz4=Ruleset.Timezone(-18000,"KART"));
+      if (ux>=-764145000) // from 1945 Oct 15 
+         return tz2 || (tz2=Ruleset.Timezone(-19800,"IST"));
+      if (ux>=-862637400) // from 1942 Sep 
+         return tz3 || (tz3=Ruleset.Timezone(-23400,"IST"));
+      if (ux>=-1988166492) // from 1907 
+         return tz2 || (tz2=Ruleset.Timezone(-19800,"IST"));
+      return tz1 || (tz1=Ruleset.Timezone(-16092,"LMT"));
+   }
+}
+
+class Asia_Gaza
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=915156000) // from 1999 
+         return tz6 || (tz6=TZrules.Palestine(-7200,"EE%sT"));
+      if (ux>=820461600) // from 1996 
+         return tz5 || (tz5=TZrules.Jordan(-7200,"EE%sT"));
+      if (ux>=-81291600) // from 1967 Jun  5 
+         return tz4 || (tz4=TZrules.Zion(-7200,"I%sT"));
+      if (ux>=-682639200) // from 1948 May 15 
+         return tz3 || (tz3=TZrules.EgyptAsia(-7200,"EE%sT"));
+      if (ux>=-2185409872) // from 1900 Oct 
+         return tz2 || (tz2=TZrules.Zion(-7200,"EET"));
+      return tz1 || (tz1=Ruleset.Timezone(-8272,"LMT"));
+   }
+}
+
+class Asia_Manila
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-794221200) // from 1944 Nov 
+         return tz3 || (tz3=TZrules.Phil(-28800,"PH%sT"));
+      if (ux>=-873216000) // from 1942 May 
+         return tz4 || (tz4=Ruleset.Timezone(-32400,"JST"));
+      if (ux>=-2229321840) // from 1899 May 11 
+         return tz3 || (tz3=TZrules.Phil(-28800,"PH%sT"));
+      if (ux>=-3976157040) // from 1844 
+         return tz2 || (tz2=Ruleset.Timezone(-29040,"LMT"));
+      return tz1 || (tz1=Ruleset.Timezone(57360,"LMT"));
+   }
+}
+
+class Asia_Qatar
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=76190400) // from 1972 Jun 
+         return tz3 || (tz3=Ruleset.Timezone(-10800,"AST"));
+      if (ux>=-1577935568) // from 1920 
+         return tz2 || (tz2=Ruleset.Timezone(-14400,"GST"));
+      // Al Dawhah
+      return tz1 || (tz1=Ruleset.Timezone(-12368,"LMT"));
+   }
+}
+
+class Asia_Riyadh
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-631163212) // from 1950 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"AST"));
+      return tz1 || (tz1=Ruleset.Timezone(-11212,"LMT"));
+   }
+}
+
+class Asia_Singapore
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7,tz8;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=389032200) // from 1982 May 
+         return tz8 || (tz8=Ruleset.Timezone(-28800,"SGT"));
+      if (ux>=-138785400) // from 1965 Aug  9 Singapore Time
+         return tz7 || (tz7=Ruleset.Timezone(-27000,"SGT"));
+      if (ux>=-631178400) // from 1950 independence
+         return tz6 || (tz6=Ruleset.Timezone(-27000,"MALT"));
+      if (ux>=-767869200) // from 1945 Sep  2 
+         return tz4 || (tz4=Ruleset.Timezone(-26400,"MALT"));
+      if (ux>=-879751200) // from 1942 Feb 15 
+         return tz5 || (tz5=Ruleset.Timezone(-32400,"JST"));
+      if (ux>=-1167634800) // from 1933 
+         return tz4 || (tz4=Ruleset.Timezone(-26400,"MALT"));
+      if (ux>=-2038200924) // from 1905 Jun Malaya Time
+         return tz3 || (tz3=Ruleset.Timezone(-25200,"MALT"));
+      if (ux>=-2840165724) // from 1880 Singapore Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-24924,"SMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-24924,"LMT"));
+   }
+}
+constant Singapore=Asia_Singapore;
+
+class Asia_Colombo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=846266400) // from 1996 Oct 26 0:30 
+         return tz7 || (tz7=Ruleset.Timezone(-21600,"LKT"));
+      if (ux>=832962600) // from 1996 May 25 0:00 
+         return tz6 || (tz6=Ruleset.Timezone(-23400,"LKT"));
+      if (ux>=-764051400) // from 1945 Oct 16 2:00 
+         return tz3 || (tz3=Ruleset.Timezone(-19800,"IST"));
+      if (ux>=-862639200) // from 1942 Sep 
+         return tz5 || (tz5=Ruleset.Timezone(-23400,"IST"));
+      if (ux>=-883287000) // from 1942 Jan  5 
+         return tz4 || (tz4=Ruleset.Timezone(-21600,"IHST"));
+      if (ux>=-2019705572) // from 1906 
+         return tz3 || (tz3=Ruleset.Timezone(-19800,"IST"));
+      if (ux>=-2840159964) // from 1880 Moratuwa Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-19172,"MMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-19164,"LMT"));
+   }
+}
+
+class Asia_Damascus
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1577931912) // from 1920 
+         return tz2 || (tz2=TZrules.Syria(-7200,"EE%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-8712,"LMT"));
+   }
+}
+
+class Asia_Dushanbe
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=684363600) // from 1991 Sep  9 2:00s Tajikistan Time
+         return tz5 || (tz5=Ruleset.Timezone(-18000,"TJT"));
+      if (ux>=670363200) // from 1991 Mar 31 2:00s 
+         return tz4 || (tz4=Ruleset.Timezone(-21600,"DUSST"));
+      if (ux>=-1247547600) // from 1930 Jun 21 
+         return tz3 || (tz3=TZrules.RussiaAsia(-21600,"DUS%sT"));
+      if (ux>=-1441168512) // from 1924 May  2 Dushanbe Time
+         return tz2 || (tz2=Ruleset.Timezone(-18000,"DUST"));
+      return tz1 || (tz1=Ruleset.Timezone(-16512,"LMT"));
+   }
+}
+
+class Asia_Bangkok
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1570084924) // from 1920 Apr 
+         return tz3 || (tz3=Ruleset.Timezone(-25200,"ICT"));
+      if (ux>=-2840164924) // from 1880 Bangkok Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-24124,"BMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-24124,"LMT"));
+   }
+}
+
+class Asia_Ashkhabad
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=695800800) // from 1992 Jan 19 2:00 
+         return tz6 || (tz6=Ruleset.Timezone(-18000,"TMT"));
+      if (ux>=688536000) // from 1991 Oct 27 
+         return tz5 || (tz5=TZrules.RussiaAsia(-14400,"TM%sT"));
+      if (ux>=670402800) // from 1991 Mar 31 2:00 independence
+         return tz4 || (tz4=TZrules.RussiaAsia(-14400,"ASH%sT"));
+      if (ux>=-1247544000) // from 1930 Jun 21 
+         return tz3 || (tz3=TZrules.RussiaAsia(-18000,"ASH%sT"));
+      if (ux>=-1441166012) // from 1924 May  2 Ashkhabad Time
+         return tz2 || (tz2=Ruleset.Timezone(-14400,"ASHT"));
+      // or Ashgabat
+      return tz1 || (tz1=Ruleset.Timezone(-14012,"LMT"));
+   }
+}
+
+class Asia_Dubai
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1577936472) // from 1920 
+         return tz2 || (tz2=Ruleset.Timezone(-14400,"GST"));
+      return tz1 || (tz1=Ruleset.Timezone(-13272,"LMT"));
+   }
+}
+
+class Asia_Samarkand
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7,tz8;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=725864400) // from 1993 
+         return tz8 || (tz8=Ruleset.Timezone(-18000,"UZT"));
+      if (ux>=694242000) // from 1992 
+         return tz7 || (tz7=TZrules.RussiaAsia(-18000,"UZ%sT"));
+      if (ux>=683704800) // from 1991 Sep  1 
+         return tz7 || (tz7=TZrules.RussiaAsia(-18000,"UZ%sT"));
+      if (ux>=670406400) // from 1991 Mar 31 2:00 independence
+         return tz6 || (tz6=TZrules.RussiaAsia(-18000,"TAS%sT"));
+      if (ux>=370720800) // from 1981 Oct  1 Tashkent Time
+         return tz5 || (tz5=TZrules.RussiaAsia(-21600,"TAS%sT"));
+      if (ux>=354913200) // from 1981 Apr  1 
+         return tz4 || (tz4=Ruleset.Timezone(-21600,"SAMST"));
+      if (ux>=-1247544000) // from 1930 Jun 21 
+         return tz3 || (tz3=Ruleset.Timezone(-18000,"SAMT"));
+      if (ux>=-1441168032) // from 1924 May  2 Samarkand Time
+         return tz2 || (tz2=Ruleset.Timezone(-14400,"SAMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-16032,"LMT"));
+   }
+}
+
+class Asia_Tashkent
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=725864400) // from 1993 
+         return tz6 || (tz6=Ruleset.Timezone(-18000,"UZT"));
+      if (ux>=694242000) // from 1992 
+         return tz5 || (tz5=TZrules.RussiaAsia(-18000,"UZ%sT"));
+      if (ux>=683704800) // from 1991 Sep  1 
+         return tz5 || (tz5=TZrules.RussiaAsia(-18000,"UZ%sT"));
+      if (ux>=670363200) // from 1991 Mar 31 2:00s independence
+         return tz4 || (tz4=TZrules.RussiaAsia(-18000,"TAS%sT"));
+      if (ux>=-1247547600) // from 1930 Jun 21 
+         return tz3 || (tz3=TZrules.RussiaAsia(-21600,"TAS%sT"));
+      if (ux>=-1441168632) // from 1924 May  2 Tashkent Time
+         return tz2 || (tz2=Ruleset.Timezone(-18000,"TAST"));
+      return tz1 || (tz1=Ruleset.Timezone(-16632,"LMT"));
+   }
+}
+
+class Asia_Saigon
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1220428800) // from 1931 May 
+         return tz3 || (tz3=Ruleset.Timezone(-25200,"ICT"));
+      if (ux>=-1819954800) // from 1912 May 
+         return tz4 || (tz4=Ruleset.Timezone(-28800,"ICT"));
+      if (ux>=-1855983920) // from 1911 Mar 11 0:01 
+         return tz3 || (tz3=Ruleset.Timezone(-25200,"ICT"));
+      if (ux>=-2005974400) // from 1906 Jun  9 Saigon MT?
+         return tz2 || (tz2=Ruleset.Timezone(-25580,"SMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-25600,"LMT"));
+   }
+}
+
+class Asia_Aden
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-631162848) // from 1950 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"AST"));
+      return tz1 || (tz1=Ruleset.Timezone(-10848,"LMT"));
+   }
+}
+
+class Australia_Darwin
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2230189200) // from 1899 May 
+         return tz3 || (tz3=TZrules.Aus(-34200,"CST"));
+      if (ux>=-2364108200) // from 1895 Feb 
+         return tz2 || (tz2=Ruleset.Timezone(-32400,"CST"));
+      return tz1 || (tz1=Ruleset.Timezone(-31400,"LMT"));
+   }
+}
+constant Australia_North=Australia_Darwin;
+
+class Australia_Perth
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=699375600) // from 1992 Mar Sun>=1 2:00s 
+         return tz3 || (tz3=Ruleset.Timezone(-28800,"WST"));
+      if (ux>=690314400) // from 1991 Nov 17 2:00s 
+         return tz4 || (tz4=Ruleset.Timezone(-32400,"WST"));
+      if (ux>=446914800) // from 1984 Mar Sun>=1 2:00s 
+         return tz3 || (tz3=Ruleset.Timezone(-28800,"WST"));
+      if (ux>=433785600) // from 1983 Oct lastSun 2:00s 
+         return tz4 || (tz4=Ruleset.Timezone(-32400,"WST"));
+      if (ux>=162831600) // from 1975 Mar Sun>=1 2:00s 
+         return tz3 || (tz3=Ruleset.Timezone(-28800,"WST"));
+      if (ux>=149788800) // from 1974 Oct lastSun 2:00s 
+         return tz4 || (tz4=Ruleset.Timezone(-32400,"WST"));
+      if (ux>=-836409600) // from 1943 Jul 
+         return tz3 || (tz3=Ruleset.Timezone(-28800,"WST"));
+      if (ux>=-2337925404) // from 1895 Dec 
+         return tz2 || (tz2=TZrules.Aus(-28800,"WST"));
+      return tz1 || (tz1=Ruleset.Timezone(-27804,"LMT"));
+   }
+}
+constant Australia_West=Australia_Perth;
+
+class Australia_Brisbane
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=31572000) // from 1971 
+         return tz3 || (tz3=TZrules.AQ(-36000,"EST"));
+      if (ux>=-2366791928) // from 1895 
+         return tz2 || (tz2=TZrules.Aus(-36000,"EST"));
+      return tz1 || (tz1=Ruleset.Timezone(-36728,"LMT"));
+   }
+}
+constant Australia_Queensland=Australia_Brisbane;
+
+class Australia_Lindeman
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=709984800) // from 1992 Jul 
+         return tz4 || (tz4=TZrules.Holiday(-36000,"EST"));
+      if (ux>=31572000) // from 1971 
+         return tz3 || (tz3=TZrules.AQ(-36000,"EST"));
+      if (ux>=-2366790956) // from 1895 
+         return tz2 || (tz2=TZrules.Aus(-36000,"EST"));
+      return tz1 || (tz1=Ruleset.Timezone(-35756,"LMT"));
+   }
+}
+
+class Australia_Adelaide
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=31570200) // from 1971 
+         return tz4 || (tz4=TZrules.AS(-34200,"CST"));
+      if (ux>=-2230189200) // from 1899 May 
+         return tz3 || (tz3=TZrules.Aus(-34200,"CST"));
+      if (ux>=-2364110060) // from 1895 Feb 
+         return tz2 || (tz2=Ruleset.Timezone(-32400,"CST"));
+      return tz1 || (tz1=Ruleset.Timezone(-33260,"LMT"));
+   }
+}
+constant Australia_South=Australia_Adelaide;
+
+class Australia_Hobart
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-94658400) // from 1967 
+         return tz5 || (tz5=TZrules.AT(-36000,"EST"));
+      if (ux>=-1669892400) // from 1917 Feb 
+         return tz4 || (tz4=TZrules.Aus(-36000,"EST"));
+      if (ux>=-1680508800) // from 1916 Oct 1 2:00 
+         return tz3 || (tz3=Ruleset.Timezone(-39600,"EST"));
+      if (ux>=-2345795356) // from 1895 Sep 
+         return tz2 || (tz2=Ruleset.Timezone(-36000,"EST"));
+      return tz1 || (tz1=Ruleset.Timezone(-35356,"LMT"));
+   }
+}
+constant Australia_Tasmania=Australia_Hobart;
+
+class Australia_Melbourne
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=31572000) // from 1971 
+         return tz3 || (tz3=TZrules.AV(-36000,"EST"));
+      if (ux>=-2364111592) // from 1895 Feb 
+         return tz2 || (tz2=TZrules.Aus(-36000,"EST"));
+      return tz1 || (tz1=Ruleset.Timezone(-34792,"LMT"));
+   }
+}
+constant Australia_Victoria=Australia_Melbourne;
+
+class Australia_Sydney
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=31572000) // from 1971 
+         return tz3 || (tz3=TZrules.AN(-36000,"EST"));
+      if (ux>=-2364113092) // from 1895 Feb 
+         return tz2 || (tz2=TZrules.Aus(-36000,"EST"));
+      return tz1 || (tz1=Ruleset.Timezone(-36292,"LMT"));
+   }
+}
+constant Australia_ACT=Australia_Sydney;
+constant Australia_Canberra=Australia_Sydney;
+constant Australia_NSW=Australia_Sydney;
+
+class Australia_Broken_Hill
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=946722600) // from 2000 
+         return tz6 || (tz6=TZrules.AS(-34200,"CST"));
+      if (ux>=31570200) // from 1971 
+         return tz5 || (tz5=TZrules.AN(-34200,"CST"));
+      if (ux>=-2230189200) // from 1899 May 
+         return tz4 || (tz4=TZrules.Aus(-34200,"CST"));
+      if (ux>=-2314951200) // from 1896 Aug 23 
+         return tz3 || (tz3=Ruleset.Timezone(-32400,"CST"));
+      if (ux>=-2364110748) // from 1895 Feb 
+         return tz2 || (tz2=Ruleset.Timezone(-36000,"EST"));
+      return tz1 || (tz1=Ruleset.Timezone(-33948,"LMT"));
+   }
+}
+constant Australia_Yancowinna=Australia_Broken_Hill;
+
+class Australia_Lord_Howe
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=352216800) // from 1981 Mar 
+         return tz3 || (tz3=TZrules.LH(-37800,"LHST"));
+      if (ux>=-2364114980) // from 1895 Feb 
+         return tz2 || (tz2=Ruleset.Timezone(-36000,"EST"));
+      return tz1 || (tz1=Ruleset.Timezone(-38180,"LMT"));
+   }
+}
+constant Australia_LHI=Australia_Lord_Howe;
+
+class Indian_Christmas
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2364102172) // from 1895 Feb Christmas Island Time
+         return tz2 || (tz2=Ruleset.Timezone(-25200,"CXT"));
+      return tz1 || (tz1=Ruleset.Timezone(-25372,"LMT"));
+   }
+}
+
+class Pacific_Rarotonga
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=279714600) // from 1978 Nov 12 
+         return tz3 || (tz3=TZrules.Cook(36000,"CK%sT"));
+      if (ux>=-2177414456) // from 1901 Cook Is Time
+         return tz2 || (tz2=Ruleset.Timezone(37800,"CKT"));
+      // Avarua
+      return tz1 || (tz1=Ruleset.Timezone(38344,"LMT"));
+   }
+}
+
+class Pacific_Fiji
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1709985220) // from 1915 Oct 26 Fiji Time
+         return tz2 || (tz2=TZrules.Fiji(-43200,"FJ%sT"));
+      // Suva
+      return tz1 || (tz1=Ruleset.Timezone(-42820,"LMT"));
+   }
+}
+
+class Pacific_Gambier
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1806678012) // from 1912 Oct Gambier Time
+         return tz2 || (tz2=Ruleset.Timezone(32400,"GAMT"));
+      // Rikitea
+      return tz1 || (tz1=Ruleset.Timezone(32388,"LMT"));
+   }
+}
+
+class Pacific_Marquesas
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1806676920) // from 1912 Oct Marquesas Time
+         return tz2 || (tz2=Ruleset.Timezone(34200,"MART"));
+      return tz1 || (tz1=Ruleset.Timezone(33480,"LMT"));
+   }
+}
+
+class Pacific_Tahiti
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1806674504) // from 1912 Oct Tahiti Time
+         return tz2 || (tz2=Ruleset.Timezone(36000,"TAHT"));
+      // Papeete
+      return tz1 || (tz1=Ruleset.Timezone(35896,"LMT"));
+   }
+}
+
+class Pacific_Guam
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2177487540) // from 1901 
+         return tz2 || (tz2=Ruleset.Timezone(-36000,"GST"));
+      // Agana
+      return tz1 || (tz1=Ruleset.Timezone(-34740,"LMT"));
+   }
+}
+
+class Pacific_Tarawa
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2177494324) // from 1901 Gilbert Is Time
+         return tz2 || (tz2=Ruleset.Timezone(-43200,"GILT"));
+      // Bairiki
+      return tz1 || (tz1=Ruleset.Timezone(-41524,"LMT"));
+   }
+}
+
+class Pacific_Enderbury
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=788958000) // from 1995 
+         return tz4 || (tz4=Ruleset.Timezone(-46800,"PHOT"));
+      if (ux>=307627200) // from 1979 Oct 
+         return tz3 || (tz3=Ruleset.Timezone(39600,"PHOT"));
+      if (ux>=-2177411740) // from 1901 Phoenix Is Time
+         return tz2 || (tz2=Ruleset.Timezone(43200,"PHOT"));
+      return tz1 || (tz1=Ruleset.Timezone(41060,"LMT"));
+   }
+}
+
+class Pacific_Kiritimati
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=788954400) // from 1995 
+         return tz4 || (tz4=Ruleset.Timezone(-50400,"LINT"));
+      if (ux>=307622400) // from 1979 Oct 
+         return tz3 || (tz3=Ruleset.Timezone(36000,"LINT"));
+      if (ux>=-2177415040) // from 1901 Line Is Time
+         return tz2 || (tz2=Ruleset.Timezone(38400,"LINT"));
+      return tz1 || (tz1=Ruleset.Timezone(37760,"LMT"));
+   }
+}
+
+class Pacific_Saipan
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-7981200) // from 1969 Oct 
+         return tz3 || (tz3=Ruleset.Timezone(-36000,"MPT"));
+      if (ux>=-2177487780) // from 1901 N Mariana Is Time
+         return tz2 || (tz2=Ruleset.Timezone(-32400,"MPT"));
+      return tz1 || (tz1=Ruleset.Timezone(-34980,"LMT"));
+   }
+}
+
+class Pacific_Majuro
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-7988400) // from 1969 Oct 
+         return tz3 || (tz3=Ruleset.Timezone(-43200,"MHT"));
+      if (ux>=-2177493888) // from 1901 Marshall Islands Time
+         return tz2 || (tz2=Ruleset.Timezone(-39600,"MHT"));
+      return tz1 || (tz1=Ruleset.Timezone(-41088,"LMT"));
+   }
+}
+
+class Pacific_Kwajalein
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=745848000) // from 1993 Aug 20 
+         return tz4 || (tz4=Ruleset.Timezone(-43200,"MHT"));
+      if (ux>=-7988400) // from 1969 Oct Kwajalein Time
+         return tz3 || (tz3=Ruleset.Timezone(43200,"KWAT"));
+      if (ux>=-2177492960) // from 1901 
+         return tz2 || (tz2=Ruleset.Timezone(-39600,"MHT"));
+      return tz1 || (tz1=Ruleset.Timezone(-40160,"LMT"));
+   }
+}
+constant Kwajalein=Pacific_Kwajalein;
+
+class Pacific_Yap
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-7981200) // from 1969 Oct 
+         return tz3 || (tz3=Ruleset.Timezone(-36000,"YAPT"));
+      if (ux>=-2177485952) // from 1901 Yap Time
+         return tz2 || (tz2=Ruleset.Timezone(-32400,"YAPT"));
+      // Colonia
+      return tz1 || (tz1=Ruleset.Timezone(-33152,"LMT"));
+   }
+}
+
+class Pacific_Truk
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2177489228) // from 1901 Truk Time
+         return tz2 || (tz2=Ruleset.Timezone(-36000,"TRUT"));
+      return tz1 || (tz1=Ruleset.Timezone(-36428,"LMT"));
+   }
+}
+
+class Pacific_Ponape
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2177490772) // from 1901 Ponape Time
+         return tz2 || (tz2=Ruleset.Timezone(-39600,"PONT"));
+      // Kolonia
+      return tz1 || (tz1=Ruleset.Timezone(-37972,"LMT"));
+   }
+}
+
+class Pacific_Kosrae
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=915105600) // from 1999 
+         return tz2 || (tz2=Ruleset.Timezone(-39600,"KOST"));
+      if (ux>=-7988400) // from 1969 Oct 
+         return tz3 || (tz3=Ruleset.Timezone(-43200,"KOST"));
+      if (ux>=-2177491916) // from 1901 Kosrae Time
+         return tz2 || (tz2=Ruleset.Timezone(-39600,"KOST"));
+      return tz1 || (tz1=Ruleset.Timezone(-39116,"LMT"));
+   }
+}
+
+class Pacific_Nauru
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=294323400) // from 1979 May 
+         return tz4 || (tz4=Ruleset.Timezone(-43200,"NRT"));
+      if (ux>=-800960400) // from 1944 Aug 15 
+         return tz2 || (tz2=Ruleset.Timezone(-41400,"NRT"));
+      if (ux>=-877347000) // from 1942 Mar 15 
+         return tz3 || (tz3=Ruleset.Timezone(-32400,"JST"));
+      if (ux>=-1545131260) // from 1921 Jan 15 Nauru Time
+         return tz2 || (tz2=Ruleset.Timezone(-41400,"NRT"));
+      // Uaobe
+      return tz1 || (tz1=Ruleset.Timezone(-40060,"LMT"));
+   }
+}
+
+class Pacific_Noumea
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1829387148) // from 1912 Jan 13 
+         return tz2 || (tz2=TZrules.NC(-39600,"NC%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-39948,"LMT"));
+   }
+}
+
+class Pacific_Auckland
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-923221800) // from 1940 Sep 29 2:00 
+         return tz3 || (tz3=TZrules.NZ(-43200,"NZ%sT"));
+      if (ux>=-3218873944) // from 1868 
+         return tz2 || (tz2=TZrules.NZ(-41400,"NZ%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-41944,"LMT"));
+   }
+}
+constant NZ=Pacific_Auckland;
+
+class Pacific_Niue
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=276089400) // from 1978 Oct 1 
+         return tz4 || (tz4=Ruleset.Timezone(39600,"NUT"));
+      if (ux>=-599575200) // from 1951 
+         return tz3 || (tz3=Ruleset.Timezone(41400,"NUT"));
+      if (ux>=-2177412020) // from 1901 Niue Time
+         return tz2 || (tz2=Ruleset.Timezone(40800,"NUT"));
+      // Alofi
+      return tz1 || (tz1=Ruleset.Timezone(40780,"LMT"));
+   }
+}
+
+class Pacific_Norfolk
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-599656320) // from 1951 Norfolk Time
+         return tz3 || (tz3=Ruleset.Timezone(-41400,"NFT"));
+      if (ux>=-2177493112) // from 1901 Norfolk Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-40320,"NMT"));
+      // Kingston
+      return tz1 || (tz1=Ruleset.Timezone(-40312,"LMT"));
+   }
+}
+
+class Pacific_Palau
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2177485076) // from 1901 Palau Time
+         return tz2 || (tz2=Ruleset.Timezone(-32400,"PWT"));
+      // Koror
+      return tz1 || (tz1=Ruleset.Timezone(-32276,"LMT"));
+   }
+}
+
+class Pacific_Port_Moresby
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2366790520) // from 1895 Papua New Guinea Time
+         return tz3 || (tz3=Ruleset.Timezone(-36000,"PGT"));
+      if (ux>=-2840176120) // from 1880 Port Moresby Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-35320,"PMMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-35320,"LMT"));
+   }
+}
+
+class Pacific_Pitcairn
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=893665800) // from 1998 Apr 27 00:00 Pitcairn Standard Time
+         return tz3 || (tz3=Ruleset.Timezone(28800,"PST"));
+      if (ux>=-2177421580) // from 1901 
+         return tz2 || (tz2=Ruleset.Timezone(30600,"PNT"));
+      // Adamstown
+      return tz1 || (tz1=Ruleset.Timezone(31220,"LMT"));
+   }
+}
+
+class Pacific_Pago_Pago
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=439038000) // from 1983 Nov 30 S=Samoa
+         return tz6 || (tz6=Ruleset.Timezone(39600,"SST"));
+      if (ux>=-86878800) // from 1967 Apr B=Bering
+         return tz5 || (tz5=Ruleset.Timezone(39600,"BST"));
+      if (ux>=-631110600) // from 1950 N=Nome
+         return tz4 || (tz4=Ruleset.Timezone(39600,"NST"));
+      if (ux>=-1861879032) // from 1911 Samoa Time
+         return tz3 || (tz3=Ruleset.Timezone(41400,"SAMT"));
+      if (ux>=-2855738232) // from 1879 Jul  5 
+         return tz2 || (tz2=Ruleset.Timezone(40968,"LMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-45432,"LMT"));
+   }
+}
+constant Pacific_Samoa=Pacific_Pago_Pago;
+constant US_Samoa=Pacific_Pago_Pago;
+
+class Pacific_Apia
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-631110600) // from 1950 W Samoa Time
+         return tz4 || (tz4=Ruleset.Timezone(39600,"WST"));
+      if (ux>=-1861878784) // from 1911 Samoa Time
+         return tz3 || (tz3=Ruleset.Timezone(41400,"SAMT"));
+      if (ux>=-2855737984) // from 1879 Jul  5 
+         return tz2 || (tz2=Ruleset.Timezone(41216,"LMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-45184,"LMT"));
+   }
+}
+
+class Pacific_Guadalcanal
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1806748788) // from 1912 Oct Solomon Is Time
+         return tz2 || (tz2=Ruleset.Timezone(-39600,"SBT"));
+      // Honiara
+      return tz1 || (tz1=Ruleset.Timezone(-38388,"LMT"));
+   }
+}
+
+class Pacific_Fakaofo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2177411704) // from 1901 Tokelau Time
+         return tz2 || (tz2=Ruleset.Timezone(36000,"TKT"));
+      return tz1 || (tz1=Ruleset.Timezone(41096,"LMT"));
+   }
+}
+
+class Pacific_Tongatapu
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=915102000) // from 1999 
+         return tz4 || (tz4=TZrules.Tonga(-46800,"TO%sT"));
+      if (ux>=-915193200) // from 1941 
+         return tz3 || (tz3=Ruleset.Timezone(-46800,"TOT"));
+      if (ux>=-2177497160) // from 1901 Tonga Time
+         return tz2 || (tz2=Ruleset.Timezone(-44400,"TOT"));
+      return tz1 || (tz1=Ruleset.Timezone(-44360,"LMT"));
+   }
+}
+
+class Pacific_Funafuti
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2177495812) // from 1901 Tuvalu Time
+         return tz2 || (tz2=Ruleset.Timezone(-43200,"TVT"));
+      return tz1 || (tz1=Ruleset.Timezone(-43012,"LMT"));
+   }
+}
+
+class Pacific_Midway
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=439038000) // from 1983 Nov 30 S=Samoa
+         return tz4 || (tz4=Ruleset.Timezone(39600,"SST"));
+      if (ux>=-86878800) // from 1967 Apr B=Bering
+         return tz3 || (tz3=Ruleset.Timezone(39600,"BST"));
+      if (ux>=-2177410232) // from 1901 N=Nome
+         return tz2 || (tz2=Ruleset.Timezone(39600,"NST"));
+      return tz1 || (tz1=Ruleset.Timezone(42568,"LMT"));
+   }
+}
+
+class Pacific_Wake
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2177492788) // from 1901 Wake Time
+         return tz2 || (tz2=Ruleset.Timezone(-43200,"WAKT"));
+      return tz1 || (tz1=Ruleset.Timezone(-39988,"LMT"));
+   }
+}
+
+class Pacific_Efate
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1829387596) // from 1912 Jan 13 Vanuatu Time
+         return tz2 || (tz2=TZrules.Vanuatu(-39600,"VU%sT"));
+      // Vila
+      return tz1 || (tz1=Ruleset.Timezone(-40396,"LMT"));
+   }
+}
+
+class Pacific_Wallis
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2177496920) // from 1901 Wallis & Futuna Time
+         return tz2 || (tz2=Ruleset.Timezone(-43200,"WFT"));
+      return tz1 || (tz1=Ruleset.Timezone(-44120,"LMT"));
+   }
+}
+
+class Europe_London
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=820454400) // from 1996 
+         return tz4 || (tz4=TZrules.EU(0,"GMT/BST"));
+      if (ux>=57722400) // from 1971 Oct 31 2:00u 
+         return tz2 || (tz2=TZrules.GB_Eire(0,"%s"));
+      if (ux>=-37234800) // from 1968 Oct 27 
+         return tz3 || (tz3=Ruleset.Timezone(-3600,"BST"));
+      if (ux>=-3852662325) // from 1847 Dec  1 
+         return tz2 || (tz2=TZrules.GB_Eire(0,"%s"));
+      return tz1 || (tz1=Ruleset.Timezone(75,"LMT"));
+   }
+}
+constant GB=Europe_London;
+constant GB_Eire=Europe_London;
+
+class Europe_Belfast
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=820454400) // from 1996 
+         return tz6 || (tz6=TZrules.EU(0,"GMT/BST"));
+      if (ux>=57722400) // from 1971 Oct 31 2:00u 
+         return tz4 || (tz4=TZrules.GB_Eire(0,"%s"));
+      if (ux>=-37234800) // from 1968 Oct 27 
+         return tz5 || (tz5=Ruleset.Timezone(-3600,"BST"));
+      if (ux>=-1680471279) // from 1916 Oct  1 2:00s 
+         return tz4 || (tz4=TZrules.GB_Eire(0,"%s"));
+      if (ux>=-1691962479) // from 1916 May 21 2:00 Irish Summer Time
+         return tz3 || (tz3=Ruleset.Timezone(-2079,"IST"));
+      if (ux>=-2821649780) // from 1880 Aug  2 Dublin MT
+         return tz2 || (tz2=Ruleset.Timezone(1521,"DMT"));
+      return tz1 || (tz1=Ruleset.Timezone(1420,"LMT"));
+   }
+}
+
+class Europe_Dublin
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7,tz8;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=820454400) // from 1996 
+         return tz8 || (tz8=TZrules.EU(0,"GMT/IST"));
+      if (ux>=57722400) // from 1971 Oct 31 2:00u 
+         return tz5 || (tz5=TZrules.GB_Eire(0,"GMT/IST"));
+      if (ux>=-37234800) // from 1968 Oct 27 
+         return tz6 || (tz6=Ruleset.Timezone(-3600,"IST"));
+      if (ux>=-684972000) // from 1948 Apr 18 2:00 
+         return tz5 || (tz5=TZrules.GB_Eire(0,"GMT/IST"));
+      if (ux>=-699490800) // from 1947 Nov  2 2:00 
+         return tz7 || (tz7=Ruleset.Timezone(0,"GMT"));
+      if (ux>=-719445600) // from 1947 Mar 16 2:00 
+         return tz6 || (tz6=Ruleset.Timezone(-3600,"IST"));
+      if (ux>=-733359600) // from 1946 Oct  6 2:00 
+         return tz7 || (tz7=Ruleset.Timezone(0,"GMT"));
+      if (ux>=-942012000) // from 1940 Feb 25 2:00 
+         return tz6 || (tz6=Ruleset.Timezone(-3600,"IST"));
+      if (ux>=-1517011200) // from 1921 Dec  6 
+         return tz5 || (tz5=TZrules.GB_Eire(0,"GMT/IST"));
+      if (ux>=-1680471279) // from 1916 Oct  1 2:00s independence
+         return tz4 || (tz4=TZrules.GB_Eire(0,"%s"));
+      if (ux>=-1691962479) // from 1916 May 21 2:00 
+         return tz3 || (tz3=Ruleset.Timezone(-2079,"IST"));
+      if (ux>=-2821649679) // from 1880 Aug  2 Dublin MT
+         return tz2 || (tz2=Ruleset.Timezone(1521,"DMT"));
+      return tz1 || (tz1=Ruleset.Timezone(1521,"LMT"));
+   }
+}
+constant Eire=Europe_Dublin;
+
+class Europe_Tirane
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=457495200) // from 1984 Jul 
+         return tz4 || (tz4=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-932346000) // from 1940 Jun 16 
+         return tz3 || (tz3=TZrules.Albania(-3600,"CE%sT"));
+      if (ux>=-1767230360) // from 1914 
+         return tz2 || (tz2=Ruleset.Timezone(-3600,"CET"));
+      return tz1 || (tz1=Ruleset.Timezone(-4760,"LMT"));
+   }
+}
+
+class Europe_Andorra
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=481078800) // from 1985 Mar 31 2:00 
+         return tz4 || (tz4=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-733881600) // from 1946 Sep 30 
+         return tz3 || (tz3=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=-2177453164) // from 1901 
+         return tz2 || (tz2=Ruleset.Timezone(0,"WET"));
+      return tz1 || (tz1=Ruleset.Timezone(-364,"LMT"));
+   }
+}
+
+class Europe_Vienna
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=347158800) // from 1981 
+         return tz4 || (tz4=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-781045200) // from 1945 Apr  2 2:00 
+         return tz3 || (tz3=TZrules.Austria(-3600,"CE%sT"));
+      if (ux>=-938898000) // from 1940 Apr  1 2:00 
+         return tz2 || (tz2=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-1626634800) // from 1918 Jun 16 3:00 
+         return tz3 || (tz3=TZrules.Austria(-3600,"CE%sT"));
+      if (ux>=-2422055120) // from 1893 Apr 
+         return tz2 || (tz2=TZrules.C_Eur(-3600,"CE%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-3920,"LMT"));
+   }
+}
+
+class Europe_Minsk
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7,tz8;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=717544800) // from 1992 Sep 27 0:00s 
+         return tz8 || (tz8=TZrules.Russia(-7200,"EE%sT"));
+      if (ux>=701820000) // from 1992 Mar 29 0:00s 
+         return tz7 || (tz7=Ruleset.Timezone(-10800,"EEST"));
+      if (ux>=686102400) // from 1991 Sep 29 2:00s 
+         return tz3 || (tz3=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=670374000) // from 1991 Mar 31 2:00s 
+         return tz7 || (tz7=Ruleset.Timezone(-10800,"EEST"));
+      if (ux>=631162800) // from 1990 
+         return tz4 || (tz4=Ruleset.Timezone(-10800,"MSK"));
+      if (ux>=-804636000) // from 1944 Jul  3 
+         return tz6 || (tz6=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=-899780400) // from 1941 Jun 28 
+         return tz5 || (tz5=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-1247536800) // from 1930 Jun 21 
+         return tz4 || (tz4=Ruleset.Timezone(-10800,"MSK"));
+      if (ux>=-1441158600) // from 1924 May 2 
+         return tz3 || (tz3=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=-2840147416) // from 1880 Minsk Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-6600,"MMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-6616,"LMT"));
+   }
+}
+
+class Europe_Brussels
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7,tz8;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=220928400) // from 1977 
+         return tz8 || (tz8=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-799279200) // from 1944 Sep  3 
+         return tz7 || (tz7=TZrules.Belgium(-3600,"CE%sT"));
+      if (ux>=-934668000) // from 1940 May 20  2:00s 
+         return tz5 || (tz5=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-1613826000) // from 1918 Nov 11 11:00u 
+         return tz6 || (tz6=TZrules.Belgium(0,"WE%sT"));
+      if (ux>=-1693702800) // from 1916 May  1  0:00 
+         return tz5 || (tz5=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-1740355200) // from 1914 Nov  8 
+         return tz4 || (tz4=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=-2450953050) // from 1892 May  1 12:00 
+         return tz3 || (tz3=Ruleset.Timezone(0,"WET"));
+      if (ux>=-2840141850) // from 1880 Brussels MT
+         return tz2 || (tz2=Ruleset.Timezone(-1050,"BMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-1050,"LMT"));
+   }
+}
+
+class Europe_Sofia
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7,tz8;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=852084000) // from 1997 
+         return tz8 || (tz8=TZrules.EU(-7200,"EE%sT"));
+      if (ux>=662695200) // from 1991 
+         return tz7 || (tz7=TZrules.E_Eur(-7200,"EE%sT"));
+      if (ux>=401864400) // from 1982 Sep 26  2:00 
+         return tz6 || (tz6=TZrules.C_Eur(-7200,"EE%sT"));
+      if (ux>=291762000) // from 1979 Mar 31 23:00 
+         return tz5 || (tz5=TZrules.Bulg(-7200,"EE%sT"));
+      if (ux>=-781041600) // from 1945 Apr  2  3:00 
+         return tz3 || (tz3=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=-857257200) // from 1942 Nov  2  3:00 
+         return tz4 || (tz4=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-2369527016) // from 1894 Nov 30 
+         return tz3 || (tz3=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=-2840146396) // from 1880 Istanbul MT?
+         return tz2 || (tz2=Ruleset.Timezone(-7016,"IMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-5596,"LMT"));
+   }
+}
+
+class Europe_Prague
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=284000400) // from 1979 
+         return tz5 || (tz5=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-798073200) // from 1944 Sep 17 2:00s 
+         return tz4 || (tz4=TZrules.Czech(-3600,"CE%sT"));
+      if (ux>=-2469401864) // from 1891 Oct 
+         return tz3 || (tz3=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-3786829064) // from 1850 Prague Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-3464,"PMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-3464,"LMT"));
+   }
+}
+constant Europe_Bratislava=Europe_Prague;
+
+class Europe_Copenhagen
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=315536400) // from 1980 
+         return tz5 || (tz5=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-781045200) // from 1945 Apr  2 2:00 
+         return tz3 || (tz3=TZrules.Denmark(-3600,"CE%sT"));
+      if (ux>=-857257200) // from 1942 Nov  2 2:00s 
+         return tz4 || (tz4=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-2390518220) // from 1894 Apr 
+         return tz3 || (tz3=TZrules.Denmark(-3600,"CE%sT"));
+      if (ux>=-2524524620) // from 1890 Copenhagen Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-3020,"CMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-3020,"LMT"));
+   }
+}
+
+class Atlantic_Faeroe
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=347155200) // from 1981 
+         return tz3 || (tz3=TZrules.EU(0,"WE%sT"));
+      if (ux>=-1955748776) // from 1908 Jan 11 
+         return tz2 || (tz2=Ruleset.Timezone(0,"WET"));
+      // Torshavn
+      return tz1 || (tz1=Ruleset.Timezone(1624,"LMT"));
+   }
+}
+
+class America_Scoresbysund
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=354664800) // from 1981 Mar 29 
+         return tz4 || (tz4=TZrules.EU(3600,"EG%sT"));
+      if (ux>=323841600) // from 1980 Apr  6 2:00 
+         return tz3 || (tz3=TZrules.C_Eur(7200,"CG%sT"));
+      if (ux>=-1686090660) // from 1916 Jul 28 
+         return tz2 || (tz2=Ruleset.Timezone(7200,"CGT"));
+      // Ittoqqortoormit
+      return tz1 || (tz1=Ruleset.Timezone(5340,"LMT"));
+   }
+}
+
+class America_Godthab
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=323845200) // from 1980 Apr  6 2:00 
+         return tz3 || (tz3=TZrules.EU(10800,"WG%sT"));
+      if (ux>=-1686083584) // from 1916 Jul 28 
+         return tz2 || (tz2=Ruleset.Timezone(10800,"WGT"));
+      // Nuuk
+      return tz1 || (tz1=Ruleset.Timezone(12416,"LMT"));
+   }
+}
+
+class America_Thule
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1686079492) // from 1916 Jul 28 
+         return tz2 || (tz2=TZrules.Thule(14400,"A%sT"));
+      // Pituffik
+      return tz1 || (tz1=Ruleset.Timezone(16508,"LMT"));
+   }
+}
+
+class Europe_Tallinn
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7,tz8,tz9;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=941421600) // from 1999 Nov  1 
+         return tz4 || (tz4=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=906433200) // from 1998 Sep 22 
+         return tz9 || (tz9=TZrules.EU(-7200,"EE%sT"));
+      if (ux>=622598400) // from 1989 Sep 24 2:00s 
+         return tz8 || (tz8=TZrules.C_Eur(-7200,"EE%sT"));
+      if (ux>=606870000) // from 1989 Mar 26 2:00s 
+         return tz7 || (tz7=Ruleset.Timezone(-10800,"EEST"));
+      if (ux>=-797637600) // from 1944 Sep 22 
+         return tz6 || (tz6=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=-892954800) // from 1941 Sep 15 
+         return tz3 || (tz3=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-927943200) // from 1940 Aug  6 
+         return tz5 || (tz5=Ruleset.Timezone(-10800,"MSK"));
+      if (ux>=-1535938740) // from 1921 May 
+         return tz4 || (tz4=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=-1593817200) // from 1919 Jul 
+         return tz2 || (tz2=Ruleset.Timezone(-5940,"TMT"));
+      if (ux>=-1638322740) // from 1918 Feb 
+         return tz3 || (tz3=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-2840146740) // from 1880 Tallinn Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-5940,"TMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-5940,"LMT"));
+   }
+}
+
+class Europe_Helsinki
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=354686400) // from 1981 Mar 29 2:00 
+         return tz4 || (tz4=TZrules.EU(-7200,"EE%sT"));
+      if (ux>=-1535938792) // from 1921 May 
+         return tz3 || (tz3=TZrules.Finland(-7200,"EE%sT"));
+      if (ux>=-2890258792) // from 1878 May 31 Helsinki Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-5992,"HMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-5992,"LMT"));
+   }
+}
+
+class Europe_Paris
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=220928400) // from 1977 
+         return tz6 || (tz6=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-766609200) // from 1945 Sep 16  3:00 
+         return tz5 || (tz5=TZrules.France(-3600,"CE%sT"));
+      if (ux>=-800056800) // from 1944 Aug 25 
+         return tz3 || (tz3=TZrules.France(0,"WE%sT"));
+      if (ux>=-932428800) // from 1940 Jun 14 23:00 
+         return tz4 || (tz4=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-1855958961) // from 1911 Mar 11 
+         return tz3 || (tz3=TZrules.France(0,"WE%sT"));
+      if (ux>=-2486678901) // from 1891 Mar 15  0:01 Paris Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-561,"PMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-561,"LMT"));
+   }
+}
+
+class Europe_Berlin
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=315536400) // from 1980 
+         return tz4 || (tz4=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-781045200) // from 1945 Apr 2 2:00 
+         return tz3 || (tz3=TZrules.Germany(-3600,"CE%sT"));
+      if (ux>=-2422054408) // from 1893 Apr 
+         return tz2 || (tz2=TZrules.C_Eur(-3600,"CE%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-3208,"LMT"));
+   }
+}
+
+class Europe_Gibraltar
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=378687600) // from 1982 
+         return tz4 || (tz4=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-401320800) // from 1957 Apr 14 2:00 
+         return tz3 || (tz3=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=-2821649916) // from 1880 Aug  2 
+         return tz2 || (tz2=TZrules.GB_Eire(0,"%s"));
+      return tz1 || (tz1=Ruleset.Timezone(1284,"LMT"));
+   }
+}
+
+class Europe_Athens
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=347162400) // from 1981 
+         return tz5 || (tz5=TZrules.EU(-7200,"EE%sT"));
+      if (ux>=-812415600) // from 1944 Apr  4 
+         return tz3 || (tz3=TZrules.Greece(-7200,"EE%sT"));
+      if (ux>=-904856400) // from 1941 Apr 30 
+         return tz4 || (tz4=TZrules.Greece(-3600,"CE%sT"));
+      if (ux>=-1686101632) // from 1916 Jul 28 0:01 
+         return tz3 || (tz3=TZrules.Greece(-7200,"EE%sT"));
+      if (ux>=-2344642492) // from 1895 Sep 14 Athens MT
+         return tz2 || (tz2=Ruleset.Timezone(-5692,"AMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-5692,"LMT"));
+   }
+}
+
+class Europe_Budapest
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=338950800) // from 1980 Sep 28  2:00s 
+         return tz4 || (tz4=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-778464000) // from 1945 May  1 23:00 
+         return tz3 || (tz3=TZrules.Hungary(-3600,"CE%sT"));
+      if (ux>=-906930000) // from 1941 Apr  6  2:00 
+         return tz2 || (tz2=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-1640991600) // from 1918 
+         return tz3 || (tz3=TZrules.Hungary(-3600,"CE%sT"));
+      if (ux>=-2500938980) // from 1890 Oct 
+         return tz2 || (tz2=TZrules.C_Eur(-3600,"CE%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-4580,"LMT"));
+   }
+}
+
+class Atlantic_Reykjavik
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-54770400) // from 1968 Apr 7 1:00s 
+         return tz4 || (tz4=Ruleset.Timezone(0,"GMT"));
+      if (ux>=-1956609132) // from 1908 
+         return tz3 || (tz3=TZrules.Iceland(3600,"IS%sT"));
+      if (ux>=-4197047556) // from 1837 Reykjavik Mean Time?
+         return tz2 || (tz2=Ruleset.Timezone(5268,"RMT"));
+      return tz1 || (tz1=Ruleset.Timezone(5244,"LMT"));
+   }
+}
+constant Iceland=Atlantic_Reykjavik;
+
+class Europe_Rome
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=315536400) // from 1980 
+         return tz5 || (tz5=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-804808800) // from 1944 Jul 
+         return tz3 || (tz3=TZrules.Italy(-3600,"CE%sT"));
+      if (ux>=-857257200) // from 1942 Nov  2 2:00s 
+         return tz4 || (tz4=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-2403564596) // from 1893 Nov 
+         return tz3 || (tz3=TZrules.Italy(-3600,"CE%sT"));
+      if (ux>=-3259097396) // from 1866 Sep 22 Rome Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-2996,"RMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-2996,"LMT"));
+   }
+}
+constant Europe_Vatican=Europe_Rome;
+constant Europe_San_Marino=Europe_Rome;
+
+class Europe_Riga
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz10,tz2,tz3,tz4,tz5,tz6,tz7,tz8,tz9;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=951789600) // from 2000 Feb 29 
+         return tz4 || (tz4=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=853812000) // from 1997 Jan 21 
+         return tz10 || (tz10=TZrules.EU(-7200,"EE%sT"));
+      if (ux>=620600400) // from 1989 Sep lastSun 2:00s 
+         return tz9 || (tz9=TZrules.Latvia(-7200,"EE%sT"));
+      if (ux>=604724400) // from 1989 Mar lastSun 2:00s 
+         return tz8 || (tz8=Ruleset.Timezone(-10800,"EEST"));
+      if (ux>=-795826800) // from 1944 Oct 13 
+         return tz7 || (tz7=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=-899521200) // from 1941 Jul 
+         return tz6 || (tz6=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-928029600) // from 1940 Aug  5 
+         return tz5 || (tz5=Ruleset.Timezone(-10800,"MSK"));
+      if (ux>=-1377308184) // from 1926 May 11 
+         return tz4 || (tz4=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=-1597275384) // from 1919 May 22 3:00 
+         return tz2 || (tz2=Ruleset.Timezone(-5784,"RMT"));
+      if (ux>=-1601681784) // from 1919 Apr  1 2:00 
+         return tz3 || (tz3=Ruleset.Timezone(-9384,"LST"));
+      if (ux>=-1618702584) // from 1918 Sep 16 3:00 
+         return tz2 || (tz2=Ruleset.Timezone(-5784,"RMT"));
+      if (ux>=-1632008184) // from 1918 Apr 15 2:00 Latvian Summer
+         return tz3 || (tz3=Ruleset.Timezone(-9384,"LST"));
+      if (ux>=-2840146584) // from 1880 Riga Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-5784,"RMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-5784,"LMT"));
+   }
+}
+
+class Europe_Vaduz
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=347151600) // from 1981 
+         return tz3 || (tz3=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-2385247084) // from 1894 Jun 
+         return tz2 || (tz2=Ruleset.Timezone(-3600,"CET"));
+      return tz1 || (tz1=Ruleset.Timezone(-2284,"LMT"));
+   }
+}
+
+class Europe_Vilnius
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz10,tz11,tz12,tz2,tz3,tz4,tz5,tz6,tz7,tz8,tz9;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=941331600) // from 1999 Oct 31 1:00u 
+         return tz12 || (tz12=TZrules.EU(-7200,"EE%sT"));
+      if (ux>=891133200) // from 1998 Mar 29 1:00u 
+         return tz11 || (tz11=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=883620000) // from 1998 
+         return tz5 || (tz5=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=686102400) // from 1991 Sep 29 2:00s 
+         return tz10 || (tz10=TZrules.C_Eur(-7200,"EE%sT"));
+      if (ux>=670374000) // from 1991 Mar 31 2:00s 
+         return tz9 || (tz9=Ruleset.Timezone(-10800,"EEST"));
+      if (ux>=-802130400) // from 1944 Aug 
+         return tz8 || (tz8=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=-900126000) // from 1941 Jun 24 
+         return tz7 || (tz7=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-928198800) // from 1940 Aug  3 
+         return tz6 || (tz6=Ruleset.Timezone(-10800,"MSK"));
+      if (ux>=-1553565600) // from 1920 Oct  9 
+         return tz4 || (tz4=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=-1561251600) // from 1920 Jul 12 
+         return tz5 || (tz5=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=-1585100136) // from 1919 Oct 10 
+         return tz4 || (tz4=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=-1672536240) // from 1917 Kaunas Mean Time
+         return tz3 || (tz3=Ruleset.Timezone(-5736,"KMT"));
+      if (ux>=-2840146876) // from 1880 Warsaw Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-5040,"WMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-6076,"LMT"));
+   }
+}
+
+class Europe_Luxembourg
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=220928400) // from 1977 
+         return tz7 || (tz7=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-797972400) // from 1944 Sep 18 3:00 
+         return tz6 || (tz6=TZrules.Belgium(-3600,"CE%sT"));
+      if (ux>=-935179200) // from 1940 May 14 3:00 
+         return tz5 || (tz5=TZrules.C_Eur(-3600,"WE%sT"));
+      if (ux>=-1269813600) // from 1929 Oct  6 2:00s 
+         return tz4 || (tz4=TZrules.Belgium(0,"WE%sT"));
+      if (ux>=-1612652400) // from 1918 Nov 25 
+         return tz3 || (tz3=TZrules.Lux(0,"WE%sT"));
+      if (ux>=-2069713476) // from 1904 Jun 
+         return tz2 || (tz2=TZrules.Lux(-3600,"CE%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-1476,"LMT"));
+   }
+}
+
+class Europe_Malta
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=347158800) // from 1981 
+         return tz5 || (tz5=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=102387600) // from 1973 Mar 31 
+         return tz4 || (tz4=TZrules.Malta(-3600,"CE%sT"));
+      if (ux>=-781052400) // from 1945 Apr  2 2:00s 
+         return tz2 || (tz2=TZrules.Italy(-3600,"CE%sT"));
+      if (ux>=-857257200) // from 1942 Nov  2 2:00s 
+         return tz3 || (tz3=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-2403478684) // from 1893 Nov  2 
+         return tz2 || (tz2=TZrules.Italy(-3600,"CE%sT"));
+      // Valletta
+      return tz1 || (tz1=Ruleset.Timezone(-3484,"LMT"));
+   }
+}
+
+class Europe_Chisinau
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz10,tz11,tz12,tz2,tz3,tz4,tz5,tz6,tz7,tz8,tz9;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=852084000) // from 1997 
+         return tz12 || (tz12=TZrules.EU(-7200,"EE%sT"));
+      if (ux>=694231200) // from 1992 
+         return tz11 || (tz11=TZrules.E_Eur(-7200,"EE%sT"));
+      if (ux>=662680800) // from 1991 
+         return tz10 || (tz10=TZrules.Russia(-7200,"EE%sT"));
+      if (ux>=641941200) // from 1990 May 6 
+         return tz9 || (tz9=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=631162800) // from 1990 
+         return tz8 || (tz8=Ruleset.Timezone(-10800,"MSK"));
+      if (ux>=-800143200) // from 1944 Aug 24 
+         return tz7 || (tz7=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=-898138800) // from 1941 Jul 17 
+         return tz6 || (tz6=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-927151200) // from 1940 Aug 15 
+         return tz5 || (tz5=Ruleset.Timezone(-10800,"EEST"));
+      if (ux>=-1213148664) // from 1931 Jul 24 
+         return tz4 || (tz4=TZrules.Romania(-7200,"EE%sT"));
+      if (ux>=-1637114100) // from 1918 Feb 15 Bucharest MT
+         return tz3 || (tz3=Ruleset.Timezone(-6264,"BMT"));
+      if (ux>=-2840147720) // from 1880 Chisinau MT
+         return tz2 || (tz2=Ruleset.Timezone(-6900,"CMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-6920,"LMT"));
+   }
+}
+
+class Europe_Tiraspol
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7,tz8;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=695793600) // from 1992 Jan 19 2:00 
+         return tz7 || (tz7=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=670395600) // from 1991 Mar 31 2:00 
+         return tz8 || (tz8=TZrules.Russia(-7200,"EE%sT"));
+      if (ux>=-800143200) // from 1944 Aug 24 
+         return tz7 || (tz7=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=-898138800) // from 1941 Jul 17 
+         return tz6 || (tz6=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-927151200) // from 1940 Aug 15 
+         return tz5 || (tz5=Ruleset.Timezone(-10800,"EEST"));
+      if (ux>=-1213148664) // from 1931 Jul 24 
+         return tz4 || (tz4=TZrules.Romania(-7200,"EE%sT"));
+      if (ux>=-1637114100) // from 1918 Feb 15 Bucharest MT
+         return tz3 || (tz3=Ruleset.Timezone(-6264,"BMT"));
+      if (ux>=-2840147912) // from 1880 Chisinau MT
+         return tz2 || (tz2=Ruleset.Timezone(-6900,"CMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-7112,"LMT"));
+   }
+}
+
+class Europe_Monaco
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=220928400) // from 1977 
+         return tz5 || (tz5=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-766609200) // from 1945 Sep 16 3:00 
+         return tz4 || (tz4=TZrules.France(-3600,"CE%sT"));
+      if (ux>=-1855958961) // from 1911 Mar 11 
+         return tz3 || (tz3=TZrules.France(0,"WE%sT"));
+      if (ux>=-2486680172) // from 1891 Mar 15 Paris Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-561,"PMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-1772,"LMT"));
+   }
+}
+
+class Europe_Amsterdam
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=220928400) // from 1977 
+         return tz6 || (tz6=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-781045200) // from 1945 Apr  2 2:00 
+         return tz5 || (tz5=TZrules.Neth(-3600,"CE%sT"));
+      if (ux>=-935017200) // from 1940 May 16 0:40 
+         return tz4 || (tz4=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-1025736032) // from 1937 Jul 
+         return tz3 || (tz3=TZrules.Neth(-1200,"NE%sT"));
+      if (ux>=-2450996368) // from 1892 May 
+         return tz2 || (tz2=TZrules.Neth(-1168,"%s"));
+      return tz1 || (tz1=Ruleset.Timezone(-1168,"LMT"));
+   }
+}
+
+class Europe_Oslo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=315536400) // from 1980 
+         return tz4 || (tz4=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-781045200) // from 1945 Apr  2  2:00 
+         return tz2 || (tz2=TZrules.Norway(-3600,"CE%sT"));
+      if (ux>=-927504000) // from 1940 Aug 10 23:00 
+         return tz3 || (tz3=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-2366757780) // from 1895 
+         return tz2 || (tz2=TZrules.Norway(-3600,"CE%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-2580,"LMT"));
+   }
+}
+constant Arctic_Longyearbyen=Europe_Oslo;
+
+class Europe_Warsaw
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=915152400) // from 1999 
+         return tz7 || (tz7=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=228880800) // from 1977 Apr  3 1:00 
+         return tz6 || (tz6=TZrules.W_Eur(-3600,"CE%sT"));
+      if (ux>=-796860000) // from 1944 Oct 
+         return tz5 || (tz5=TZrules.Poland(-3600,"CE%sT"));
+      if (ux>=-931726800) // from 1940 Jun 23 2:00 
+         return tz3 || (tz3=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-1501711200) // from 1922 Jun 
+         return tz5 || (tz5=TZrules.Poland(-3600,"CE%sT"));
+      if (ux>=-1618686000) // from 1918 Sep 16 3:00 
+         return tz4 || (tz4=TZrules.Poland(-7200,"EE%sT"));
+      if (ux>=-1717032240) // from 1915 Aug  5 
+         return tz3 || (tz3=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-2840145840) // from 1880 Warsaw Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-5040,"WMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-5040,"LMT"));
+   }
+}
+constant Poland=Europe_Warsaw;
+
+class Europe_Lisbon
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=828234000) // from 1996 Mar 31 1:00u 
+         return tz6 || (tz6=TZrules.EU(0,"WE%sT"));
+      if (ux>=717555600) // from 1992 Sep 27 1:00s 
+         return tz5 || (tz5=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=433299600) // from 1983 Sep 25 1:00s 
+         return tz4 || (tz4=TZrules.W_Eur(0,"WE%sT"));
+      if (ux>=212544000) // from 1976 Sep 26 1:00 
+         return tz2 || (tz2=TZrules.Port(0,"WE%sT"));
+      if (ux>=-118274400) // from 1966 Apr  3 2:00 
+         return tz3 || (tz3=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=-1849562608) // from 1911 May 24 
+         return tz2 || (tz2=TZrules.Port(0,"WE%sT"));
+      if (ux>=-2713908208) // from 1884 Lisbon Mean Time
+         return tz1 || (tz1=Ruleset.Timezone(2192,"LMT"));
+      return tz1 || (tz1=Ruleset.Timezone(2192,"LMT"));
+   }
+}
+constant Portugal=Europe_Lisbon;
+
+class Atlantic_Azores
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=733280400) // from 1993 Mar 28 1:00u 
+         return tz7 || (tz7=TZrules.EU(3600,"AZO%sT"));
+      if (ux>=717559200) // from 1992 Sep 27 1:00s 
+         return tz6 || (tz6=TZrules.EU(0,"WE%sT"));
+      if (ux>=433303200) // from 1983 Sep 25 1:00s 
+         return tz5 || (tz5=TZrules.W_Eur(3600,"AZO%sT"));
+      if (ux>=-118281600) // from 1966 Apr  3 2:00 
+         return tz4 || (tz4=TZrules.Port(3600,"AZO%sT"));
+      if (ux>=-1849557900) // from 1911 May 24 Azores Time
+         return tz3 || (tz3=TZrules.Port(7200,"AZO%sT"));
+      if (ux>=-2713904240) // from 1884 Horta Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(6900,"HMT"));
+      // Ponta Delgada
+      return tz1 || (tz1=Ruleset.Timezone(6160,"LMT"));
+   }
+}
+
+class Atlantic_Madeira
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=433299600) // from 1983 Sep 25 1:00s 
+         return tz5 || (tz5=TZrules.EU(0,"WE%sT"));
+      if (ux>=-118278000) // from 1966 Apr  3 2:00 
+         return tz4 || (tz4=TZrules.Port(0,"WE%sT"));
+      if (ux>=-1849560720) // from 1911 May 24 Madeira Time
+         return tz3 || (tz3=TZrules.Port(3600,"MAD%sT"));
+      if (ux>=-2713906344) // from 1884 Funchal Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(4080,"FMT"));
+      // Funchal
+      return tz1 || (tz1=Ruleset.Timezone(4056,"LMT"));
+   }
+}
+
+class Europe_Bucharest
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=852084000) // from 1997 
+         return tz6 || (tz6=TZrules.EU(-7200,"EE%sT"));
+      if (ux>=757389600) // from 1994 
+         return tz5 || (tz5=TZrules.E_Eur(-7200,"EE%sT"));
+      if (ux>=662695200) // from 1991 
+         return tz3 || (tz3=TZrules.Romania(-7200,"EE%sT"));
+      if (ux>=354672000) // from 1981 Mar 29 2:00s 
+         return tz4 || (tz4=TZrules.C_Eur(-7200,"EE%sT"));
+      if (ux>=-1213148664) // from 1931 Jul 24 
+         return tz3 || (tz3=TZrules.Romania(-7200,"EE%sT"));
+      if (ux>=-2469404664) // from 1891 Oct Bucharest MT
+         return tz2 || (tz2=Ruleset.Timezone(-6264,"BMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-6264,"LMT"));
+   }
+}
+
+class Europe_Kaliningrad
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=670374000) // from 1991 Mar 31 2:00s 
+         return tz5 || (tz5=TZrules.Russia(-7200,"EE%sT"));
+      if (ux>=-757375200) // from 1946 
+         return tz4 || (tz4=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=-788914800) // from 1945 
+         return tz3 || (tz3=TZrules.Poland(-7200,"CE%sT"));
+      if (ux>=-2422056120) // from 1893 Apr 
+         return tz2 || (tz2=TZrules.C_Eur(-3600,"CE%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(-4920,"LMT"));
+   }
+}
+
+class Europe_Moscow
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=695779200) // from 1992 Jan 19 2:00s 
+         return tz4 || (tz4=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=670374000) // from 1991 Mar 31 2:00s 
+         return tz6 || (tz6=TZrules.Russia(-7200,"EE%sT"));
+      if (ux>=-1247536800) // from 1930 Jun 21 
+         return tz4 || (tz4=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=-1491166800) // from 1922 Oct 
+         return tz5 || (tz5=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=-1593797352) // from 1919 Jul  1 2:00 
+         return tz4 || (tz4=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=-1688265000) // from 1916 Jul  3 
+         return tz3 || (tz3=TZrules.Russia(-9048,"%s"));
+      if (ux>=-2840149820) // from 1880 Moscow Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-9000,"MMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-9020,"LMT"));
+   }
+}
+constant W_SU=Europe_Moscow;
+
+class Europe_Samara
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=687916800) // from 1991 Oct 20 3:00 Samara Time
+         return tz6 || (tz6=TZrules.Russia(-14400,"SAM%sT"));
+      if (ux>=686102400) // from 1991 Sep 29 2:00s 
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"KUYT"));
+      if (ux>=670374000) // from 1991 Mar 31 2:00s 
+         return tz5 || (tz5=TZrules.Russia(-7200,"KUY%sT"));
+      if (ux>=606866400) // from 1989 Mar 26 2:00s 
+         return tz4 || (tz4=TZrules.Russia(-10800,"KUY%sT"));
+      if (ux>=-1247540400) // from 1930 Jun 21 
+         return tz3 || (tz3=TZrules.Russia(-14400,"KUY%sT"));
+      if (ux>=-1593825636) // from 1919 Jul  1 2:00 Kuybyshev
+         return tz2 || (tz2=Ruleset.Timezone(-10800,"KUYT"));
+      return tz1 || (tz1=Ruleset.Timezone(-12036,"LMT"));
+   }
+}
+
+class Asia_Yekaterinburg
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=695772000) // from 1992 Jan 19 2:00s Yekaterinburg Time
+         return tz5 || (tz5=TZrules.Russia(-18000,"YEK%sT"));
+      if (ux>=670366800) // from 1991 Mar 31 2:00s 
+         return tz4 || (tz4=TZrules.Russia(-14400,"SVE%sT"));
+      if (ux>=-1247544000) // from 1930 Jun 21 
+         return tz3 || (tz3=TZrules.Russia(-18000,"SVE%sT"));
+      if (ux>=-1592611344) // from 1919 Jul 15 4:00 Sverdlovsk Time
+         return tz2 || (tz2=Ruleset.Timezone(-14400,"SVET"));
+      return tz1 || (tz1=Ruleset.Timezone(-14544,"LMT"));
+   }
+}
+
+class Asia_Omsk
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=695768400) // from 1992 Jan 19 2:00s 
+         return tz3 || (tz3=TZrules.Russia(-21600,"OMS%sT"));
+      if (ux>=670363200) // from 1991 Mar 31 2:00s 
+         return tz4 || (tz4=TZrules.Russia(-18000,"OMS%sT"));
+      if (ux>=-1247547600) // from 1930 Jun 21 
+         return tz3 || (tz3=TZrules.Russia(-21600,"OMS%sT"));
+      if (ux>=-1582088016) // from 1919 Nov 14 Omsk TIme
+         return tz2 || (tz2=Ruleset.Timezone(-18000,"OMST"));
+      return tz1 || (tz1=Ruleset.Timezone(-17616,"LMT"));
+   }
+}
+
+class Asia_Novosibirsk
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=738144000) // from 1993 May 23 
+         return tz4 || (tz4=TZrules.Russia(-21600,"NOV%sT"));
+      if (ux>=695764800) // from 1992 Jan 19 2:00s says Shanks
+         return tz3 || (tz3=TZrules.Russia(-25200,"NOV%sT"));
+      if (ux>=670359600) // from 1991 Mar 31 2:00s 
+         return tz4 || (tz4=TZrules.Russia(-21600,"NOV%sT"));
+      if (ux>=-1247551200) // from 1930 Jun 21 
+         return tz3 || (tz3=TZrules.Russia(-25200,"NOV%sT"));
+      if (ux>=-1579476700) // from 1919 Dec 14 6:00 Novosibirsk Time
+         return tz2 || (tz2=Ruleset.Timezone(-21600,"NOVT"));
+      return tz1 || (tz1=Ruleset.Timezone(-19900,"LMT"));
+   }
+}
+
+class Asia_Krasnoyarsk
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=695764800) // from 1992 Jan 19 2:00s 
+         return tz3 || (tz3=TZrules.Russia(-25200,"KRA%sT"));
+      if (ux>=670359600) // from 1991 Mar 31 2:00s 
+         return tz4 || (tz4=TZrules.Russia(-21600,"KRA%sT"));
+      if (ux>=-1247551200) // from 1930 Jun 21 
+         return tz3 || (tz3=TZrules.Russia(-25200,"KRA%sT"));
+      if (ux>=-1577513480) // from 1920 Jan  6 Krasnoyarsk Time
+         return tz2 || (tz2=Ruleset.Timezone(-21600,"KRAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-22280,"LMT"));
+   }
+}
+
+class Asia_Irkutsk
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=695761200) // from 1992 Jan 19 2:00s 
+         return tz4 || (tz4=TZrules.Russia(-28800,"IRK%sT"));
+      if (ux>=670356000) // from 1991 Mar 31 2:00s 
+         return tz5 || (tz5=TZrules.Russia(-25200,"IRK%sT"));
+      if (ux>=-1247554800) // from 1930 Jun 21 
+         return tz4 || (tz4=TZrules.Russia(-28800,"IRK%sT"));
+      if (ux>=-1575874640) // from 1920 Jan 25 Irkutsk Time
+         return tz3 || (tz3=Ruleset.Timezone(-25200,"IRKT"));
+      if (ux>=-2840165840) // from 1880 Irkutsk Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-25040,"IMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-25040,"LMT"));
+   }
+}
+
+class Asia_Yakutsk
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=695757600) // from 1992 Jan 19 2:00s 
+         return tz3 || (tz3=TZrules.Russia(-32400,"YAK%sT"));
+      if (ux>=670352400) // from 1991 Mar 31 2:00s 
+         return tz4 || (tz4=TZrules.Russia(-28800,"YAK%sT"));
+      if (ux>=-1247558400) // from 1930 Jun 21 
+         return tz3 || (tz3=TZrules.Russia(-32400,"YAK%sT"));
+      if (ux>=-1579423120) // from 1919 Dec 15 Yakutsk Time
+         return tz2 || (tz2=Ruleset.Timezone(-28800,"YAKT"));
+      return tz1 || (tz1=Ruleset.Timezone(-31120,"LMT"));
+   }
+}
+
+class Asia_Vladivostok
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=695754000) // from 1992 Jan 19 2:00s 
+         return tz3 || (tz3=TZrules.Russia(-36000,"VLA%sT"));
+      if (ux>=670348800) // from 1991 Mar 31 2:00s 
+         return tz4 || (tz4=TZrules.Russia(-32400,"VLA%sST"));
+      if (ux>=-1247562000) // from 1930 Jun 21 
+         return tz3 || (tz3=TZrules.Russia(-36000,"VLA%sT"));
+      if (ux>=-1487321264) // from 1922 Nov 15 Vladivostok Time
+         return tz2 || (tz2=Ruleset.Timezone(-32400,"VLAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-31664,"LMT"));
+   }
+}
+
+class Asia_Magadan
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=695750400) // from 1992 Jan 19 2:00s 
+         return tz3 || (tz3=TZrules.Russia(-39600,"MAG%sT"));
+      if (ux>=670345200) // from 1991 Mar 31 2:00s 
+         return tz4 || (tz4=TZrules.Russia(-36000,"MAG%sT"));
+      if (ux>=-1247565600) // from 1930 Jun 21 
+         return tz3 || (tz3=TZrules.Russia(-39600,"MAG%sT"));
+      if (ux>=-1441188192) // from 1924 May  2 Magadan Time
+         return tz2 || (tz2=Ruleset.Timezone(-36000,"MAGT"));
+      return tz1 || (tz1=Ruleset.Timezone(-36192,"LMT"));
+   }
+}
+
+class Asia_Kamchatka
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=695746800) // from 1992 Jan 19 2:00s 
+         return tz3 || (tz3=TZrules.Russia(-43200,"PET%sT"));
+      if (ux>=670341600) // from 1991 Mar 31 2:00s 
+         return tz4 || (tz4=TZrules.Russia(-39600,"PET%sT"));
+      if (ux>=-1247569200) // from 1930 Jun 21 
+         return tz3 || (tz3=TZrules.Russia(-43200,"PET%sT"));
+      if (ux>=-1487759676) // from 1922 Nov 10 P-K Time
+         return tz2 || (tz2=Ruleset.Timezone(-39600,"PETT"));
+      return tz1 || (tz1=Ruleset.Timezone(-38076,"LMT"));
+   }
+}
+
+class Asia_Anadyr
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=695746800) // from 1992 Jan 19 2:00s 
+         return tz4 || (tz4=TZrules.Russia(-43200,"ANA%sT"));
+      if (ux>=670341600) // from 1991 Mar 31 2:00s 
+         return tz5 || (tz5=TZrules.Russia(-39600,"ANA%sT"));
+      if (ux>=386420400) // from 1982 Apr  1 0:00s 
+         return tz4 || (tz4=TZrules.Russia(-43200,"ANA%sT"));
+      if (ux>=-1247572800) // from 1930 Jun 21 
+         return tz3 || (tz3=TZrules.Russia(-46800,"ANA%sT"));
+      if (ux>=-1441194596) // from 1924 May  2 Anadyr Time
+         return tz2 || (tz2=Ruleset.Timezone(-43200,"ANAT"));
+      return tz1 || (tz1=Ruleset.Timezone(-42596,"LMT"));
+   }
+}
+
+class Europe_Madrid
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=284000400) // from 1979 
+         return tz4 || (tz4=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-733881600) // from 1946 Sep 30 
+         return tz3 || (tz3=TZrules.Spain(-3600,"CE%sT"));
+      if (ux>=-2177451916) // from 1901 
+         return tz2 || (tz2=TZrules.Spain(0,"WE%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(884,"LMT"));
+   }
+}
+
+class Africa_Ceuta
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=504918000) // from 1986 
+         return tz7 || (tz7=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=448243200) // from 1984 Mar 16 
+         return tz6 || (tz6=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=-1293840000) // from 1929 
+         return tz5 || (tz5=TZrules.SpainAfrica(0,"WE%sT"));
+      if (ux>=-1451692800) // from 1924 
+         return tz4 || (tz4=TZrules.Spain(0,"WE%sT"));
+      if (ux>=-1616810400) // from 1918 Oct  7 23:00 
+         return tz2 || (tz2=Ruleset.Timezone(0,"WET"));
+      if (ux>=-1630112400) // from 1918 May  6 23:00 
+         return tz3 || (tz3=Ruleset.Timezone(-3600,"WEST"));
+      if (ux>=-2177451524) // from 1901 
+         return tz2 || (tz2=Ruleset.Timezone(0,"WET"));
+      return tz1 || (tz1=Ruleset.Timezone(1276,"LMT"));
+   }
+}
+
+class Atlantic_Canary
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=338947200) // from 1980 Sep 28 0:00s 
+         return tz5 || (tz5=TZrules.EU(0,"WE%sT"));
+      if (ux>=323827200) // from 1980 Apr  6 0:00s 
+         return tz4 || (tz4=Ruleset.Timezone(-3600,"WEST"));
+      if (ux>=-733874400) // from 1946 Sep 30 1:00 
+         return tz3 || (tz3=Ruleset.Timezone(0,"WET"));
+      if (ux>=-1509663504) // from 1922 Mar Canaries Time
+         return tz2 || (tz2=Ruleset.Timezone(3600,"CANT"));
+      // Las Palmas de Gran C.
+      return tz1 || (tz1=Ruleset.Timezone(3696,"LMT"));
+   }
+}
+
+class Europe_Stockholm
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=315529200) // from 1980 
+         return tz5 || (tz5=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-1680487200) // from 1916 Sep 30 23:00s 
+         return tz3 || (tz3=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=-1695088800) // from 1916 Apr 14 23:00s 
+         return tz4 || (tz4=Ruleset.Timezone(-7200,"CEST"));
+      if (ux>=-2208989532) // from 1900 Jan  1  1:00 
+         return tz3 || (tz3=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=-2890257132) // from 1878 May 31 Stockholm MT
+         return tz2 || (tz2=Ruleset.Timezone(-4332,"SMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-4332,"LMT"));
+   }
+}
+
+class Europe_Zurich
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=347158800) // from 1981 
+         return tz4 || (tz4=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-2385246584) // from 1894 Jun 
+         return tz3 || (tz3=TZrules.Swiss(-3600,"CE%sT"));
+      if (ux>=-3827954048) // from 1848 Sep 12 Bern Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-1784,"BMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-2048,"LMT"));
+   }
+}
+
+class Europe_Istanbul
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=662695200) // from 1991 
+         return tz6 || (tz6=TZrules.EU(-7200,"EE%sT"));
+      if (ux>=504928800) // from 1986 
+         return tz5 || (tz5=TZrules.C_Eur(-7200,"EE%sT"));
+      if (ux>=482814000) // from 1985 Apr 20 
+         return tz3 || (tz3=TZrules.Turkey(-7200,"EE%sT"));
+      if (ux>=277268400) // from 1978 Oct 15 Turkey Time
+         return tz4 || (tz4=TZrules.Turkey(-10800,"TR%sT"));
+      if (ux>=-1869875816) // from 1910 Oct 
+         return tz3 || (tz3=TZrules.Turkey(-7200,"EE%sT"));
+      if (ux>=-2840147752) // from 1880 Istanbul Mean Time?
+         return tz2 || (tz2=Ruleset.Timezone(-7016,"IMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-6952,"LMT"));
+   }
+}
+constant Turkey=Europe_Istanbul;
+constant Asia_Istanbul=Europe_Istanbul;
+
+class Europe_Kiev
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7,tz8;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=788925600) // from 1995 
+         return tz8 || (tz8=TZrules.EU(-7200,"EE%sT"));
+      if (ux>=694216800) // from 1992 
+         return tz7 || (tz7=TZrules.E_Eur(-7200,"EE%sT"));
+      if (ux>=646786800) // from 1990 Jul  1 2:00 
+         return tz3 || (tz3=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=631162800) // from 1990 
+         return tz4 || (tz4=Ruleset.Timezone(-10800,"MSK"));
+      if (ux>=-825375600) // from 1943 Nov  6 
+         return tz6 || (tz6=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=-892522800) // from 1941 Sep 20 
+         return tz5 || (tz5=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-1247536800) // from 1930 Jun 21 
+         return tz4 || (tz4=Ruleset.Timezone(-10800,"MSK"));
+      if (ux>=-1441159324) // from 1924 May  2 
+         return tz3 || (tz3=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=-2840148124) // from 1880 Kiev Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(-7324,"KMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-7324,"LMT"));
+   }
+}
+
+class Europe_Uzhgorod
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7,tz8,tz9;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=788925600) // from 1995 
+         return tz9 || (tz9=TZrules.EU(-7200,"EE%sT"));
+      if (ux>=694216800) // from 1992 
+         return tz8 || (tz8=TZrules.E_Eur(-7200,"EE%sT"));
+      if (ux>=670384800) // from 1991 Mar 31 3:00 
+         return tz7 || (tz7=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=646786800) // from 1990 Jul  1 2:00 
+         return tz2 || (tz2=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=631162800) // from 1990 
+         return tz6 || (tz6=Ruleset.Timezone(-10800,"MSK"));
+      if (ux>=-773456400) // from 1945 Jun 29 
+         return tz5 || (tz5=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=-794714400) // from 1944 Oct 26 
+         return tz2 || (tz2=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=-796860000) // from 1944 Oct 
+         return tz4 || (tz4=Ruleset.Timezone(-7200,"CEST"));
+      if (ux>=-946774800) // from 1940 
+         return tz3 || (tz3=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-2500939752) // from 1890 Oct 
+         return tz2 || (tz2=Ruleset.Timezone(-3600,"CET"));
+      return tz1 || (tz1=Ruleset.Timezone(-5352,"LMT"));
+   }
+}
+
+class Europe_Zaporozhye
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7,tz8;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=788925600) // from 1995 
+         return tz8 || (tz8=TZrules.EU(-7200,"EE%sT"));
+      if (ux>=670395600) // from 1991 Mar 31 2:00 
+         return tz7 || (tz7=TZrules.E_Eur(-7200,"EE%sT"));
+      if (ux>=-826412400) // from 1943 Oct 25 
+         return tz6 || (tz6=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=-894769200) // from 1941 Aug 25 
+         return tz5 || (tz5=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-1247536800) // from 1930 Jun 21 
+         return tz4 || (tz4=Ruleset.Timezone(-10800,"MSK"));
+      if (ux>=-1441160400) // from 1924 May  2 
+         return tz3 || (tz3=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=-2840149240) // from 1880 Central Ukraine T
+         return tz2 || (tz2=Ruleset.Timezone(-8400,"CUT"));
+      return tz1 || (tz1=Ruleset.Timezone(-8440,"LMT"));
+   }
+}
+
+class Europe_Simferopol
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz10,tz2,tz3,tz4,tz5,tz6,tz7,tz8,tz9;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=857185200) // from 1997 Mar lastSun 1:00u 
+         return tz10 || (tz10=TZrules.EU(-7200,"EE%sT"));
+      if (ux>=846374400) // from 1996 Oct 27 3:00s 
+         return tz6 || (tz6=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=828230400) // from 1996 Mar 31 3:00s 
+         return tz9 || (tz9=Ruleset.Timezone(-14400,"MSD"));
+      if (ux>=767761200) // from 1994 May 
+         return tz8 || (tz8=TZrules.E_Eur(-10800,"MSK/MSD"));
+      if (ux>=694216800) // from 1992 
+         return tz7 || (tz7=TZrules.E_Eur(-7200,"EE%sT"));
+      if (ux>=646786800) // from 1990 Jul  1 2:00 
+         return tz3 || (tz3=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=631162800) // from 1990 
+         return tz4 || (tz4=Ruleset.Timezone(-10800,"MSK"));
+      if (ux>=-811634400) // from 1944 Apr 13 
+         return tz6 || (tz6=TZrules.Russia(-10800,"MSK/MSD"));
+      if (ux>=-888894000) // from 1941 Nov 
+         return tz5 || (tz5=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-1247536800) // from 1930 Jun 21 
+         return tz4 || (tz4=Ruleset.Timezone(-10800,"MSK"));
+      if (ux>=-1441160160) // from 1924 May  2 
+         return tz3 || (tz3=Ruleset.Timezone(-7200,"EET"));
+      if (ux>=-2840148984) // from 1880 Simferopol Mean T
+         return tz2 || (tz2=Ruleset.Timezone(-8160,"SMT"));
+      return tz1 || (tz1=Ruleset.Timezone(-8184,"LMT"));
+   }
+}
+
+class Europe_Belgrade
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=407199600) // from 1982 Nov 27 
+         return tz5 || (tz5=TZrules.EU(-3600,"CE%sT"));
+      if (ux>=-766623600) // from 1945 Sep 16  2:00s 
+         return tz2 || (tz2=Ruleset.Timezone(-3600,"CET"));
+      if (ux>=-777942000) // from 1945 May  8  2:00s 
+         return tz4 || (tz4=Ruleset.Timezone(-7200,"CEST"));
+      if (ux>=-905824800) // from 1941 Apr 18 23:00 
+         return tz3 || (tz3=TZrules.C_Eur(-3600,"CE%sT"));
+      if (ux>=-2713915320) // from 1884 
+         return tz2 || (tz2=Ruleset.Timezone(-3600,"CET"));
+      return tz1 || (tz1=Ruleset.Timezone(-4920,"LMT"));
+   }
+}
+constant Europe_Ljubljana=Europe_Belgrade;
+constant Europe_Sarajevo=Europe_Belgrade;
+constant Europe_Skopje=Europe_Belgrade;
+constant Europe_Zagreb=Europe_Belgrade;
+
+class America_New_York
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-94712400) // from 1967 
+         return tz2 || (tz2=TZrules.US(18000,"E%sT"));
+      if (ux>=-757400400) // from 1946 
+         return tz3 || (tz3=TZrules.NYC(18000,"E%sT"));
+      if (ux>=-883630800) // from 1942 
+         return tz2 || (tz2=TZrules.US(18000,"E%sT"));
+      if (ux>=-1577941200) // from 1920 
+         return tz3 || (tz3=TZrules.NYC(18000,"E%sT"));
+      if (ux>=-2717651038) // from 1883 Nov 18 12:00 
+         return tz2 || (tz2=TZrules.US(18000,"E%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(17762,"LMT"));
+   }
+}
+constant US_Eastern=America_New_York;
+constant EST5EDT=America_New_York;
+
+class America_Chicago
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-94716000) // from 1967 
+         return tz2 || (tz2=TZrules.US(21600,"C%sT"));
+      if (ux>=-757404000) // from 1946 
+         return tz3 || (tz3=TZrules.Chicago(21600,"C%sT"));
+      if (ux>=-883634400) // from 1942 
+         return tz2 || (tz2=TZrules.US(21600,"C%sT"));
+      if (ux>=-1045414800) // from 1936 Nov 15 2:00 
+         return tz3 || (tz3=TZrules.Chicago(21600,"C%sT"));
+      if (ux>=-1067832000) // from 1936 Mar  1 2:00 
+         return tz4 || (tz4=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-1577944800) // from 1920 
+         return tz3 || (tz3=TZrules.Chicago(21600,"C%sT"));
+      if (ux>=-2717647764) // from 1883 Nov 18 12:00 
+         return tz2 || (tz2=TZrules.US(21600,"C%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(21036,"LMT"));
+   }
+}
+constant US_Central=America_Chicago;
+constant CST6CDT=America_Chicago;
+
+class America_Denver
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-94719600) // from 1967 
+         return tz2 || (tz2=TZrules.US(25200,"M%sT"));
+      if (ux>=-757407600) // from 1946 
+         return tz3 || (tz3=TZrules.Denver(25200,"M%sT"));
+      if (ux>=-883638000) // from 1942 
+         return tz2 || (tz2=TZrules.US(25200,"M%sT"));
+      if (ux>=-1577948400) // from 1920 
+         return tz3 || (tz3=TZrules.Denver(25200,"M%sT"));
+      if (ux>=-2717643604) // from 1883 Nov 18 12:00 
+         return tz2 || (tz2=TZrules.US(25200,"M%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(25196,"LMT"));
+   }
+}
+constant Navajo=America_Denver;
+constant US_Mountain=America_Denver;
+constant America_Shiprock=America_Denver;
+constant MST7MDT=America_Denver;
+
+class America_Los_Angeles
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-94723200) // from 1967 
+         return tz2 || (tz2=TZrules.US(28800,"P%sT"));
+      if (ux>=-757411200) // from 1946 
+         return tz3 || (tz3=TZrules.CA(28800,"P%sT"));
+      if (ux>=-2717640422) // from 1883 Nov 18 12:00 
+         return tz2 || (tz2=TZrules.US(28800,"P%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(28378,"LMT"));
+   }
+}
+constant US_Pacific=America_Los_Angeles;
+constant PST8PDT=America_Los_Angeles;
+constant US_Pacific_New=America_Los_Angeles;
+
+class America_Juneau
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=436302000) // from 1983 Oct 30 2:00 
+         return tz4 || (tz4=TZrules.US(32400,"AK%sT"));
+      if (ux>=-31507200) // from 1969 
+         return tz3 || (tz3=TZrules.US(28800,"P%sT"));
+      if (ux>=-757411200) // from 1946 
+         return tz2 || (tz2=Ruleset.Timezone(28800,"PST"));
+      if (ux>=-883584000) // from 1942 
+         return tz3 || (tz3=TZrules.US(28800,"P%sT"));
+      if (ux>=-2188954939) // from 1900 Aug 20 12:00 
+         return tz2 || (tz2=Ruleset.Timezone(28800,"PST"));
+      return tz1 || (tz1=Ruleset.Timezone(32261,"LMT"));
+   }
+}
+
+class America_Yakutat
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=436298400) // from 1983 Oct 30 2:00 
+         return tz4 || (tz4=TZrules.US(32400,"AK%sT"));
+      if (ux>=-31503600) // from 1969 
+         return tz3 || (tz3=TZrules.US(32400,"Y%sT"));
+      if (ux>=-757414800) // from 1946 
+         return tz2 || (tz2=Ruleset.Timezone(32400,"YST"));
+      if (ux>=-883580400) // from 1942 
+         return tz3 || (tz3=TZrules.US(32400,"Y%sT"));
+      if (ux>=-2188953665) // from 1900 Aug 20 12:00 
+         return tz2 || (tz2=Ruleset.Timezone(32400,"YST"));
+      return tz1 || (tz1=Ruleset.Timezone(33535,"LMT"));
+   }
+}
+
+class America_Anchorage
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=436294800) // from 1983 Oct 30 2:00 
+         return tz6 || (tz6=TZrules.US(32400,"AK%sT"));
+      if (ux>=-31500000) // from 1969 
+         return tz5 || (tz5=TZrules.US(36000,"AH%sT"));
+      if (ux>=-86882400) // from 1967 Apr 
+         return tz4 || (tz4=Ruleset.Timezone(36000,"AHST"));
+      if (ux>=-757418400) // from 1946 
+         return tz2 || (tz2=Ruleset.Timezone(36000,"CAT"));
+      if (ux>=-883576800) // from 1942 
+         return tz3 || (tz3=TZrules.US(36000,"CAT/CAWT"));
+      if (ux>=-2188951224) // from 1900 Aug 20 12:00 
+         return tz2 || (tz2=Ruleset.Timezone(36000,"CAT"));
+      return tz1 || (tz1=Ruleset.Timezone(35976,"LMT"));
+   }
+}
+constant US_Alaska=America_Anchorage;
+
+class America_Nome
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=436291200) // from 1983 Oct 30 2:00 
+         return tz6 || (tz6=TZrules.US(32400,"AK%sT"));
+      if (ux>=-31496400) // from 1969 
+         return tz5 || (tz5=TZrules.US(39600,"B%sT"));
+      if (ux>=-86878800) // from 1967 Apr 
+         return tz4 || (tz4=Ruleset.Timezone(39600,"BST"));
+      if (ux>=-757422000) // from 1946 
+         return tz2 || (tz2=Ruleset.Timezone(39600,"NST"));
+      if (ux>=-883573200) // from 1942 
+         return tz3 || (tz3=TZrules.US(39600,"N%sT"));
+      if (ux>=-2188947502) // from 1900 Aug 20 12:00 
+         return tz2 || (tz2=Ruleset.Timezone(39600,"NST"));
+      return tz1 || (tz1=Ruleset.Timezone(39698,"LMT"));
+   }
+}
+
+class America_Adak
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=436291200) // from 1983 Oct 30 2:00 
+         return tz6 || (tz6=TZrules.US(36000,"HA%sT"));
+      if (ux>=-31496400) // from 1969 
+         return tz5 || (tz5=TZrules.US(39600,"B%sT"));
+      if (ux>=-86878800) // from 1967 Apr 
+         return tz4 || (tz4=Ruleset.Timezone(39600,"BST"));
+      if (ux>=-757422000) // from 1946 
+         return tz2 || (tz2=Ruleset.Timezone(39600,"NST"));
+      if (ux>=-883573200) // from 1942 
+         return tz3 || (tz3=TZrules.US(39600,"N%sT"));
+      if (ux>=-2188944802) // from 1900 Aug 20 12:00 
+         return tz2 || (tz2=Ruleset.Timezone(39600,"NST"));
+      return tz1 || (tz1=Ruleset.Timezone(42398,"LMT"));
+   }
+}
+constant America_Atka=America_Adak;
+constant US_Aleutian=America_Adak;
+
+class Pacific_Honolulu
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-712225800) // from 1947 Jun  8 2:00 
+         return tz5 || (tz5=Ruleset.Timezone(36000,"HST"));
+      if (ux>=-1155472200) // from 1933 May 21 2:00 
+         return tz4 || (tz4=TZrules.US(37800,"H%sT"));
+      if (ux>=-1157283000) // from 1933 Apr 30 2:00 
+         return tz3 || (tz3=Ruleset.Timezone(34200,"HDT"));
+      if (ux>=-2208907714) // from 1900 Jan  1 12:00 
+         return tz2 || (tz2=Ruleset.Timezone(37800,"HST"));
+      return tz1 || (tz1=Ruleset.Timezone(37886,"LMT"));
+   }
+}
+constant US_Hawaii=Pacific_Honolulu;
+constant HST=Pacific_Honolulu;
+
+class America_Phoenix
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-63183600) // from 1968 
+         return tz3 || (tz3=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-94669200) // from 1967 
+         return tz2 || (tz2=TZrules.US(25200,"M%sT"));
+      if (ux>=-796888740) // from 1944 Oct  1 00:01 
+         return tz3 || (tz3=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-813949140) // from 1944 Mar 17 00:01 
+         return tz2 || (tz2=TZrules.US(25200,"M%sT"));
+      if (ux>=-820562340) // from 1944 Jan  1 00:01 
+         return tz3 || (tz3=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-2717641902) // from 1883 Nov 18 12:00 
+         return tz2 || (tz2=TZrules.US(25200,"M%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(26898,"LMT"));
+   }
+}
+constant US_Arizona=America_Phoenix;
+constant MST=America_Phoenix;
+
+class America_Boise
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=129114000) // from 1974 Feb  3 2:00 
+         return tz3 || (tz3=TZrules.US(25200,"M%sT"));
+      if (ux>=126205200) // from 1974 
+         return tz4 || (tz4=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-1471845600) // from 1923 May 13 2:00 
+         return tz3 || (tz3=TZrules.US(25200,"M%sT"));
+      if (ux>=-2717640911) // from 1883 Nov 18 12:00 
+         return tz2 || (tz2=TZrules.US(28800,"P%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(27889,"LMT"));
+   }
+}
+
+class America_Indianapolis
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=31518000) // from 1971 
+         return tz4 || (tz4=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-31518000) // from 1969 
+         return tz6 || (tz6=TZrules.US(18000,"E%sT"));
+      if (ux>=-368640000) // from 1958 Apr 27 2:00 
+         return tz4 || (tz4=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-386787600) // from 1957 Sep 29 2:00 
+         return tz5 || (tz5=Ruleset.Timezone(21600,"CST"));
+      if (ux>=-463636800) // from 1955 Apr 24 2:00 
+         return tz4 || (tz4=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-757404000) // from 1946 
+         return tz3 || (tz3=TZrules.Indianapolis(21600,"C%sT"));
+      if (ux>=-883634400) // from 1942 
+         return tz2 || (tz2=TZrules.US(21600,"C%sT"));
+      if (ux>=-1577944800) // from 1920 
+         return tz3 || (tz3=TZrules.Indianapolis(21600,"C%sT"));
+      if (ux>=-2717648122) // from 1883 Nov 18 12:00 
+         return tz2 || (tz2=TZrules.US(21600,"C%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(20678,"LMT"));
+   }
+}
+constant America_Fort_Wayne=America_Indianapolis;
+constant US_East_Indiana=America_Indianapolis;
+constant America_Indiana_Indianapolis=America_Indianapolis;
+constant EST=America_Indianapolis;
+
+class America_Indiana_Marengo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=189284400) // from 1976 
+         return tz4 || (tz4=Ruleset.Timezone(18000,"EST"));
+      if (ux>=152089200) // from 1974 Oct 27 2:00 
+         return tz5 || (tz5=TZrules.US(18000,"E%sT"));
+      if (ux>=126651600) // from 1974 Jan  6 2:00 
+         return tz6 || (tz6=Ruleset.Timezone(18000,"CDT"));
+      if (ux>=-31518000) // from 1969 
+         return tz5 || (tz5=TZrules.US(18000,"E%sT"));
+      if (ux>=-273729600) // from 1961 Apr 30 2:00 
+         return tz4 || (tz4=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-599637600) // from 1951 
+         return tz3 || (tz3=TZrules.Marengo(21600,"C%sT"));
+      if (ux>=-2717648077) // from 1883 Nov 18 12:00 
+         return tz2 || (tz2=TZrules.US(21600,"C%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(20723,"LMT"));
+   }
+}
+
+class America_Indiana_Knox
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=688510800) // from 1991 Oct 27 2:00 
+         return tz4 || (tz4=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-195066000) // from 1963 Oct 27 2:00 
+         return tz2 || (tz2=TZrules.US(21600,"C%sT"));
+      if (ux>=-242280000) // from 1962 Apr 29 2:00 
+         return tz4 || (tz4=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-725868000) // from 1947 
+         return tz3 || (tz3=TZrules.Starke(21600,"C%sT"));
+      if (ux>=-2717648010) // from 1883 Nov 18 12:00 
+         return tz2 || (tz2=TZrules.US(21600,"C%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(20790,"LMT"));
+   }
+}
+constant America_Knox_IN=America_Indiana_Knox;
+constant US_Indiana_Starke=America_Indiana_Knox;
+
+class America_Indiana_Vevay
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=94676400) // from 1973 
+         return tz3 || (tz3=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-31518000) // from 1969 
+         return tz4 || (tz4=TZrules.US(18000,"E%sT"));
+      if (ux>=-495086400) // from 1954 Apr 25 2:00 
+         return tz3 || (tz3=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-2717648384) // from 1883 Nov 18 12:00 
+         return tz2 || (tz2=TZrules.US(21600,"C%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(20416,"LMT"));
+   }
+}
+
+class America_Louisville
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=152089200) // from 1974 Oct 27 2:00 
+         return tz5 || (tz5=TZrules.US(18000,"E%sT"));
+      if (ux>=126651600) // from 1974 Jan  6 2:00 
+         return tz6 || (tz6=Ruleset.Timezone(18000,"CDT"));
+      if (ux>=-63140400) // from 1968 
+         return tz5 || (tz5=TZrules.US(18000,"E%sT"));
+      if (ux>=-266468400) // from 1961 Jul 23 2:00 
+         return tz4 || (tz4=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-757404000) // from 1946 
+         return tz3 || (tz3=TZrules.Louisville(21600,"C%sT"));
+      if (ux>=-883634400) // from 1942 
+         return tz2 || (tz2=TZrules.US(21600,"C%sT"));
+      if (ux>=-1546322400) // from 1921 
+         return tz3 || (tz3=TZrules.Louisville(21600,"C%sT"));
+      if (ux>=-2717648218) // from 1883 Nov 18 12:00 
+         return tz2 || (tz2=TZrules.US(21600,"C%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(20582,"LMT"));
+   }
+}
+
+class America_Detroit
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=167814000) // from 1975 Apr 27 2:00 
+         return tz4 || (tz4=TZrules.US(18000,"E%sT"));
+      if (ux>=157748400) // from 1975 
+         return tz3 || (tz3=Ruleset.Timezone(18000,"EST"));
+      if (ux>=94676400) // from 1973 
+         return tz4 || (tz4=TZrules.US(18000,"E%sT"));
+      if (ux>=-757400400) // from 1946 
+         return tz5 || (tz5=TZrules.Detroit(18000,"E%sT"));
+      if (ux>=-883594800) // from 1942 
+         return tz4 || (tz4=TZrules.US(18000,"E%sT"));
+      if (ux>=-1724083200) // from 1915 May 15 2:00 
+         return tz3 || (tz3=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-2051202469) // from 1905 
+         return tz2 || (tz2=Ruleset.Timezone(21600,"CST"));
+      return tz1 || (tz1=Ruleset.Timezone(19931,"LMT"));
+   }
+}
+constant US_Michigan=America_Detroit;
+
+class America_Menominee
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=104914800) // from 1973 Apr 29 2:00 
+         return tz2 || (tz2=TZrules.US(21600,"C%sT"));
+      if (ux>=-21528000) // from 1969 Apr 27 2:00 
+         return tz4 || (tz4=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-757404000) // from 1946 
+         return tz3 || (tz3=TZrules.Menominee(21600,"C%sT"));
+      if (ux>=-2659759773) // from 1885 Sep 18 12:00 
+         return tz2 || (tz2=TZrules.US(21600,"C%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(21027,"LMT"));
+   }
+}
+
+class America_St_Johns
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1096947052) // from 1935 Mar 30 
+         return tz3 || (tz3=TZrules.StJohns(12600,"N%sT"));
+      if (ux>=-2713897748) // from 1884 
+         return tz2 || (tz2=TZrules.StJohns(12652,"N%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(12652,"LMT"));
+   }
+}
+constant Canada_Newfoundland=America_St_Johns;
+
+class America_Goose_Bay
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-119928600) // from 1966 Mar 15 2:00 
+         return tz6 || (tz6=TZrules.StJohns(14400,"A%sT"));
+      if (ux>=-1072989000) // from 1936 
+         return tz5 || (tz5=TZrules.StJohns(12600,"N%sT"));
+      if (ux>=-1096921748) // from 1935 Mar 30 
+         return tz4 || (tz4=Ruleset.Timezone(12600,"NST"));
+      if (ux>=-1609471852) // from 1919 
+         return tz3 || (tz3=Ruleset.Timezone(12652,"NST"));
+      if (ux>=-2713895900) // from 1884 
+         return tz2 || (tz2=TZrules.StJohns(12652,"NST"));
+      // Happy Valley-Goose Bay
+      return tz1 || (tz1=Ruleset.Timezone(14500,"LMT"));
+   }
+}
+
+class America_Halifax
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2131645536) // from 1902 Jun 15 
+         return tz2 || (tz2=TZrules.Halifax(14400,"A%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(15264,"LMT"));
+   }
+}
+constant Canada_Atlantic=America_Halifax;
+
+class America_Glace_Bay
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=63086400) // from 1972 
+         return tz3 || (tz3=TZrules.Halifax(14400,"A%sT"));
+      if (ux>=-504936000) // from 1954 
+         return tz4 || (tz4=Ruleset.Timezone(14400,"AST"));
+      if (ux>=-536472000) // from 1953 
+         return tz3 || (tz3=TZrules.Halifax(14400,"A%sT"));
+      if (ux>=-2131646412) // from 1902 Jun 15 
+         return tz2 || (tz2=TZrules.Canada(14400,"A%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(14388,"LMT"));
+   }
+}
+
+class America_Montreal
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2713892744) // from 1884 
+         return tz2 || (tz2=TZrules.Mont(18000,"E%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(17656,"LMT"));
+   }
+}
+constant Canada_Eastern=America_Montreal;
+
+class America_Thunder_Bay
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=126248400) // from 1974 
+         return tz2 || (tz2=TZrules.Canada(18000,"E%sT"));
+      if (ux>=94676400) // from 1973 
+         return tz4 || (tz4=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-18000) // from 1970 
+         return tz3 || (tz3=TZrules.Mont(18000,"E%sT"));
+      if (ux>=-2366733780) // from 1895 
+         return tz2 || (tz2=TZrules.Canada(18000,"E%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(21420,"LMT"));
+   }
+}
+
+class America_Nipigon
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2366734016) // from 1895 
+         return tz2 || (tz2=TZrules.Canada(18000,"E%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(21184,"LMT"));
+   }
+}
+
+class America_Rainy_River
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2366732524) // from 1895 
+         return tz2 || (tz2=TZrules.Canada(21600,"C%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(22676,"LMT"));
+   }
+}
+
+class America_Winnipeg
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2602258284) // from 1887 Jul 16 
+         return tz2 || (tz2=TZrules.Winn(21600,"C%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(23316,"LMT"));
+   }
+}
+constant Canada_Central=America_Winnipeg;
+
+class America_Regina
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-307782000) // from 1960 Apr lastSun 2:00 
+         return tz3 || (tz3=Ruleset.Timezone(21600,"CST"));
+      if (ux>=-2030202084) // from 1905 Sep 
+         return tz2 || (tz2=TZrules.Regina(25200,"M%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(25116,"LMT"));
+   }
+}
+constant Canada_East_Saskatchewan=America_Regina;
+constant Canada_Saskatchewan=America_Regina;
+
+class America_Swift_Current
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=70909200) // from 1972 Apr lastSun 2:00 
+         return tz5 || (tz5=Ruleset.Timezone(21600,"CST"));
+      if (ux>=-631177200) // from 1950 
+         return tz4 || (tz4=TZrules.Swift(25200,"M%sT"));
+      if (ux>=-749631600) // from 1946 Apr lastSun 2:00 
+         return tz3 || (tz3=TZrules.Regina(25200,"M%sT"));
+      if (ux>=-2030201320) // from 1905 Sep 
+         return tz2 || (tz2=TZrules.Canada(25200,"M%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(25880,"LMT"));
+   }
+}
+
+class America_Edmonton
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1998663968) // from 1906 Sep 
+         return tz2 || (tz2=TZrules.Edm(25200,"M%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(27232,"LMT"));
+   }
+}
+constant Canada_Mountain=America_Edmonton;
+
+class America_Vancouver
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2713880852) // from 1884 
+         return tz2 || (tz2=TZrules.Vanc(28800,"P%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(29548,"LMT"));
+   }
+}
+constant Canada_Pacific=America_Vancouver;
+
+class America_Dawson_Creek
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=83962800) // from 1972 Aug 30 2:00 
+         return tz4 || (tz4=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-725875200) // from 1947 
+         return tz3 || (tz3=TZrules.Vanc(28800,"P%sT"));
+      if (ux>=-2713881544) // from 1884 
+         return tz2 || (tz2=TZrules.Canada(28800,"P%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(28856,"LMT"));
+   }
+}
+
+class America_Pangnirtung
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=941320800) // from 1999 Oct 31 2:00 
+         return tz4 || (tz4=TZrules.Canada(21600,"C%sT"));
+      if (ux>=796680000) // from 1995 Apr Sun>=1 2:00 
+         return tz3 || (tz3=TZrules.Canada(18000,"E%sT"));
+      if (ux>=-2713894624) // from 1884 
+         return tz2 || (tz2=TZrules.NT_YK(14400,"A%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(15776,"LMT"));
+   }
+}
+
+class America_Iqaluit
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=941320800) // from 1999 Oct 31 2:00 
+         return tz3 || (tz3=TZrules.Canada(21600,"C%sT"));
+      if (ux>=-2713893968) // from 1884 
+         return tz2 || (tz2=TZrules.NT_YK(18000,"E%sT"));
+      // Frobisher Bay before 1987
+      return tz1 || (tz1=Ruleset.Timezone(16432,"LMT"));
+   }
+}
+
+class America_Rankin_Inlet
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2713888280) // from 1884 
+         return tz2 || (tz2=TZrules.NT_YK(21600,"C%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(22120,"LMT"));
+   }
+}
+
+class America_Cambridge_Bay
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=941313600) // from 1999 Oct 31 2:00 
+         return tz3 || (tz3=TZrules.Canada(21600,"C%sT"));
+      if (ux>=-2713885180) // from 1884 
+         return tz2 || (tz2=TZrules.NT_YK(25200,"M%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(25220,"LMT"));
+   }
+}
+
+class America_Yellowknife
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2713882956) // from 1884 
+         return tz2 || (tz2=TZrules.NT_YK(25200,"M%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(27444,"LMT"));
+   }
+}
+
+class America_Inuvik
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=291744000) // from 1979 Apr lastSun 2:00 
+         return tz3 || (tz3=TZrules.NT_YK(25200,"M%sT"));
+      if (ux>=-2713878360) // from 1884 
+         return tz2 || (tz2=TZrules.NT_YK(28800,"P%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(32040,"LMT"));
+   }
+}
+
+class America_Whitehorse
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-110617200) // from 1966 Jul 1 2:00 
+         return tz3 || (tz3=TZrules.NT_YK(28800,"P%sT"));
+      if (ux>=-2188997988) // from 1900 Aug 20 
+         return tz2 || (tz2=TZrules.NT_YK(32400,"Y%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(32412,"LMT"));
+   }
+}
+constant Canada_Yukon=America_Whitehorse;
+
+class America_Dawson
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=120582000) // from 1973 Oct 28 0:00 
+         return tz3 || (tz3=TZrules.NT_YK(28800,"P%sT"));
+      if (ux>=-2188996940) // from 1900 Aug 20 
+         return tz2 || (tz2=TZrules.NT_YK(32400,"Y%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(33460,"LMT"));
+   }
+}
+
+class America_Cancun
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=902008800) // from 1998 Aug  2  2:00 
+         return tz3 || (tz3=TZrules.Mexico(21600,"C%sT"));
+      if (ux>=875646000) // from 1997 Oct lastSun 2:00 
+         return tz4 || (tz4=TZrules.Mexico(18000,"E%sT"));
+      if (ux>=820476000) // from 1996 
+         return tz3 || (tz3=TZrules.Mexico(21600,"C%sT"));
+      if (ux>=-1514743200) // from 1922 Jan  1  0:12:56 
+         return tz2 || (tz2=Ruleset.Timezone(21600,"CST"));
+      return tz1 || (tz1=Ruleset.Timezone(20824,"LMT"));
+   }
+}
+
+class America_Mexico_City
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1191434400) // from 1932 Mar 30 23:00 
+         return tz4 || (tz4=TZrules.Mexico(21600,"C%sT"));
+      if (ux>=-1207159200) // from 1931 Oct 
+         return tz2 || (tz2=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-1220292000) // from 1931 May  1 23:00 
+         return tz3 || (tz3=Ruleset.Timezone(21600,"CST"));
+      if (ux>=-1234807200) // from 1930 Nov 15 
+         return tz2 || (tz2=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-1343066400) // from 1927 Jun 10 23:00 
+         return tz3 || (tz3=Ruleset.Timezone(21600,"CST"));
+      if (ux>=-1514739600) // from 1922 Jan  1  0:23:24 
+         return tz2 || (tz2=Ruleset.Timezone(25200,"MST"));
+      return tz1 || (tz1=Ruleset.Timezone(23796,"LMT"));
+   }
+}
+constant Mexico_General=America_Mexico_City;
+
+class America_Chihuahua
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=891410400) // from 1998 Apr Sun>=1 3:00 
+         return tz5 || (tz5=TZrules.Mexico(25200,"M%sT"));
+      if (ux>=883591200) // from 1998 
+         return tz3 || (tz3=Ruleset.Timezone(21600,"CST"));
+      if (ux>=820476000) // from 1996 
+         return tz4 || (tz4=TZrules.Mexico(21600,"C%sT"));
+      if (ux>=-1191434400) // from 1932 Mar 30 23:00 
+         return tz3 || (tz3=Ruleset.Timezone(21600,"CST"));
+      if (ux>=-1207159200) // from 1931 Oct 
+         return tz2 || (tz2=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-1220292000) // from 1931 May  1 23:00 
+         return tz3 || (tz3=Ruleset.Timezone(21600,"CST"));
+      if (ux>=-1234807200) // from 1930 Nov 15 
+         return tz2 || (tz2=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-1343066400) // from 1927 Jun 10 23:00 
+         return tz3 || (tz3=Ruleset.Timezone(21600,"CST"));
+      if (ux>=-1514739600) // from 1921 Dec 31 23:55:40 
+         return tz2 || (tz2=Ruleset.Timezone(25200,"MST"));
+      return tz1 || (tz1=Ruleset.Timezone(25460,"LMT"));
+   }
+}
+
+class America_Hermosillo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=915123600) // from 1999 
+         return tz2 || (tz2=Ruleset.Timezone(25200,"MST"));
+      if (ux>=28800) // from 1970 
+         return tz5 || (tz5=TZrules.Mexico(25200,"M%sT"));
+      if (ux>=-661539600) // from 1949 Jan 14 
+         return tz4 || (tz4=Ruleset.Timezone(28800,"PST"));
+      if (ux>=-875815200) // from 1942 Apr 
+         return tz2 || (tz2=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-1191434400) // from 1932 Mar 30 23:00 
+         return tz3 || (tz3=Ruleset.Timezone(21600,"CST"));
+      if (ux>=-1207159200) // from 1931 Oct 
+         return tz2 || (tz2=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-1220292000) // from 1931 May  1 23:00 
+         return tz3 || (tz3=Ruleset.Timezone(21600,"CST"));
+      if (ux>=-1234807200) // from 1930 Nov 15 
+         return tz2 || (tz2=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-1343066400) // from 1927 Jun 10 23:00 
+         return tz3 || (tz3=Ruleset.Timezone(21600,"CST"));
+      if (ux>=-1514739600) // from 1921 Dec 31 23:36:08 
+         return tz2 || (tz2=Ruleset.Timezone(25200,"MST"));
+      return tz1 || (tz1=Ruleset.Timezone(26632,"LMT"));
+   }
+}
+
+class America_Mazatlan
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=28800) // from 1970 
+         return tz5 || (tz5=TZrules.Mexico(25200,"M%sT"));
+      if (ux>=-661539600) // from 1949 Jan 14 
+         return tz4 || (tz4=Ruleset.Timezone(28800,"PST"));
+      if (ux>=-875815200) // from 1942 Apr 
+         return tz2 || (tz2=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-1191434400) // from 1932 Mar 30 23:00 
+         return tz3 || (tz3=Ruleset.Timezone(21600,"CST"));
+      if (ux>=-1207159200) // from 1931 Oct 
+         return tz2 || (tz2=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-1220292000) // from 1931 May  1 23:00 
+         return tz3 || (tz3=Ruleset.Timezone(21600,"CST"));
+      if (ux>=-1234807200) // from 1930 Nov 15 
+         return tz2 || (tz2=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-1343066400) // from 1927 Jun 10 23:00 
+         return tz3 || (tz3=Ruleset.Timezone(21600,"CST"));
+      if (ux>=-1514739600) // from 1921 Dec 31 23:54:20 
+         return tz2 || (tz2=Ruleset.Timezone(25200,"MST"));
+      return tz1 || (tz1=Ruleset.Timezone(25540,"LMT"));
+   }
+}
+constant Mexico_BajaSur=America_Mazatlan;
+
+class America_Tijuana
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=820425600) // from 1996 
+         return tz6 || (tz6=TZrules.Mexico(28800,"P%sT"));
+      if (ux>=189273600) // from 1976 
+         return tz5 || (tz5=TZrules.US(28800,"P%sT"));
+      if (ux>=-661539600) // from 1949 Jan 14 
+         return tz4 || (tz4=TZrules.BajaN(28800,"P%sT"));
+      if (ux>=-875808000) // from 1942 Apr 
+         return tz3 || (tz3=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-1234717200) // from 1930 Nov 16 
+         return tz2 || (tz2=Ruleset.Timezone(28800,"PST"));
+      if (ux>=-1343062800) // from 1927 Jun 10 23:00 
+         return tz3 || (tz3=Ruleset.Timezone(25200,"MST"));
+      if (ux>=-1514736000) // from 1922 Jan  1  0:11:56 
+         return tz2 || (tz2=Ruleset.Timezone(28800,"PST"));
+      return tz1 || (tz1=Ruleset.Timezone(28084,"LMT"));
+   }
+}
+constant America_Ensenada=America_Tijuana;
+constant Mexico_BajaNorte=America_Tijuana;
+
+class America_Anguilla
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1825098464) // from 1912 Mar 2 
+         return tz2 || (tz2=Ruleset.Timezone(14400,"AST"));
+      return tz1 || (tz1=Ruleset.Timezone(15136,"LMT"));
+   }
+}
+
+class America_Antigua
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-599598000) // from 1951 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"AST"));
+      if (ux>=-1825098768) // from 1912 Mar 2 
+         return tz2 || (tz2=Ruleset.Timezone(18000,"EST"));
+      return tz1 || (tz1=Ruleset.Timezone(14832,"LMT"));
+   }
+}
+
+class America_Nassau
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1825095036) // from 1912 Mar 2 
+         return tz2 || (tz2=TZrules.Bahamas(18000,"E%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(18564,"LMT"));
+   }
+}
+
+class America_Barbados
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1199217692) // from 1932 
+         return tz3 || (tz3=TZrules.Barb(14400,"A%sT"));
+      if (ux>=-1451678492) // from 1924 Bridgetown Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(14308,"BMT"));
+      // Bridgetown
+      return tz1 || (tz1=Ruleset.Timezone(14308,"LMT"));
+   }
+}
+
+class America_Belize
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1822500432) // from 1912 Apr 
+         return tz2 || (tz2=TZrules.Belize(21600,"C%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(21168,"LMT"));
+   }
+}
+
+class Atlantic_Bermuda
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=136360800) // from 1974 Apr 28 2:00 
+         return tz3 || (tz3=TZrules.Bahamas(14400,"A%sT"));
+      if (ux>=-1262281256) // from 1930 Jan  1 2:00 
+         return tz2 || (tz2=Ruleset.Timezone(14400,"AST"));
+      // Hamilton
+      return tz1 || (tz1=Ruleset.Timezone(15544,"LMT"));
+   }
+}
+
+class America_Cayman
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1827687168) // from 1912 Feb 
+         return tz3 || (tz3=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-2524502068) // from 1890 Kingston Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(18432,"KMT"));
+      // Georgetown
+      return tz1 || (tz1=Ruleset.Timezone(19532,"LMT"));
+   }
+}
+
+class America_Costa_Rica
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1545071020) // from 1921 Jan 15 
+         return tz3 || (tz3=TZrules.CR(21600,"C%sT"));
+      if (ux>=-2524501420) // from 1890 San Jose Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(20180,"SJMT"));
+      // San Jose
+      return tz1 || (tz1=Ruleset.Timezone(20180,"LMT"));
+   }
+}
+
+class America_Havana
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1402813824) // from 1925 Jul 19 12:00 
+         return tz3 || (tz3=TZrules.Cuba(18000,"C%sT"));
+      if (ux>=-2524501832) // from 1890 Havana MT
+         return tz2 || (tz2=Ruleset.Timezone(19776,"HMT"));
+      return tz1 || (tz1=Ruleset.Timezone(19768,"LMT"));
+   }
+}
+constant Cuba=America_Havana;
+
+class America_Dominica
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1846266804) // from 1911 Jul 1 0:01 
+         return tz2 || (tz2=Ruleset.Timezone(14400,"AST"));
+      // Roseau
+      return tz1 || (tz1=Ruleset.Timezone(14736,"LMT"));
+   }
+}
+
+class America_Santo_Domingo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=152046000) // from 1974 Oct 27 
+         return tz4 || (tz4=Ruleset.Timezone(14400,"AST"));
+      if (ux>=-1159773600) // from 1933 Apr  1 12:00 
+         return tz3 || (tz3=TZrules.DR(18000,"E%sT"));
+      if (ux>=-2524504824) // from 1890 S. Dom. MT
+         return tz2 || (tz2=Ruleset.Timezone(16800,"SDMT"));
+      return tz1 || (tz1=Ruleset.Timezone(16776,"LMT"));
+   }
+}
+
+class America_El_Salvador
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1546279392) // from 1921 
+         return tz2 || (tz2=TZrules.Salv(21600,"C%sT"));
+      // San Salvador
+      return tz1 || (tz1=Ruleset.Timezone(21408,"LMT"));
+   }
+}
+
+class America_Grenada
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1846266780) // from 1911 Jul 
+         return tz2 || (tz2=Ruleset.Timezone(14400,"AST"));
+      // St George's
+      return tz1 || (tz1=Ruleset.Timezone(14820,"LMT"));
+   }
+}
+
+class America_Guadeloupe
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1848254032) // from 1911 Jun 8 
+         return tz2 || (tz2=Ruleset.Timezone(14400,"AST"));
+      // Pointe a Pitre
+      return tz1 || (tz1=Ruleset.Timezone(14768,"LMT"));
+   }
+}
+
+class America_Guatemala
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1617040676) // from 1918 Oct 5 
+         return tz2 || (tz2=TZrules.Guat(21600,"C%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(21724,"LMT"));
+   }
+}
+
+class America_Port_au_Prince
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1670483460) // from 1917 Jan 24 12:00 
+         return tz3 || (tz3=TZrules.Haiti(18000,"E%sT"));
+      if (ux>=-2524504240) // from 1890 P-a-P MT
+         return tz2 || (tz2=Ruleset.Timezone(17340,"PPMT"));
+      return tz1 || (tz1=Ruleset.Timezone(17360,"LMT"));
+   }
+}
+
+class America_Tegucigalpa
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1538503868) // from 1921 Apr 
+         return tz2 || (tz2=TZrules.Salv(21600,"C%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(20932,"LMT"));
+   }
+}
+
+class America_Jamaica
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=441745200) // from 1984 
+         return tz3 || (tz3=Ruleset.Timezone(18000,"EST"));
+      if (ux>=136364400) // from 1974 Apr 28 2:00 
+         return tz4 || (tz4=TZrules.US(18000,"E%sT"));
+      if (ux>=-1827687168) // from 1912 Feb 
+         return tz3 || (tz3=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-2524503168) // from 1890 Kingston Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(18432,"KMT"));
+      // Kingston
+      return tz1 || (tz1=Ruleset.Timezone(18432,"LMT"));
+   }
+}
+constant Jamaica=America_Jamaica;
+
+class America_Martinique
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=338958000) // from 1980 Sep 28 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"AST"));
+      if (ux>=323841600) // from 1980 Apr  6 
+         return tz4 || (tz4=Ruleset.Timezone(10800,"ADT"));
+      if (ux>=-1851537360) // from 1911 May 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"AST"));
+      if (ux>=-2524506940) // from 1890 Fort-de-France MT
+         return tz2 || (tz2=Ruleset.Timezone(14640,"FFMT"));
+      // Fort-de-France
+      return tz1 || (tz1=Ruleset.Timezone(14660,"LMT"));
+   }
+}
+
+class America_Montserrat
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1846266608) // from 1911 Jul 1 0:01 
+         return tz2 || (tz2=Ruleset.Timezone(14400,"AST"));
+      // Olveston
+      return tz1 || (tz1=Ruleset.Timezone(14932,"LMT"));
+   }
+}
+
+class America_Managua
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=912488400) // from 1998 Dec 
+         return tz3 || (tz3=Ruleset.Timezone(21600,"CST"));
+      if (ux>=725839200) // from 1993 Jan 1 4:00 
+         return tz4 || (tz4=Ruleset.Timezone(18000,"EST"));
+      if (ux>=161758800) // from 1975 Feb 16 
+         return tz5 || (tz5=TZrules.Nic(21600,"C%sT"));
+      if (ux>=105084000) // from 1973 May 
+         return tz4 || (tz4=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-1121105700) // from 1934 Jun 23 
+         return tz3 || (tz3=Ruleset.Timezone(21600,"CST"));
+      if (ux>=-2524500892) // from 1890 Managua Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(20700,"MMT"));
+      return tz1 || (tz1=Ruleset.Timezone(20708,"LMT"));
+   }
+}
+
+class America_Panama
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1946918400) // from 1908 Apr 22 
+         return tz3 || (tz3=Ruleset.Timezone(18000,"EST"));
+      if (ux>=-2524502512) // from 1890 Panama Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(19200,"PMT"));
+      return tz1 || (tz1=Ruleset.Timezone(19088,"LMT"));
+   }
+}
+
+class America_Puerto_Rico
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-765399600) // from 1945 Sep 30  2:00 
+         return tz2 || (tz2=Ruleset.Timezone(14400,"AST"));
+      if (ux>=-873057600) // from 1942 May  3 
+         return tz3 || (tz3=Ruleset.Timezone(10800,"AWT"));
+      if (ux>=-2233035335) // from 1899 Mar 28 12:00 
+         return tz2 || (tz2=Ruleset.Timezone(14400,"AST"));
+      // San Juan
+      return tz1 || (tz1=Ruleset.Timezone(15865,"LMT"));
+   }
+}
+
+class America_St_Kitts
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1825098548) // from 1912 Mar 2 
+         return tz2 || (tz2=Ruleset.Timezone(14400,"AST"));
+      // Basseterre
+      return tz1 || (tz1=Ruleset.Timezone(15052,"LMT"));
+   }
+}
+
+class America_St_Lucia
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1830369360) // from 1912 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"AST"));
+      if (ux>=-2524506960) // from 1890 Castries Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(14640,"CMT"));
+      // Castries
+      return tz1 || (tz1=Ruleset.Timezone(14640,"LMT"));
+   }
+}
+
+class America_Miquelon
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=326001600) // from 1980 May Pierre & Miquelon Time
+         return tz3 || (tz3=TZrules.Mont(10800,"PM%sT"));
+      if (ux>=-1850328920) // from 1911 May 15 
+         return tz2 || (tz2=Ruleset.Timezone(14400,"AST"));
+      // St Pierre
+      return tz1 || (tz1=Ruleset.Timezone(13480,"LMT"));
+   }
+}
+
+class America_St_Vincent
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1830369304) // from 1912 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"AST"));
+      if (ux>=-2524506904) // from 1890 Kingstown Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(14696,"KMT"));
+      // Kingstown
+      return tz1 || (tz1=Ruleset.Timezone(14696,"LMT"));
+   }
+}
+
+class America_Grand_Turk
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1827687168) // from 1912 Feb 
+         return tz3 || (tz3=TZrules.TC(18000,"E%sT"));
+      if (ux>=-2524504528) // from 1890 Kingston Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(18432,"KMT"));
+      return tz1 || (tz1=Ruleset.Timezone(17072,"LMT"));
+   }
+}
+
+class America_Tortola
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1846266092) // from 1911 Jul 
+         return tz2 || (tz2=Ruleset.Timezone(14400,"AST"));
+      // Road Town
+      return tz1 || (tz1=Ruleset.Timezone(15508,"LMT"));
+   }
+}
+
+class America_St_Thomas
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1846266016) // from 1911 Jul 
+         return tz2 || (tz2=Ruleset.Timezone(14400,"AST"));
+      // Charlotte Amalie
+      return tz1 || (tz1=Ruleset.Timezone(15584,"LMT"));
+   }
+}
+constant America_Virgin=America_St_Thomas;
+
+class America_Buenos_Aires
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-7617600) // from 1969 Oct  5 
+         return tz5 || (tz5=TZrules.Arg(10800,"AR%sT"));
+      if (ux>=-1233432000) // from 1930 Dec 
+         return tz4 || (tz4=TZrules.Arg(14400,"AR%sT"));
+      if (ux>=-1567453396) // from 1920 May 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"ART"));
+      if (ux>=-2372011572) // from 1894 Nov Cordoba Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(15404,"CMT"));
+      return tz1 || (tz1=Ruleset.Timezone(14028,"LMT"));
+   }
+}
+
+class America_Rosario
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=678315600) // from 1991 Jul 
+         return tz6 || (tz6=Ruleset.Timezone(10800,"ART"));
+      if (ux>=-7617600) // from 1969 Oct  5 
+         return tz5 || (tz5=TZrules.Arg(10800,"AR%sT"));
+      if (ux>=-1233432000) // from 1930 Dec 
+         return tz4 || (tz4=TZrules.Arg(14400,"AR%sT"));
+      if (ux>=-1567453396) // from 1920 May 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"ART"));
+      if (ux>=-2372011040) // from 1894 Nov 
+         return tz2 || (tz2=Ruleset.Timezone(15404,"CMT"));
+      return tz1 || (tz1=Ruleset.Timezone(14560,"LMT"));
+   }
+}
+
+class America_Cordoba
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=646779600) // from 1990 Jul 
+         return tz6 || (tz6=Ruleset.Timezone(10800,"ART"));
+      if (ux>=-7617600) // from 1969 Oct  5 
+         return tz5 || (tz5=TZrules.Arg(10800,"AR%sT"));
+      if (ux>=-1233432000) // from 1930 Dec 
+         return tz4 || (tz4=TZrules.Arg(14400,"AR%sT"));
+      if (ux>=-1567453396) // from 1920 May 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"ART"));
+      if (ux>=-2372010196) // from 1894 Nov 
+         return tz2 || (tz2=Ruleset.Timezone(15404,"CMT"));
+      return tz1 || (tz1=Ruleset.Timezone(15404,"LMT"));
+   }
+}
+
+class America_Jujuy
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7,tz8;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=719380800) // from 1992 Oct 18 
+         return tz8 || (tz8=Ruleset.Timezone(10800,"ART"));
+      if (ux>=700628400) // from 1992 Mar 15 
+         return tz6 || (tz6=Ruleset.Timezone(14400,"WART"));
+      if (ux>=686721600) // from 1991 Oct  6 
+         return tz7 || (tz7=Ruleset.Timezone(10800,"WARST"));
+      if (ux>=667947600) // from 1991 Mar  3 
+         return tz6 || (tz6=Ruleset.Timezone(14400,"WART"));
+      if (ux>=-7617600) // from 1969 Oct  5 
+         return tz5 || (tz5=TZrules.Arg(10800,"AR%sT"));
+      if (ux>=-1233432000) // from 1930 Dec 
+         return tz4 || (tz4=TZrules.Arg(14400,"AR%sT"));
+      if (ux>=-1567453396) // from 1920 May 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"ART"));
+      if (ux>=-2372009928) // from 1894 Nov 
+         return tz2 || (tz2=Ruleset.Timezone(15404,"CMT"));
+      return tz1 || (tz1=Ruleset.Timezone(15672,"LMT"));
+   }
+}
+
+class America_Catamarca
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=709938000) // from 1992 Jul 
+         return tz6 || (tz6=Ruleset.Timezone(10800,"ART"));
+      if (ux>=678337200) // from 1991 Jul 
+         return tz5 || (tz5=TZrules.Arg(10800,"AR%sT"));
+      if (ux>=646779600) // from 1990 Jul 
+         return tz6 || (tz6=Ruleset.Timezone(10800,"ART"));
+      if (ux>=-7617600) // from 1969 Oct  5 
+         return tz5 || (tz5=TZrules.Arg(10800,"AR%sT"));
+      if (ux>=-1233432000) // from 1930 Dec 
+         return tz4 || (tz4=TZrules.Arg(14400,"AR%sT"));
+      if (ux>=-1567453396) // from 1920 May 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"ART"));
+      if (ux>=-2372009812) // from 1894 Nov 
+         return tz2 || (tz2=Ruleset.Timezone(15404,"CMT"));
+      return tz1 || (tz1=Ruleset.Timezone(15788,"LMT"));
+   }
+}
+
+class America_Mendoza
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6,tz7,tz8;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=719380800) // from 1992 Oct 18 
+         return tz8 || (tz8=Ruleset.Timezone(10800,"ART"));
+      if (ux>=699418800) // from 1992 Mar  1 
+         return tz6 || (tz6=Ruleset.Timezone(14400,"WART"));
+      if (ux>=687499200) // from 1991 Oct 15 
+         return tz7 || (tz7=Ruleset.Timezone(10800,"WARST"));
+      if (ux>=667947600) // from 1991 Mar  3 
+         return tz6 || (tz6=Ruleset.Timezone(14400,"WART"));
+      if (ux>=-7617600) // from 1969 Oct  5 
+         return tz5 || (tz5=TZrules.Arg(10800,"AR%sT"));
+      if (ux>=-1233432000) // from 1930 Dec 
+         return tz4 || (tz4=TZrules.Arg(14400,"AR%sT"));
+      if (ux>=-1567453396) // from 1920 May 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"ART"));
+      if (ux>=-2372009084) // from 1894 Nov 
+         return tz2 || (tz2=Ruleset.Timezone(15404,"CMT"));
+      return tz1 || (tz1=Ruleset.Timezone(16516,"LMT"));
+   }
+}
+
+class America_Aruba
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-157750200) // from 1965 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"AST"));
+      if (ux>=-1826738376) // from 1912 Feb 12 Netherlands Antilles Time
+         return tz2 || (tz2=Ruleset.Timezone(16200,"ANT"));
+      // Oranjestad
+      return tz1 || (tz1=Ruleset.Timezone(16824,"LMT"));
+   }
+}
+
+class America_La_Paz
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1192307244) // from 1932 Mar 21 Bolivia Time
+         return tz4 || (tz4=Ruleset.Timezone(14400,"BOT"));
+      if (ux>=-1205954844) // from 1931 Oct 15 Bolivia ST
+         return tz3 || (tz3=Ruleset.Timezone(12756,"BOST"));
+      if (ux>=-2524505244) // from 1890 La Paz Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(16356,"LPMT"));
+      return tz1 || (tz1=Ruleset.Timezone(16356,"LMT"));
+   }
+}
+
+class America_Noronha
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=653522400) // from 1990 Sep 17 
+         return tz3 || (tz3=Ruleset.Timezone(7200,"FNT"));
+      if (ux>=-1767217820) // from 1914 
+         return tz2 || (tz2=TZrules.Brazil(7200,"FN%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(7780,"LMT"));
+   }
+}
+constant Brazil_DeNoronha=America_Noronha;
+
+class America_Belem
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=590014800) // from 1988 Sep 12 
+         return tz3 || (tz3=Ruleset.Timezone(10800,"BRT"));
+      if (ux>=-1767213964) // from 1914 
+         return tz2 || (tz2=TZrules.Brazil(10800,"BR%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(11636,"LMT"));
+   }
+}
+
+class America_Fortaleza
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=938660400) // from 1999 Sep 30 
+         return tz2 || (tz2=TZrules.Brazil(10800,"BR%sT"));
+      if (ux>=653518800) // from 1990 Sep 17 
+         return tz3 || (tz3=Ruleset.Timezone(10800,"BRT"));
+      if (ux>=-1767216360) // from 1914 
+         return tz2 || (tz2=TZrules.Brazil(10800,"BR%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(9240,"LMT"));
+   }
+}
+
+class America_Araguaina
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=811047600) // from 1995 Sep 14 
+         return tz2 || (tz2=TZrules.Brazil(10800,"BR%sT"));
+      if (ux>=653518800) // from 1990 Sep 17 
+         return tz3 || (tz3=Ruleset.Timezone(10800,"BRT"));
+      if (ux>=-1767214032) // from 1914 
+         return tz2 || (tz2=TZrules.Brazil(10800,"BR%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(11568,"LMT"));
+   }
+}
+
+class America_Maceio
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=938660400) // from 1999 Sep 30 
+         return tz2 || (tz2=TZrules.Brazil(10800,"BR%sT"));
+      if (ux>=841784400) // from 1996 Sep  4 
+         return tz3 || (tz3=Ruleset.Timezone(10800,"BRT"));
+      if (ux>=813553200) // from 1995 Oct 13 
+         return tz2 || (tz2=TZrules.Brazil(10800,"BR%sT"));
+      if (ux>=653518800) // from 1990 Sep 17 
+         return tz3 || (tz3=Ruleset.Timezone(10800,"BRT"));
+      if (ux>=-1767217028) // from 1914 
+         return tz2 || (tz2=TZrules.Brazil(10800,"BR%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(8572,"LMT"));
+   }
+}
+
+class America_Sao_Paulo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-189381600) // from 1964 
+         return tz2 || (tz2=TZrules.Brazil(10800,"BR%sT"));
+      if (ux>=-195447600) // from 1963 Oct 23 00:00 
+         return tz3 || (tz3=Ruleset.Timezone(7200,"BRST"));
+      if (ux>=-1767214412) // from 1914 
+         return tz2 || (tz2=TZrules.Brazil(10800,"BR%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(11188,"LMT"));
+   }
+}
+constant Brazil_East=America_Sao_Paulo;
+
+class America_Cuiaba
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1767212140) // from 1914 
+         return tz2 || (tz2=TZrules.Brazil(14400,"AM%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(13460,"LMT"));
+   }
+}
+
+class America_Porto_Velho
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=590011200) // from 1988 Sep 12 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"AMT"));
+      if (ux>=-1767210264) // from 1914 
+         return tz2 || (tz2=TZrules.Brazil(14400,"AM%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(15336,"LMT"));
+   }
+}
+
+class America_Boa_Vista
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=938664000) // from 1999 Sep 30 
+         return tz2 || (tz2=TZrules.Brazil(14400,"AM%sT"));
+      if (ux>=590011200) // from 1988 Sep 12 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"AMT"));
+      if (ux>=-1767211040) // from 1914 
+         return tz2 || (tz2=TZrules.Brazil(14400,"AM%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(14560,"LMT"));
+   }
+}
+
+class America_Manaus
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=780177600) // from 1994 Sep 22 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"AMT"));
+      if (ux>=749188800) // from 1993 Sep 28 
+         return tz2 || (tz2=TZrules.Brazil(14400,"AM%sT"));
+      if (ux>=590011200) // from 1988 Sep 12 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"AMT"));
+      if (ux>=-1767211196) // from 1914 
+         return tz2 || (tz2=TZrules.Brazil(14400,"AM%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(14404,"LMT"));
+   }
+}
+constant Brazil_West=America_Manaus;
+
+class America_Porto_Acre
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=590007600) // from 1988 Sep 12 
+         return tz3 || (tz3=Ruleset.Timezone(18000,"ACT"));
+      if (ux>=-1767209328) // from 1914 
+         return tz2 || (tz2=TZrules.Brazil(18000,"AC%sT"));
+      return tz1 || (tz1=Ruleset.Timezone(16272,"LMT"));
+   }
+}
+constant Brazil_Acre=America_Porto_Acre;
+
+class America_Santiago
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1178168400) // from 1932 Sep 
+         return tz4 || (tz4=TZrules.Chile(14400,"CL%sT"));
+      if (ux>=-1893439040) // from 1910 Chile Time
+         return tz3 || (tz3=TZrules.Chile(18000,"CL%sT"));
+      if (ux>=-2524504640) // from 1890 Santiago Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(16960,"SMT"));
+      return tz1 || (tz1=Ruleset.Timezone(16960,"LMT"));
+   }
+}
+constant Chile_Continental=America_Santiago;
+
+class Pacific_Easter
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=384886800) // from 1982 Mar 14 
+         return tz4 || (tz4=TZrules.Chile(21600,"EAS%sT"));
+      if (ux>=-1178124152) // from 1932 Sep Easter I Time
+         return tz3 || (tz3=TZrules.Chile(25200,"EAS%sT"));
+      if (ux>=-2524495352) // from 1890 Mataveri Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(26248,"MMT"));
+      // Mataveri
+      return tz1 || (tz1=Ruleset.Timezone(26248,"LMT"));
+   }
+}
+constant Chile_EasterIsland=Pacific_Easter;
+
+class America_Bogota
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1739041420) // from 1914 Nov 23 Colombia Time
+         return tz3 || (tz3=TZrules.CO(18000,"CO%sT"));
+      if (ux>=-2707671820) // from 1884 Mar 13 Bogota Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(17780,"BMT"));
+      return tz1 || (tz1=Ruleset.Timezone(17780,"LMT"));
+   }
+}
+
+class America_Curacao
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-157750200) // from 1965 
+         return tz3 || (tz3=Ruleset.Timezone(14400,"AST"));
+      if (ux>=-1826738656) // from 1912 Feb 12 Netherlands Antilles Time
+         return tz2 || (tz2=Ruleset.Timezone(16200,"ANT"));
+      // Willemstad
+      return tz1 || (tz1=Ruleset.Timezone(16544,"LMT"));
+   }
+}
+
+class America_Guayaquil
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1230749160) // from 1931 Ecuador Time
+         return tz3 || (tz3=Ruleset.Timezone(18000,"ECT"));
+      if (ux>=-2524502440) // from 1890 Quito Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(18840,"QMT"));
+      return tz1 || (tz1=Ruleset.Timezone(19160,"LMT"));
+   }
+}
+
+class Pacific_Galapagos
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=504939600) // from 1986 Galapagos Time
+         return tz3 || (tz3=Ruleset.Timezone(21600,"GALT"));
+      if (ux>=-1230746496) // from 1931 
+         return tz2 || (tz2=Ruleset.Timezone(18000,"ECT"));
+      // Puerto Baquerizo Moreno
+      return tz1 || (tz1=Ruleset.Timezone(21504,"LMT"));
+   }
+}
+
+class Atlantic_Stanley
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=495579600) // from 1985 Sep 15 
+         return tz3 || (tz3=TZrules.Falk(14400,"FK%sT"));
+      if (ux>=420580800) // from 1983 May 
+         return tz4 || (tz4=TZrules.Falk(10800,"FK%sT"));
+      if (ux>=-1824235716) // from 1912 Mar 12 Falkland Is Time
+         return tz3 || (tz3=TZrules.Falk(14400,"FK%sT"));
+      if (ux>=-2524507716) // from 1890 Stanley Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(13884,"SMT"));
+      return tz1 || (tz1=Ruleset.Timezone(13884,"LMT"));
+   }
+}
+
+class America_Cayenne
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-71092800) // from 1967 Oct 
+         return tz3 || (tz3=Ruleset.Timezone(10800,"GFT"));
+      if (ux>=-1846269040) // from 1911 Jul French Guiana Time
+         return tz2 || (tz2=Ruleset.Timezone(14400,"GFT"));
+      return tz1 || (tz1=Ruleset.Timezone(12560,"LMT"));
+   }
+}
+
+class America_Guyana
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=662698800) // from 1991 
+         return tz5 || (tz5=Ruleset.Timezone(14400,"GYT"));
+      if (ux>=176010300) // from 1975 Jul 31 
+         return tz4 || (tz4=Ruleset.Timezone(10800,"GYT"));
+      if (ux>=-113688900) // from 1966 May 26 Guyana Time
+         return tz3 || (tz3=Ruleset.Timezone(13500,"GYT"));
+      if (ux>=-1730578040) // from 1915 Mar Br Guiana Time
+         return tz2 || (tz2=Ruleset.Timezone(13500,"GBGT"));
+      // Georgetown
+      return tz1 || (tz1=Ruleset.Timezone(13960,"LMT"));
+   }
+}
+
+class America_Asuncion
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=134017200) // from 1974 Apr 
+         return tz5 || (tz5=TZrules.Para(14400,"PY%sT"));
+      if (ux>=86760000) // from 1972 Oct 
+         return tz4 || (tz4=Ruleset.Timezone(10800,"PYT"));
+      if (ux>=-1206389360) // from 1931 Oct 10 Paraguay Time
+         return tz3 || (tz3=Ruleset.Timezone(14400,"PYT"));
+      if (ux>=-2524507760) // from 1890 Asuncion Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(13840,"AMT"));
+      return tz1 || (tz1=Ruleset.Timezone(13840,"LMT"));
+   }
+}
+
+class America_Lima
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1938538260) // from 1908 Jul 28 Peru Time
+         return tz3 || (tz3=TZrules.Peru(18000,"PE%sT"));
+      if (ux>=-2524503108) // from 1890 Lima Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(18540,"LMT"));
+      return tz1 || (tz1=Ruleset.Timezone(18492,"LMT"));
+   }
+}
+
+class Atlantic_South_Georgia
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-2524512832) // from 1890 South Georgia Time
+         return tz2 || (tz2=Ruleset.Timezone(7200,"GST"));
+      // Grytviken
+      return tz1 || (tz1=Ruleset.Timezone(8768,"LMT"));
+   }
+}
+
+class America_Paramaribo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4,tz5,tz6;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=465449400) // from 1984 Oct 
+         return tz6 || (tz6=Ruleset.Timezone(10800,"SRT"));
+      if (ux>=185686200) // from 1975 Nov 20 Suriname Time
+         return tz5 || (tz5=Ruleset.Timezone(12600,"SRT"));
+      if (ux>=-765317964) // from 1945 Oct Dutch Guiana Time
+         return tz4 || (tz4=Ruleset.Timezone(12600,"NEGT"));
+      if (ux>=-1104524348) // from 1935 The capital moved?
+         return tz3 || (tz3=Ruleset.Timezone(13236,"PMT"));
+      if (ux>=-1861906760) // from 1911 Paramaribo Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(13252,"PMT"));
+      return tz1 || (tz1=Ruleset.Timezone(13240,"LMT"));
+   }
+}
+
+class America_Port_of_Spain
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-1825098836) // from 1912 Mar 2 
+         return tz2 || (tz2=Ruleset.Timezone(14400,"AST"));
+      return tz1 || (tz1=Ruleset.Timezone(14764,"LMT"));
+   }
+}
+
+class America_Montevideo
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-853641000) // from 1942 Dec 14 
+         return tz4 || (tz4=TZrules.Uruguay(10800,"UY%sT"));
+      if (ux>=-1567455316) // from 1920 May  1 Uruguay Time
+         return tz3 || (tz3=TZrules.Uruguay(12600,"UY%sT"));
+      if (ux>=-2256668116) // from 1898 Jun 28 Montevideo MT
+         return tz2 || (tz2=Ruleset.Timezone(13484,"MMT"));
+      return tz1 || (tz1=Ruleset.Timezone(13484,"LMT"));
+   }
+}
+
+class America_Caracas
+{
+   inherit TZHistory;
+   Ruleset.Timezone tz1,tz2,tz3,tz4;
+   Ruleset.Timezone whatrule(int ux)
+   {
+      if (ux>=-157750200) // from 1965 
+         return tz4 || (tz4=Ruleset.Timezone(14400,"VET"));
+      if (ux>=-1826739136) // from 1912 Feb 12 Venezuela Time
+         return tz3 || (tz3=Ruleset.Timezone(16200,"VET"));
+      if (ux>=-2524505536) // from 1890 Caracas Mean Time
+         return tz2 || (tz2=Ruleset.Timezone(16064,"CMT"));
+      return tz1 || (tz1=Ruleset.Timezone(16064,"LMT"));
+   }
+}
+
+
+// ----------------------------------------------------------------------
diff --git a/lib/modules/Calendar.pmod/Time.pmod b/lib/modules/Calendar.pmod/Time.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..b19555feb10057fb4b17bea8eff1107ef1cd164f
--- /dev/null
+++ b/lib/modules/Calendar.pmod/Time.pmod
@@ -0,0 +1,1833 @@
+//!
+//! module Calendar
+//! submodule Time
+//!
+//! 	Base for time of day in calendars, ie 
+//! 	calendars with hours, minutes, seconds
+//! 	
+//! 	This module can't be used by itself, but
+//! 	is inherited by other modules (<ref>ISO</ref> by <ref>YMD</ref>, 
+//! 	for instance).
+
+//  #pragma strict_types
+
+//- these classes majorly works on seconds
+//- an hour is 3600 seconds, a minute is 60 seconds
+
+import ".";
+inherit TimeRanges:TimeRanges;
+
+constant inano=1000000000;
+
+// from inherited module
+
+function(mixed...:TimeRange) Day;
+
+// sanity check
+
+static private int __sanity_check=lambda()
+{
+   if (5000000000!=5*inano)
+      error("Calendar.Time needs bignums (Gmp.mpz)\n");
+   return 1;
+}();
+
+Ruleset.Timezone Timezone_UTC=Ruleset.Timezone(0,"UTC"); // needed for dumping
+
+//------------------------------------------------------------------------
+//! class TimeOfDay
+//------------------------------------------------------------------------
+
+class TimeofDay
+{
+//! inherits TimeRange
+   inherit TimeRange;
+
+   constant is_timeofday=1;
+
+   TimeRange base; // base day
+   int ux;         // unix time (in UTC, no timezone or DST thing)
+   int len;        // size in seconds (n*60)
+   
+// may be unknown (CALUNKNOWN)
+   int ls;         // local second (on this day, adjusted for dst and tz)
+   int utco=CALUNKNOWN; // offset to utc, counting dst
+   string tzn;     // name of timezone
+   
+//! method void create()
+//! method void create(int unixtime)
+//!	In addition to the wide range of construction arguments
+//!	for a normal TimeRange (see <ref>TimeRange.create</ref>),
+//!	a time of day can also be constructed with unixtime
+//!	as single argument consisting of the unix time
+//!	- as returned from <tt>time(2)</tt> - of the time unit start.
+//!
+//!	It can also be constructed without argument, which
+//!	then means "now", as in "this minute".
+
+//- for internal use:
+//- method void create("timeofday",rules,unixtime,len)
+
+   void create(mixed ...args)
+   {
+      if (!sizeof(args))
+      {
+	 rules=default_rules;
+	 create_now();
+	 return;
+      }
+      switch (args[0])
+      {
+	 case "timeofday":
+	    rules=[object(Ruleset)]args[1];
+	    ux=[int]args[2];
+	    len=[int]args[3];
+	    ls=CALUNKNOWN;
+	    return;
+
+	 case "timeofday_sd":
+	    rules=[object(Ruleset)]args[1];
+	    ux=[int]args[2];
+	    len=[int]args[3];
+	    ls=[int]args[4];
+	    utco=[int]args[5];
+	    return;
+      
+	 default:
+	    if (intp(args[0]) && sizeof(args)==1)
+	    {
+	       rules=default_rules;
+	       create_unixtime_default([int]args[0]);
+	       return;
+	    }
+      }
+      rules=default_rules;
+      if (create_backtry(@args)) return;
+      ::create(@args);
+   }
+
+   static int(0..1) create_backtry(mixed ...args) 
+   {
+      if (sizeof(args)>1 && objectp(args[0])) 
+      {
+	 base=args[0];
+	 rules=base->ruleset();
+	 args=args[1..];
+      }
+      if (base)
+      {
+	 switch (sizeof(args))
+	 {
+	    case 3:
+	       if (intp(args[0]) && intp(args[1]) && intp(args[2]))
+	       {
+		  create_unixtime_default(base->second(@args)->unix_time());
+		  return 1;
+	       }
+	       break;
+	    case 2:
+	       if (intp(args[0]) && intp(args[1]))
+	       {
+		  create_unixtime_default(base->second(@args,0)->unix_time());
+		  return 1;
+	       }
+	       break;
+	 }
+      }
+      return 0;
+   }
+
+   void create_unixtime(int unixtime,int _len)
+   {
+      ux=unixtime;
+      len=_len;
+      ls=CALUNKNOWN;
+   }
+
+   static void create_now();
+
+   void create_julian_day(int|float jd)
+   {
+// 1970-01-01 is julian day 2440588
+      jd-=2440588;
+      float fjd=(jd-(int)jd)-0.5;
+      ux=((int)jd)*86400+(int)(fjd*86400);
+      ls=CALUNKNOWN;
+   }
+
+// make base
+// needed in ymd
+/*static*/ TimeRange make_base()
+   {
+      base=Day("unix_r",ux,rules);
+      if (len) base=base->range(Day("unix_r",ux+len,rules));
+//        werror("make base -> %O\n",base);
+      return base;
+   }
+
+// make local second 
+   static void make_local()
+   {
+      if (!base) make_base();
+
+      ls=ux-base->unix_time();
+      if (rules->timezone->is_dst_timezone)
+      {
+	 if (utco==CALUNKNOWN) 
+	    [utco,tzn]=rules->timezone->tz_ux(ux);
+	 if (utco!=base->utc_offset())
+	    ls+=base->utc_offset()-utco;
+      }
+   }
+
+// default autopromote
+   TimeRange autopromote()
+   {
+      return this_object();
+   }
+
+   array(int(-1..1)) _compare(TimeRange with)
+   {
+#define CMP(A,B) ( ((A)<(B))?-1:((A)>(B))?1:0 )
+
+      if (with->is_timeofday_f)
+      {
+	 array(int(-1..1)) cmp=with->_compare(this_object());
+
+	 return ({-cmp[0],
+		  -cmp[2],
+		  -cmp[1],
+		  -cmp[3]});
+      }
+      else if (with->is_timeofday)
+	 return ({ CMP(ux,with->ux),CMP(ux,with->ux+with->len),
+		   CMP(ux+len,with->ux),CMP(ux+len,with->ux+with->len) });
+      else if (with->is_supertimerange ||
+	       with->is_nulltimerange ||
+	       !with->unix_time)
+	 return ::_compare(with);
+      else
+      {
+	 int e2=with->end()->unix_time();
+	 int b2=with->unix_time();
+
+	 return ({ CMP(ux,b2),CMP(ux,e2),CMP(ux+len,b2),CMP(ux+len,e2) });
+      }
+   }
+   
+   cSecond beginning()
+   {
+      return Second("timeofday_sd",rules,ux,0,ls,utco)->autopromote();
+   }
+
+   cSecond end()
+   {
+      return Second("timeofday",rules,ux+len,0)->autopromote();
+   }
+
+   TimeRange distance(TimeRange to)
+   {
+      if (to->is_ymd)
+	 return distance(to->hour());
+
+      if (!to->is_timeofday) 
+	 error("distance: incompatible class %O\n",
+	       object_program(to));
+
+      if (to->is_timeofday_f) 
+	 return 
+	    Fraction("timeofday_f",rules,ux,0,len,0)
+	    ->distance(to);
+
+      int m;
+      if ( (m=to->unix_time()-unix_time())<0) 
+	 error("Negative distance %O .. %O\n", this_object(),to);
+
+      return 
+	 Second("timeofday_sd",rules,ux,m,ls,utco)
+	 ->autopromote();
+   }
+
+   TimeRange range(TimeRange to)
+   {
+      if (to->is_timeofday_f) 
+      {
+	 return distance(to->end());
+      }
+      if (to->is_timeofday) 
+      {
+	 int m;
+	 if ( (m=to->unix_time()+to->len-unix_time())<0 )
+	    error("Negative range\n");
+	 return Second("timeofday_sd",rules,ux,m,ls,utco)
+	    ->autopromote();
+      }
+      return ::range(to);
+   }
+
+   static void convert_from(TimeRange other)
+   {
+      ::convert_from(other);
+      if (other->is_timeofday)
+	 len=other->len;
+      else if (other->number_of_seconds)
+	 len=other->number_of_seconds();
+      else if (other->number_of_days)
+	 len=86400*other->number_of_days(); // chance
+      else
+	 len=0; // *shrug*
+   }
+
+   TimeRange _set_size(int n,TimeRange t)
+   {
+      if (!t->is_timeofday)
+	 return distance(add(n,t));
+
+      return Second("timeofday_sd",rules,ux,n*(t->len),ls,utco)->autopromote();
+   }
+
+   TimeRange _move(int n,int m);
+
+   TimeRange _add(int n,TimeRange step)
+   {
+      if (step->is_timeofday_f)
+	 return Fraction("timeofday_f",rules,ux,0,len,0)
+	    ->add(n,step);
+      if (step->is_timeofday)
+	 return _move(n,step->number_of_seconds());
+
+      if (!base) make_base();
+      return base->add(n,step)->place(this_object(),1);
+   }
+
+//! method Hour hour()
+//! method Hour hour(int n)
+//! method array(Hour) hours()
+//! method array(Hour) hours(int first,int last)
+//! method int number_of_hours()
+//!	<ref>hour</ref>() gives back the timerange representing the
+//!	first or <i>n</i>th Hour of the called object.
+//!	Note that hours normally starts to count at zero,
+//!	so <tt>->hour(2)</tt> gives the third hour within
+//!	the range.
+//!
+//!	An Hour is in the Calendar perspective as any other
+//!	time range not only 60 minutes, but also one 
+//!	of the (normally) 24 hours of the day, precisely.
+//!
+//!	<ref>hours</ref>() give back an array of all the hours
+//!	containing the time periods called. With arguments,
+//!	it will give back a range of those hours, in the
+//!	same enumeration as the <i>n</i> to <ref>hour</ref>().
+//!
+//!	<ref>number_of_hours</ref>() simple counts the
+//!	number of hours containing the called time period.
+//!
+//! Note:
+//!	The called object doesn't have to
+//!	*fill* all the hours it will send back, it's 
+//!	enough if it exist in those hours:
+//!
+//! 	<pre>
+//!	> object h=Calendar.Time.Hour();
+//!	Result: Hour(265567)
+//!	> h->hours();                    
+//!	Result: ({ /* 1 element */
+//!		    Hour(265567)
+//!		})
+//!	> h+=Calendar.Time.Minute();
+//!	Result: Minute(265567:01+60m)
+//!	> h->hours();
+//!	Result: ({ /* 2 elements */
+//!		    Hour(265567),
+//!		    Hour(265568)
+//!		})
+//!	</pre>
+
+
+
+   cHour hour(void|int n)
+   {
+// hours are on the day, adjust for timezone (non-full-hour timezones!)
+      if (ls==CALUNKNOWN) make_local();
+      int zx=ux-ls%3600;
+
+      if (!n || (n==-1 && !len)) 
+	 return Hour("timeofday",rules,zx,3600);
+      if (n<0) n=number_of_hours()+n;
+      if (n<0 || n*3600>=len+ux-zx) 
+	 error("hour not in timerange (hour 0..%d exist)\n",(len-1)/3600);
+      return Hour("timeofday",rules,zx+3600*n,3600)->autopromote();
+   }
+
+   int number_of_hours()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      int zx=ux-ls%3600;
+      return ((ux-zx)+len+3599)/3600;
+   }
+
+   array(cSecond) hours(int ...range)
+   { return get_timeofday("hours",0,3600,Hour,@range); }
+
+//! method Minute minute()
+//! method Minute minute(int n)
+//! method array(Minute) minutes()
+//! method array(Minute) minutes(int first,int last)
+//! method int number_of_minutes()
+//!	<ref>minute</ref>() gives back the timerange representing the
+//!	first or <i>n</i>th Minute of the called object.
+//!	Note that minutes normally starts to count at zero,
+//!	so <tt>->minute(2)</tt> gives the third minute within
+//!	the range.
+//!
+//!	An Minute is in the Calendar perspective as any other
+//!	time range not only 60 seconds, but also one 
+//!	of the (normally) 60 minutes of the <ref>Hour</ref>, precisely.
+//!
+//!	<ref>minutes</ref>() give back an array of all the minutes
+//!	containing the time periods called. With arguments,
+//!	it will give back a range of those minutes, in the
+//!	same enumeration as the <i>n</i> to <ref>minute</ref>().
+//!
+//!	<ref>number_of_minutes</ref>() simple counts the
+//!	number of minutes containing the called time period.
+//!
+
+   cMinute minute(void|int n)
+   {
+// minutes are on the day, adjust for timezone (non-full-minute timezones!)
+      if (ls==CALUNKNOWN) make_local();
+      int zx=ux-ls%60;
+
+      if (!n || (n==-1 && !len)) 
+	 return Minute("timeofday",rules,zx,60);
+      if (n<0) n=number_of_minutes()+n;
+      if (n<0 || n*60>=len+ux-zx) 
+	 error("minute not in timerange (minute 0..%d exist)\n",(len-1)/60);
+      return Minute("timeofday",rules,zx+60*n,60)->autopromote();
+   }
+
+   int number_of_minutes()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      int zx=ux-ls%60;
+      return ((ux-zx)+len+59)/60;
+   }
+
+   array(cSecond) minutes(int ...range)
+   { return get_timeofday("minutes",0,60,Minute,@range); }
+
+//! method Second second()
+//! method Second second(int n)
+//! method array(Second) seconds()
+//! method array(Second) seconds(int first,int last)
+//! method int number_of_seconds()
+//!	<ref>second</ref>() gives back the timerange representing the
+//!	first or <i>n</i>th Second of the called object.
+//!	Note that seconds normally starts to count at zero,
+//!	so <tt>->second(2)</tt> gives the third second within
+//!	the range.
+//!
+//!	<ref>seconds</ref>() give back an array of all the seconds
+//!	containing the time periods called. With arguments,
+//!	it will give back a range of those seconds, in the
+//!	same enumeration as the <i>n</i> to <ref>second</ref>().
+//!
+//!	<ref>number_of_seconds</ref>() simple counts the
+//!	number of seconds containing the called time period.
+
+   cSecond second(void|int n)
+   {
+      int len=number_of_seconds();
+      if (!n || (n==-1 && !len)) 
+	 return Second("timeofday",rules,ux,1);
+      if (n<0) n=len+n;
+      if (n<0 || n>=len)
+	 error("second not in timerange (second 0..%d exist)\n",len);
+      return Second("timeofday",rules,ux+n,1)->autopromote();
+   }
+
+   static array(TimeRange) get_timeofday(string unit,
+					 int start,int step,program p,
+					 int ... range)
+   {
+      int from=0,n=::`[]("number_of_"+unit)(),to=n-1;
+
+      if (sizeof(range)) 
+	 if (sizeof(range)<2)
+	    error("Illegal numbers of arguments to "+unit+"()\n");
+	 else
+	 {
+	    [from,to]=range;
+	    if (from>=n) return ({}); else if (from<0) from=0;
+	    if (to>=n) to=n-1; else if (to<from) return ({});
+	 }
+      
+      from*=step;
+      to*=step;
+
+      to-=from-step;
+
+      if (ls==CALUNKNOWN) make_local();
+      from+=ux-ls%step;
+
+      return
+	 map(enumerate(to/step,step,from),
+	     lambda(int x)
+	     { return p("timeofday",rules,x,step); });
+   }
+
+   array(cSecond) seconds(int ...range)
+   { return get_timeofday("seconds",0,1,Second,@range); }
+
+   int number_of_seconds()
+   {
+      return len;
+   }
+
+// --------------------
+
+   float number_of_fractions() { return (float)number_of_seconds(); }
+   cSecond fraction(float|int ... n) 
+   {
+      if (sizeof(n))
+      {
+	 float m=n[0];
+	 if (m<=-1.0) m=1+number_of_fractions()+m;
+	 array q=fractions(m,m);
+	 if (!sizeof(q)) 
+	    error("fraction not in range (0..%.1f)\n",number_of_fractions());
+	 return q[0];
+      }
+      else
+	 return fractions()[0];
+   }
+   array(cSecond) fractions(int|float ...range)
+   { 
+      float from,to,n=number_of_fractions();
+      if (sizeof(range)==2)
+	 from=(float)range[0],to=(float)range[1]; 
+      else if (sizeof(range)==0)
+	 from=0.0,to=n;
+      else 
+	 error("Illegal arguments\n");
+      if (from<0.0) from=0.0;
+      if (to>n) to=n;
+      if (to<from)
+	 return ({});
+      to-=from;
+      return ({Fraction("timeofday_f",rules,
+			ux+(int)from,(int)(inano*(from-(int)from)),
+			(int)to,(int)(inano*(to-(int)to)))
+	       ->autopromote()});
+   }
+
+// --------------------
+
+   string nice_print();
+
+   string nice_print_period()
+   {
+      if (!base) make_base();
+
+      if (!len) 
+	 return sprintf("%s %s sharp",
+			base->nice_print(),nice_print());
+
+      string a=base->nice_print();
+      object e=end();
+      string b=e->day()->nice_print();
+      string c=e->nice_print();
+      if (a==b) 
+	 return a+" "+nice_print()+" - "+end()->nice_print();
+      if (c==b)
+	 return a+" "+nice_print()+" - "+b+" 0:00";
+      return a+" "+nice_print()+" - "+b+" "+end()->nice_print();
+   }
+
+//! method TimeRange set_size_seconds(int seconds)
+//! method TimeRange set_size_ns(int nanoseconds)
+//!	These two methods allows the time range
+//!	to be edited by size of specific units.
+
+
+   TimeRange set_size_seconds(int seconds)
+   {
+      if (seconds<0) error("Negative size\n");
+      return Second("timeofday_sd",rules,ux,seconds,ls,utco)
+	 ->autopromote();
+   }
+
+   TimeRange set_size_ns(int nanoseconds)
+   {
+      if (nanoseconds<0) error("Negative size\n");
+      return Fraction("timeofday_f",rules,ux,0,0,nanoseconds)
+	 ->autopromote();
+   }
+
+//! method TimeRange move_seconds(int seconds)
+//! method TimeRange move_ns(int nanoseconds)
+//!	These two methods gives back the 
+//!	time range called moved the specified
+//!	amount of time, with the length intact.
+//!
+//!	The motion is relative to the original position
+//!	in time; 10 seconds ahead of 10:42:32 is 10:42:42, etc.
+
+   TimeRange move_seconds(int seconds)
+   {
+      return _move(seconds,1);
+   }
+
+   TimeRange move_ns(int nanoseconds)
+   {
+      return Fraction("timeofday_f",rules,ux,nanoseconds,len,0)
+	 ->autopromote();
+   }
+
+// --------
+
+//! method int unix_time()
+//!	This calculates the corresponding unix time,
+//!	- as returned from <tt>time(2)</tt> - from the
+//!	time range. Note that the calculated unix time
+//!	is the beginning of the period.
+
+   int unix_time() { return ux; }
+
+//! method float julian_day()
+//!	This calculates the corresponding julian day,
+//!	from the time range. Note that the calculated day
+//!	is the beginning of the period, and is a float -
+//!	julian day standard says .00 is midday, 12:00 pm.
+//!
+//! note:
+//!	Normal pike (ie, 32 bit) floats (without --with-double-precision)
+//!	has a limit of about 7 digits, and since we are about
+//!	julian day 2500000, the precision on time of day is very limited.
+
+   float julian_day() 
+   { 
+      return 2440588+ux/86400.0-0.5;
+   }
+
+//! method int hour_no()
+//! method int minute_no()
+//! method int second_no()
+//! method float fraction_no()
+//!	This gives back the number of the time unit,
+//!	on this day. Fraction is a float number, 0&lt;=fraction&lt;1.
+
+   int hour_no()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      return ls/3600;
+   }
+
+   int minute_no()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      return (ls/60)%60;
+   }
+
+   int second_no()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      return ls%60;
+   }
+
+   float fraction_no()
+   {
+      return 0.0;
+   }
+
+//! function mapping datetime()
+//!     This gives back a mapping with the relevant
+//!	time information (representing the start of the period);
+//!	<pre>
+//!	 ([ "year":     int        // year number (2000 AD=2000, 1 BC==0)
+//!	    "month":    int(1..)   // month of year
+//!	    "day":      int(1..)   // day of month
+//!	    "yearday":  int(1..)   // day of year
+//!	    "week":	int(1..)   // week of year
+//!	    "week_day": int(1..)   // day of week (depending on calendar)
+//!
+//!	    "hour":     int(0..)   // hour of day, including dst
+//!	    "minute":   int(0..59) // minute of hour
+//!	    "second":   int(0..59) // second of minute 
+//!	    "fraction": float      // fraction of second
+//!	    "timezone": int        // offset to utc, including dst
+//!
+//!	    "unix":     int        // unix time
+//!	    "julian":   float      // julian day
+//!	 ]);
+//!	</pre>
+
+   mapping datetime()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      if (!base) make_base();
+      return base->datetime(1) |
+      (["hour":ls/3600,
+	"minute":(ls/60)%60,
+	"second":ls%60,
+	"fraction":0.0,
+	"timezone":utc_offset(),
+	"julian":julian_day(),
+	"unix":ux
+      ]);
+   }
+
+// --- string format ----
+
+//! method string format_iso_ymd();
+//! method string format_ymd();
+//! method string format_ymd_short();
+//! method string format_ymd_xshort();
+//! method string format_iso_week();
+//! method string format_iso_week_short();
+//! method string format_week();
+//! method string format_week_short();
+//! method string format_month();
+//! method string format_month_short();
+//! method string format_iso_time();
+//! method string format_time();
+//! method string format_time_short();
+//! method string format_time_xshort();
+//! method string format_mtime();
+//! method string format_xtime();
+//! method string format_tod();
+//! method string format_xtod();
+//! method string format_mod();
+//!	Format the object into nice strings;
+//!	<pre>
+//!	iso_ymd        "2000-06-02 (Jun) -W22-5 (Fri)" [2]
+//!	ext_ymd        "Friday, 2 June 2000" [2]
+//!     ymd            "2000-06-02" 
+//!     ymd_short      "20000602"
+//!     ymd_xshort     "000602" [1]
+//!	iso_week       "2000-W22"
+//!	iso_week_short "2000W22"
+//!	week           "2000-w22" [2]
+//!	week_short     "2000w22" [2]
+//!	month          "2000-06"
+//!	month_short    "200006" [1]
+//!	iso_time       "2000-06-02 (Jun) -W22-5 (Fri) 20:53:14 UTC+1" [2]
+//!	ext_time       "Friday, 2 June 2000, 20:53:14" [2]
+//!	ctime          "Fri Jun  4 20:53:14 2000\n" [2] [3]
+//!	http           "Fri, 02 Jun 2000 20:53:14 GMT" [4]
+//!     time           "2000-06-02 20:53:14" 
+//!	time_short     "20000602 20:53:14"
+//!	time_xshort    "000602 20:53:14"
+//!     mtime          "2000-06-02 20:53" 
+//!     xtime          "2000-06-02 20:53:14.000000" 
+//!     todz           "20:53:14 CET"
+//!     todz_iso       "20:53:14 UTC+1"
+//!     tod            "20:53:14"
+//!     tod_short      "205314"
+//!     xtod           "20:53:14.000000"
+//!     mod            "20:53"
+//!	</pre>
+//!	<tt>[1]</tt> note conflict (think 1 February 2003)
+//!	<br><tt>[2]</tt> language dependent
+//!	<br><tt>[3]</tt> as from the libc function ctime()
+//!	<br><tt>[4]</tt> as specified by the HTTP standard;
+//!	this is always in GMT, ie, UTC. The timezone calculations
+//!	needed will be executed implicitly. It is not language
+//!	dependent.
+
+   string format_ext_ymd();
+   string format_iso_ymd();
+   string format_ymd();
+   string format_ymd_short();
+   string format_ymd_xshort();
+   string format_iso_week();
+   string format_iso_week_short();
+   string format_week();
+   string format_week_short();
+   string format_month();
+   string format_month_short();
+
+   string format_iso_time()
+   {
+      return this_object()->format_iso_ymd()+" "+format_todz_iso();
+   }
+
+   string format_ext_time()
+   {
+      return this_object()->format_ext_ymd()+" "+format_tod();
+   }
+
+   string format_time()
+   {
+      return this_object()->format_ymd()+" "+format_tod();
+   }
+
+   string format_time_short()
+   {
+      return this_object()->format_ymd_short()+" "+format_tod();
+   }
+
+   string format_time_xshort()
+   {
+      return this_object()->format_ymd_xshort()+" "+format_tod();
+   }
+
+   string format_mtime()
+   {
+      return this_object()->format_ymd_short()+" "+format_mod();
+   }
+
+   string format_xtime()
+   {
+      return this_object()->format_ymd_short()+" "+format_xtod();
+   }
+
+   string format_ctime()
+   {
+      if (!base) make_base();
+      return replace(base->format_ctime(),
+		     "00:00:00",format_tod());
+   }
+
+   string format_http()
+   {
+      if (utc_offset())
+	 return set_timezone(Timezone_UTC)->format_http();
+      if (!base) make_base();
+
+      return replace(base->format_http(),
+		     "00:00:00",format_tod());
+   }
+
+   string format_tod()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      return sprintf("%02d:%02d:%02d", ls/3600, (ls/60)%60, ls%60);
+   }
+
+   string format_tod_short()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      return sprintf("%02d%02d%02d", ls/3600, (ls/60)%60, ls%60);
+   }
+
+   string format_todz()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      return sprintf("%02d:%02d:%02d %s",
+		     ls/3600,
+		     (ls/60)%60,
+		     ls%60,
+		     tzname());
+   }
+
+   string format_todz_iso()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      return sprintf("%02d:%02d:%02d %s",
+		     ls/3600,
+		     (ls/60)%60,
+		     ls%60,
+		     tzname_iso());
+   }
+
+   string format_mod()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      return sprintf("%02d:%02d",ls/3600,(ls/60)%60);
+   }
+
+   string format_xtod()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      return sprintf("%02d:%02d:%02d.%06d",
+		     ls/3600,
+		     (ls/60)%60,
+		     ls%60,
+		     0);
+   }
+
+   string format_elapsed()
+   {
+      string res="";
+      object left=this_object();
+      int x;
+      if ( (x=(this_object()/Day)) )
+      {
+	 res+=sprintf("%dd",x);
+	 left=this_object()->add(x,Day)->range(this_object()->end());
+      }
+      return sprintf("%s%d:%02d:%02d",
+		     res,left->len/3600,
+		     (left->len/60)%60,
+		     left->len%60);
+   }
+
+
+// --------
+
+   TimeofDay set_ruleset(Ruleset r)
+   {
+      return 
+	 Second("timeofday",r,ux,len)
+	 ->autopromote();
+   }
+
+   int utc_offset()
+   {
+      if (utco==CALUNKNOWN)
+	 return [utco,tzn]=rules->timezone->tz_ux(ux),utco;
+      else 
+	 return utco;
+   }
+
+   string tzname()
+   {
+      if (tzn) return tzn;
+      if (rules->timezone->is_dst_timezone)
+	 return [utco,tzn]=rules->timezone->tz_ux(ux),tzn;
+      return tzn=rules->timezone->name;      
+   }
+
+   string tzname_iso()
+   {
+      int u=utc_offset();
+      if (!(u%3600))
+	 return sprintf("UTC%+d",-u/3600);
+      if (!(u%60))
+	 return 
+	    (u<0)
+	    ?sprintf("UTC+%d:%02d",-u/3600,(-u/60)%60)
+	    :sprintf("UTC-%d:%02d",u/3600,(u/60)%60);
+      return 
+	 (u<0)
+	 ?sprintf("UTC+%d:%02d:%02d",-u/3600,(-u/60)%60,(-u)%60)
+	 :sprintf("UTC-%d:%02d:%02d",u/3600,(u/60)%60,u%60);
+   }
+
+// --------
+
+//  #define TIME_OPERATOR_DEBUG
+#ifdef TIME_OPERATOR_DEBUG
+#define DEBUG_OVERLOAD_OPERATOR(OP,NAME,IND)				\
+   TimeRange OP(mixed ...args)						\
+   {									\
+      _ind+=IND;							\
+      TimeRange x=::OP(@args);						\
+      _ind=_ind[..strlen(_ind)-strlen(IND)-1];				\
+      werror(_ind+"  %O\n",this_object());				\
+      foreach (args,TimeRange t) werror(_ind+NAME+" %O\n",t);		\
+      werror(_ind+"= %O\n",x);						\
+      return x;								\
+   }
+   DEBUG_OVERLOAD_OPERATOR(`&,"&","|  ");
+   DEBUG_OVERLOAD_OPERATOR(`^,"^","|  ");
+   DEBUG_OVERLOAD_OPERATOR(`|,"|","|  ");
+   DEBUG_OVERLOAD_OPERATOR(subtract,"-","|  ");
+#endif
+}
+
+   string _ind="* ";
+
+//-----------------------------------------------------------------
+//! class SuperTimeRange
+//! inherits TimeRanges.SuperTimeRange
+//-----------------------------------------------------------------
+
+class cSuperTimeRange
+{
+   inherit TimeRanges::cSuperTimeRange;
+
+#ifdef TIME_OPERATOR_DEBUG
+   DEBUG_OVERLOAD_OPERATOR(`&,"&","S  ");
+   DEBUG_OVERLOAD_OPERATOR(`^,"^","S  ");
+   DEBUG_OVERLOAD_OPERATOR(`|,"|","S  ");
+   DEBUG_OVERLOAD_OPERATOR(subtract,"-","S  ");
+#endif
+
+//! method Second second()
+//! method Second second(int n)
+//! method array(Second) seconds()
+//! method array(Second) seconds(int first,int last)
+//! method int number_of_seconds()
+//! method Minute minute()
+//! method Minute minute(int n)
+//! method array(Minute) minutes()
+//! method array(Minute) minutes(int first,int last)
+//! method int number_of_minutes()
+//! method Hour hour()
+//! method Hour hour(int n)
+//! method array(Hour) hours()
+//! method array(Hour) hours(int first,int last)
+//! method int number_of_hours()
+//!	Similar to <ref>TimeofDay</ref>, the Time::SuperTimeRange
+//!	has a number of methods for digging out time parts of the
+//!	range. Since a <ref>SuperTimeRange</ref> is a bit more
+//!	complex - the major reason for its existance it that it 
+//!	contains holes, this calculation is a bit more advanced too.
+//!
+//!	If a range contains the seconds, say, 1..2 and 4..5, 
+//!	the third second (number 2, since we start from 0) 
+//!	in the range would be number 4, like this:
+//!
+//!	<pre>
+//!	no   means this second
+//!	0    1        
+//!	1    2        
+//!	2    4      &lt;- second three is missing,
+//!	3    5         as we don't have it in the example range
+//!	</pre>
+//!
+//!	<ref>number_of_seconds</ref>() will in this example 
+//!	therefore also report 4, not 5, even if the time from
+//!	start of the range to the end of the range is 5 seconds.
+//!
+
+   array(cHour) hours(int ...range) { return get_units("hours",@range); }
+   cHour hour(void|int n) { return get_unit("hours",n); }
+   int number_of_hours() { return num_units("hours"); }
+
+   array(cMinute) minutes(int ...range) { return get_units("minutes",@range); }
+   cMinute minute(void|int n) { return get_unit("minutes",n); }
+   int number_of_minutes() { return num_units("minutes"); }
+
+   array(cSecond) seconds(int ...range) { return get_units("seconds",@range); }
+   cSecond second(void|int n) { return get_unit("seconds",n); }
+   int number_of_seconds() { return num_units("seconds"); }
+
+// wrapper methods to calculate units in a supertimerange
+
+   static array(TimeRange) get_units(string unit,int ... range)
+   {
+      int from=0,to=0x7fffffff,pos=0;
+      array res=({});
+      TimeRange last=0;
+      string ums=unit[..strlen(unit)-2]; // no 's'
+
+      if (sizeof(range)==2)
+	 [from,to]=range;
+      else if (sizeof(range)==1)
+	 error("Illegal numbers of arguments to "+unit+"()\n");
+
+      foreach (parts,TimeRange part)
+      {
+	 if (pos>=from)
+	 {
+	    if (pos>to) break;
+	    array tmp=part[unit](from-pos,to-pos);
+	    pos+=sizeof(tmp);
+	    if (tmp[0]==last) tmp=tmp[1..];
+	    res+=tmp;
+	    if (sizeof(tmp)) last=tmp[-1];
+	 }
+	 else
+	 {
+	    int n=part["number_of_"+unit]();
+	    TimeRange l=part[ums]();
+	    if (l==last) n--;
+	    if (n+pos>from)
+	       res=part[unit](from-pos,to-pos);
+	    pos+=n;
+	    last=l;
+	 }
+      }
+      return res;
+   }
+
+   static int num_units(string unit)
+   {
+      int pos=0;
+      TimeRange last=0;
+      string ums=unit[..strlen(unit)-2]; // no 's'
+
+      foreach (parts,TimeRange part)
+      {
+	 int n=part["number_of_"+unit]();
+	 TimeRange l=part[ums]();
+	 if (l==last) n--;
+	 pos+=n;
+	 last=l;
+      }
+      return pos;
+   }
+
+   static TimeRange get_unit(string unit,int n)
+   {
+      array(TimeRange) res=get_units(unit,n,n);
+      if (sizeof(res)==1) return res[0];
+      error("not in range ("+unit+" 0..%d exist)\n",
+	    num_units(unit)-1);
+   }
+
+#define RBASE parts[0]
+
+   string format_ext_ymd();
+   string format_iso_ymd();
+   string format_ymd();
+   string format_ymd_short();
+   string format_ymd_xshort();
+   string format_iso_week();
+   string format_iso_week_short();
+   string format_week();
+   string format_week_short();
+   string format_month();
+   string format_month_short();
+
+   string format_iso_time() { return RBASE->format_iso_time(); }
+   string format_ext_time() { return RBASE->format_ext_time(); }
+   string format_time() { return RBASE->format_time(); }
+   string format_time_short() { return RBASE->format_time_short(); }
+   string format_time_xshort() { return RBASE->format_time_xshort(); }
+   string format_mtime() { return RBASE->format_mtime(); }
+   string format_xtime() { return RBASE->format_xtime(); }
+   string format_ctime() { return RBASE->format_ctime(); }
+   string format_http() { return RBASE->format_http(); }
+   string format_tod() { return RBASE->format_tod(); }
+   string format_todz() { return RBASE->format_todz(); }
+   string format_todz_iso() { return RBASE->format_todz_iso(); }
+   string format_mod() { return RBASE->format_mod(); }
+   string format_xtod() { return RBASE->format_xtod(); }
+
+   int hour_no() { return RBASE->hour_no(); }
+   int minute_no() { return RBASE->minute_no(); }
+   int second_no() { return RBASE->second_no(); }
+
+#undef RBASE
+
+// count parts elapsed
+   string format_elapsed() 
+   {
+      TimeRange z=parts[0];
+      foreach (parts,TimeRange y) z+=y;
+      return parts[0]->distance(z)->format_elapsed();
+   }
+}
+
+//------------------------------------------------------------------------
+//! class Hour
+//------------------------------------------------------------------------
+
+function(mixed...:cHour) Hour=cHour; // inheritance purposes
+class cHour
+{
+   constant is_hour=1;
+
+//! inherits TimeofDay
+
+   inherit TimeofDay;
+
+   void create_unixtime(int unixtime,int _len)
+   {
+      int z;
+      ux=unixtime;
+      len=_len;
+      if (base==0) make_base();
+      ls=ux-(z=base->unix_time());
+      ls-=ls%3600;
+      ux=z+ls;
+   }
+
+   void create_unixtime_default(int unixtime)
+   {
+      create_unixtime(unixtime,3600);
+   }
+
+   static void create_now()
+   {
+      create_unixtime(time(),3600);
+   }
+
+   static void create_julian_day(int|float jd)
+   {
+      ::create_julian_day(jd);
+      len=3600;
+   }
+
+   static void convert_from(TimeRange other)
+   {
+      ::convert_from(other);
+      len-=len%3600;
+   }
+
+   TimeofDay _move(int n,int m)
+   {
+      if (m==0 || n==0) return this_object();
+      if (m%3600) 
+	 return Second("timeofday",rules,ux,len)->_move(n,m);
+      return Hour("timeofday",rules,ux+n*m,len)->autopromote(); 
+   }
+
+
+   string _sprintf(int t)
+   {
+      if (catch {
+      switch (t)
+      {
+	 case 'O':
+	    if (!base) make_base();
+	    if (len!=3600)
+	       return sprintf("Hour(%s)",
+			      nice_print_period());
+	    return sprintf("Hour(%s %s)",
+			   base->nice_print(),
+			   nice_print());
+	 default:
+	    return 0;
+      }
+      })
+	 return "error";
+   }
+
+   string nice_print()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      return sprintf("%d:00 %s",ls/3600,tzname());
+   }
+}
+
+//------------------------------------------------------------------------
+//! class Minute
+//------------------------------------------------------------------------
+
+function(mixed...:cMinute) Minute=cMinute; // inheritance purposes
+class cMinute
+{
+   constant is_minute=1;
+
+//! inherits TimeofDay
+
+   inherit TimeofDay;
+
+   void create_unixtime(int unixtime,int _len)
+   {
+      int z;
+      ux=unixtime;
+      len=_len;
+      if (base==0) make_base();
+      ls=ux-(z=base->unix_time());
+      ls-=ls%60;
+      ux=z+ls;
+   }
+
+   void create_unixtime_default(int unixtime)
+   {
+      create_unixtime(unixtime,60);
+   }
+
+   static void create_now()
+   {
+      create_unixtime(time()/60*60,60);
+   }
+
+   TimeofDay autopromote()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      if (!(ls%3600) && !(len%3600)) 
+	 return Hour("timeofday_sd",rules,ux,len,ls,utco)->autopromote();
+      return ::autopromote();
+   }
+
+   static void convert_from(TimeRange other)
+   {
+      ::convert_from(other);
+      len-=len%60;
+   }
+
+   TimeofDay _move(int n,int m)
+   {
+      if (m==0 || n==0) return this_object();
+      if (m%60) return Second("timeofday",rules,ux,len)->_move(n,m);
+      return Minute("timeofday",rules,ux+n*m,len)->autopromote(); 
+   }
+
+   string _sprintf(int t)
+   {
+      switch (t)
+      {
+	 case 'O':
+	    if (!base) make_base();
+	    if (len!=60)
+	       return sprintf("Minute(%s)",
+			      nice_print_period());
+	    return sprintf("Minute(%s %s)",
+			   base->nice_print(),
+			   nice_print());
+	 default:
+	    return 0;
+      }
+   }
+
+   string nice_print()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      return sprintf("%d:%02d %s",ls/3600,(ls/60)%60,tzname());
+   }
+}
+
+//------------------------------------------------------------------------
+//! class Second
+//------------------------------------------------------------------------
+
+function(mixed...:cSecond) Second=cSecond; // inheritance purposes
+class cSecond
+{
+   constant is_second=1;
+
+//! inherits TimeofDay
+
+   inherit TimeofDay;
+
+   void create_unixtime_default(int unixtime)
+   {
+      create_unixtime(unixtime,1);
+   }
+
+   static void create_now()
+   {
+      create_unixtime(time(),1);
+   }
+
+   static void create_julian_day(int|float jd)
+   {
+      ::create_julian_day(jd);
+      len=1;
+   }
+
+   TimeofDay autopromote()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      if (!(ls%60) && !(len%60)) 
+	 return Minute("timeofday",rules,ux,len)->autopromote();
+      return ::autopromote();
+   }
+
+   TimeofDay _move(int n,int m)
+   {
+      if (m==0 || n==0) return this_object();
+      return Second("timeofday",rules,ux+n*m,len)->autopromote(); 
+   }
+
+   string _sprintf(int t)
+   {
+      switch (t)
+      {
+	 case 'O':
+	    if (len!=1)
+	       return sprintf("Second(%s)",
+			      nice_print_period());
+	    if (!base) make_base();
+	    return sprintf("Second(%s %s)",
+			   base->nice_print(),
+			   nice_print());
+	 default:
+	    return 0;
+      }
+   }
+
+   string nice_print()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      return sprintf("%d:%02d:%02d %s",ls/3600,ls/60%60,ls%60,tzname());
+   }
+
+// backwards compatible with calendar I
+   string iso_name()
+   { return this_object()->format_ymd()+" T"+format_tod(); }
+   string iso_short_name() 
+   { return this_object()->format_ymd_short()+" T"+(format_tod()-":"); }
+}
+
+//------------------------------------------------------------------------
+//! class Fraction
+//!	A Fraction is a part of a second, and/or a time period
+//!	with higher resolution then a second. 
+//!
+//!	It contains everything that is possible to do with a 
+//!	<ref>Second</ref>, and also some methods of grabbing
+//!	the time period with higher resolution.
+//!
+//! note:
+//!	Internally, the fraction time period is measured in
+//!	nanoseconds. A shorter or more precise time period then 
+//!	in nanoseconds is not possible within the current Fraction class.
+//!
+//! inherits TimeofDay
+//------------------------------------------------------------------------
+
+function(mixed...:cFraction) Fraction=cFraction;
+class cFraction
+{
+   inherit cSecond;
+
+   constant is_timeofday_f=1;
+   constant is_fraction=1;
+
+   int ns;     // nanoseconds add to s
+   int len_ns; // nanoseconds length
+   int len_s;  // seconds length
+
+//! method void create()
+//! method void create("unixtime",int|float unixtime)
+//! method void create("unixtime",int|float unixtime,int|float len)
+//!	It is possible to create a Fraction in two ways,
+//!	either "now" with no arguments or
+//!	from a unix time (as from <tt>time(2)</tt>).
+//!
+//!	If created from unix time, both the start of the period
+//!	and the size of the period can be given in floats,
+//!	both representing seconds. Note that the default
+//!	float precision in pike is rather low (same as 'float' in C,
+//!	the 32 bit floating point precision, normally about 7 digits),
+//!	so beware that the resolution might bite you. (Internally
+//!	in a Fraction, the representation is an integer.)
+//!
+//!	If created without explicit length, the fraction will always be
+//!	of zero length.
+
+   void create(mixed ...args)
+   {
+      if (!sizeof(args))
+      {
+	 rules=default_rules;
+	 create_now();
+	 return;
+      }
+      else if (args[0]=="timeofday_f")
+      {
+	 rules=[object(Ruleset)]args[1];
+	 ux=[int]args[2];
+	 ns=[int]args[3];
+	 len_s=[int]args[4];
+	 len_ns=[int]args[5];
+	 ls=CALUNKNOWN;
+
+	 if (ns<0)
+	    error("Can't create negative ns: %O\n",this_object());
+
+	 if (!rules) error("no rules\n");
+
+	 if (len_ns>=inano) len_s+=(len_ns/inano),len_ns%=inano;
+	 if (ns>=inano) ux+=(ns/inano),ns%=inano;
+	 len=len_s+(ns+len_ns+inano-1)/inano;
+
+	 if (ns<0)
+	    error("Can't create negative ns: %O\n",this_object());
+
+	 return;
+      }
+      else if (intp(args[0]) && sizeof(args)==1)
+      {
+	 rules=default_rules;
+	 create_unixtime(args[0]);
+	 return;
+      }
+      else switch (args[0])
+      {
+	 case "unix":
+	    rules=default_rules;
+	    create_unixtime(@args[1..]);
+	    return;
+	 case "julian":
+	    rules=default_rules;
+	    create_julian_day(args[1]);
+	    return;
+	 case "unix_r":
+	    rules=args[-1];
+	    create_unixtime(@args[..sizeof(args)-2]);
+	    return;
+	 case "julian_r":
+	    rules=args[2];
+	    create_julian_day(args[1]);
+	    return;
+      }
+      rules=default_rules;
+      if (create_backtry(@args)) return;
+      error("Fraction: illegal argument(s) %O,%O,%O,...\n",
+	    @args,0,0,0);
+   }
+
+   int create_backtry(mixed ...args) 
+   {
+      if (sizeof(args)>1 && objectp(args[0]) && args[0]->is_day) 
+      {
+	 base=args[0];
+	 rules=base->ruleset();
+	 args=args[1..];
+      }
+      ls=CALUNKNOWN;
+      if (base)
+      {
+	 switch (sizeof(args))
+	 {
+	    case 4:
+	       if (intp(args[0]) && intp(args[1]) && intp(args[2]) &&
+		   intp(args[3]))
+	       {
+		  ux=base->second(@args[..2])->unix_time();
+		  ns=args[3];
+		  return 1;
+	       }
+	       break;
+	    case 3:
+	       if (intp(args[0]) && intp(args[1]) && floatp(args[2]))
+	       {
+		  ux=base->second(args[0],args[1],(int)args[2])->unix_time();
+		  ns=(int)(inano*(args[3]-(int)args[3]));
+		  return 1;
+	       }
+	       break;
+	 }
+      }
+      return ::create_backtry(@args);
+   }
+
+   static void create_now()
+   {
+      ux=time();
+      ns=(int)(inano*time(ux));
+      if (ns>=inano) ux+=(ns/inano),ns%=inano;
+      len=len_s=len_ns=0;
+      ls=CALUNKNOWN;
+   }
+
+   int unix_time() { return ux; }
+   float f_unix_time() { return ux+ns*(1.0/inano); }
+
+   static void create_unixtime(int|float unixtime,
+			       void|int|float _len)
+   {
+      ux=(int)unixtime;
+      ns=(int)(inano*(unixtime-(int)unixtime));
+      len_s=(int)_len;
+      len_ns=(int)(inano*(_len-(int)_len));
+      ls=CALUNKNOWN;
+   }
+
+   static void create_unixtime_default(int|float unixtime)
+   {
+      return create_unixtime(unixtime);
+   }
+
+   float julian_day()
+   {
+      return 2440588+(ux+ns*(1.0/inano))*(1/86400.0)+0.5;
+   }
+
+   static void create_julian_day(int|float jd)
+   {
+// 1970-01-01 is julian day 2440588
+      jd-=2440588;
+      float fjd=((jd-(int)jd)+0.5)*86400;
+      ux=((int)jd)*86400+(int)(fjd);
+      ns=(int)(inano*(fjd-(int)fjd));
+      
+      ls=CALUNKNOWN;
+   }
+
+   string _sprintf(int t)
+   {
+      switch (t)
+      {
+	 case 'O':
+	    if (!base) make_base();
+	    if (len_ns || len_s)
+	       return sprintf("Fraction(%s)",
+			      nice_print_period());
+	    return sprintf("Fraction(%s %s)",
+			   base->nice_print(),
+			   nice_print());
+	 default:
+	    return 0;
+      }
+   }
+
+   int __hash() { return ux; }
+
+   string nice_print()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      return sprintf("%d:%02d:%02d.%06d %s",
+		     ls/3600,ls/60%60,ls%60,ns/1000,tzname());
+   }
+
+   TimeofDay autopromote()
+   {
+      if (!ns && !len_ns)
+	 return Second("timeofday",rules,ux,len_s)->autopromote();
+
+      return this_object();
+   }
+
+   TimeofDay _move(int n,int z_s,void|int z_ns)
+   {
+      if ((z_s==0 && z_ns==0) || n==0) return autopromote();
+      int nns=ns+n*z_ns;
+      int nux=ux+n*z_s;
+      if (nns<0 || nns>=inano) nux+=nns/inano,nns%=inano;
+      return Fraction("timeofday_f",rules,nux,nns,len_s,len_ns)
+	 ->autopromote();
+   }
+
+   TimeRange _add(int n,TimeRange step)
+   {
+      if (step->is_timeofday_f)
+	 return _move(n,step->len_s,step->len_ns);
+      return ::_add(n,step);
+   }
+
+   static void convert_from(TimeRange other)
+   {
+      ::convert_from(other);
+      if (other->is_timeofday_f)
+      {
+	 ns=other->ns;
+	 len_s=other->len_s;
+	 len_ns=other->len_ns;
+      }
+   }
+
+   static TimeRange _set_size(int n,TimeRange t)
+   {
+      if (t->is_timeofday_f)
+	 return Fraction("timeofday_f",rules,ux,ns,
+			 n*t->len_s,n*t->len_ns)
+	    ->autopromote();
+
+      if (t->is_timeofday)
+	 return Fraction("timeofday_f",rules,ux,ns,n*t->len,0)
+	    ->autopromote();
+
+      return distance(add(n,t));
+   }
+
+   TimeRange distance(TimeRange to)
+   {
+   // s is 0 in an object that doesn't have s
+
+      int s1=ux;
+      int s2;
+
+      if (to->is_timeofday)
+	 s2=to->ux;
+      else 
+	 s2=to->unix_time();
+
+// ns is 0 in an object that doesn't have ns
+
+      if (s2<s1 ||
+	  (s2==s1 && to->ns<ns))
+	 error("Negative distance %O .. %O\n", this_object(),to);
+
+      return 
+	 Fraction("timeofday_f",rules,ux,ns,s2-s1-1,to->ns-ns+inano)
+	 ->autopromote();
+   }
+
+   TimeRange range(TimeRange to)
+   {
+      return distance(to->end());
+   }
+
+   array(int(-1..1)) _compare(TimeRange with)
+   {
+#define CMP2(AS,ANS,BS,BNS) 						\
+      (((AS)<(BS))?-1:							\
+       ((AS)>(BS))?1:							\
+       ((ANS)<(BNS))?-1:						\
+       ((ANS)>(BNS))?1:0)
+       
+      if (with->is_timeofday_f)
+	 return ({ CMP2(ux,ns,with->ux,with->ns),
+		   CMP2(ux,ns,with->ux+with->len_s,with->ns+with->len_ns),
+		   CMP2(ux+len_s,ns+len_ns,with->ux,with->ns),
+		   CMP2(ux+len_s,ns+len_ns,with->ux+with->len_s,
+			with->ns+with->len_ns) });
+      else if (with->is_timeofday)
+	 return ({ CMP2(ux,ns,with->ux,0),
+		   CMP2(ux,ns,with->ux+with->len,0),
+		   CMP2(ux+len_s,ns+len_ns,with->ux,0),
+		   CMP2(ux+len_s,ns+len_ns,with->ux+with->len, 0) });
+      return ::_compare(with);
+   }
+
+   TimeofDay beginning()
+   {
+      if (len_s==0.0 && len_ns==0.0) return this_object();
+      return Fraction("timeofday_f",rules,ux,ns,0,0)
+	 ->autopromote();
+   }
+
+   TimeofDay end()
+   {
+      if (len_s==0 && len_ns==0) return this_object();
+      object q=Fraction("timeofday_f",rules,ux+len_s,ns+len_ns,0,0)
+	 ->autopromote();
+      return q;
+   }
+   
+   TimeRange set_size_seconds(int seconds)
+   {
+      if (seconds<0) error("Negative size\n");
+      return Fraction("timeofday_f",rules,ux,ns,seconds,0)
+	 ->autopromote();
+   }
+
+   TimeRange set_size_ns(int nanoseconds)
+   {
+      if (nanoseconds<0) error("Negative size\n");
+      return Fraction("timeofday_f",rules,ux,ns,0,nanoseconds)
+	 ->autopromote();
+   }
+
+
+   TimeRange move_seconds(int seconds)
+   {
+      return _move(1,seconds);
+   }
+
+   TimeRange move_ns(int nanoseconds)
+   {
+      return _move(1,0,nanoseconds);
+   }
+
+   int number_of_seconds()
+   {
+      if (len_ns || ns) return len_s+1;
+      else return len_s||1;
+   }
+
+   float number_of_fractions() 
+   { 
+      return len_s+1e-9*len_ns;
+   }
+
+   array(cFraction) fractions(int|float ...range)
+   { 
+      float from,to,n=number_of_fractions();
+      if (sizeof(range)==2)
+	 from=(float)range[0],to=(float)range[1]; 
+      else if (sizeof(range)==0)
+	 from=0.0,to=n;
+      else 
+	 error("Illegal arguments\n");
+      if (from<0.0) from=0.0;
+      if (to>n) to=n;
+      if (to<from)
+	 return ({});
+
+      if (from==0.0 && to==n) return ({this_object()});
+
+      to-=from;
+      return ({Fraction("timeofday_f",rules,
+			ux+(int)from,ns+(int)(inano*(from-(int)from)),
+			(int)to,(int)(inano*(to-(int)to)))});
+   }
+
+   mapping datetime()
+   {
+      return ::datetime()|(["fraction":ns*(1.0/inano)]);
+   }
+
+   string format_xtod()
+   {
+      if (ls==CALUNKNOWN) make_local();
+      return sprintf("%02d:%02d:%02d.%06d",
+		     ls/3600,
+		     (ls/60)%60,
+		     ls%60,
+		     ns/1000);
+   }
+
+   string format_elapsed()
+   {
+      int x;
+      if ( (x=(this_object()/Day)) )
+      {
+	 object left=this_object()->add(x,Day)->range(this_object()->end());
+	 return sprintf("%dd%d:%02d:%02d.%03d",
+			x,left->len_s/3600,
+			(left->len_s/60)%60,
+			left->len_s%60,
+			left->len_ns/1000000);
+      }
+      if (len_s>=3600)
+	 return sprintf("%d:%02d:%02d.%03d",
+			len_s/3600,(len_s/60)%60,
+			len_s%60,len_ns/1000000);
+      if (len_s>=60)
+	 return sprintf("%d:%02d.%03d",
+			len_s/60,len_s%60,len_ns/1000000);
+      if (len_s || len_ns>inano/1000)
+	 return sprintf("%d.%06d",
+			len_s,len_ns/1000);
+      return sprintf("0.%09d",len_ns);
+   }
+}
+
+//------------------------------------------------------------------------
+//  global convinience functions
+//------------------------------------------------------------------------
+
+//! method TimeofDay now()
+//!	Give the zero-length time period of the
+//!	current time.
+
+TimeofDay now()
+{
+   return Fraction();
+}
+
+//! method Calendar set_timezone(Timezone tz)
+//! method Calendar set_timezone(string|Timezone tz)
+//! method TimeZone timezone()
+//!	Set or get the current timezone (including dst) rule.
+//!	<ref>set_timezone</ref> returns a new calendar object,
+//!	as the called calendar but with another set of rules.
+//!
+//!	Example:
+//!	<pre>
+//!	&gt; Calendar.now();                                      
+//!	Result: Fraction(Fri 2 Jun 2000 18:03:22.010300 CET)
+//!	&gt; Calendar.set_timezone(Calendar.Timezone.UTC)->now();
+//!	Result: Fraction(Fri 2 Jun 2000 16:03:02.323912 UTC)
+//!	</pre>
+
+this_program set_timezone(string|Ruleset.Timezone tz)
+{
+   return set_ruleset(default_rules->set_timezone(tz));
+}
+
+Ruleset.Timezone timezone()
+{
+   return default_rules->timezone;
+}
+
+this_program set_language(string|Ruleset.Language lang)
+{
+   return set_ruleset(default_rules->set_language(lang));
+}
+
+Ruleset.Language language()
+{
+   return default_rules->language;
+}
+
+//! method Calendar set_ruleset(Ruleset r)
+//! method Ruleset ruleset()
+//!	Set or read the ruleset for the calendar.
+//!	<ref>set_ruleset</ref> returns a new calendar object,
+//!	but with the new ruleset.
+
+this_program set_ruleset(Ruleset r)
+{
+   this_program c=object_program(this_object())();
+   c->default_rules=r;
+   return c;
+}
+
+Ruleset ruleset()
+{
+   return default_rules;
+}
diff --git a/lib/modules/Calendar.pmod/TimeRanges.pmod b/lib/modules/Calendar.pmod/TimeRanges.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..f6593c2009d759eea53a51f0642641366bd979eb
--- /dev/null
+++ b/lib/modules/Calendar.pmod/TimeRanges.pmod
@@ -0,0 +1,1222 @@
+//! module Calendar
+
+#define zero int(0..0)
+
+import ".";
+#include "localization.h"
+
+constant CALUNKNOWN=-1000; // not calculated yet
+
+program SuperTimeRange=cSuperTimeRange;
+
+string calendar_name() { return "TimeRanges"; }
+
+object calendar_object=this_object();
+
+string _sprintf(int t) { return (t=='O')?calendar_name():0; }
+
+Ruleset default_rules=Ruleset()
+   ->set_timezone(default_timezone)
+   ->set_language(default_language);
+
+//------------------------------------------------------------------------
+//! class TimeRange
+//! 	This is the base class for any time measurement
+//!	and calendrar information. It defines all the
+//!	things you can do with a time range, any time
+//!	period.
+//!
+//!	A TimeRange doubles as both a fixed period in
+//!	time, and an amount of time. For instance,
+//!	a week plus a day moves the week-period one day
+//!	ahead (unaligning it with the week period, 
+//!	and thereby reducing it to just 7 days),
+//!	no matter when in time the actual day were.
+//!
+//------------------------------------------------------------------------
+
+class TimeRange
+{
+   constant is_timerange=1;
+
+   Ruleset rules;
+
+//! method void create("unix",int unixtime)
+//! method void create("unix",int unixtime,int seconds_len)
+//!	Create the timerange from unix time (as given by
+//!	<tt>time(2)</tt>), with eventually the size of
+//!	the time range in the same unit, seconds.
+//!
+//! method void create("julian",int|float julian_day)
+//!	Create the timerange from a julian day, the 
+//!	standardized method of counting days. If
+//!	the timerange is more then a day, it will 
+//!	at least enclose the day.
+//!
+//! method void create(TimeRange from)
+//!	Create the timerange from another timerange.
+//!
+//!	This is useful when converting objects from
+//!	one calendar to another. Note that the ruleset will be
+//!	transferred to the new object, so this method
+//!	can't be used to convert between timezones 
+//!	or languges - use <ref>set_timezone</ref>,
+//!	<ref>set_language</ref> or <ref>set_ruleset</ref>
+//!	to achieve this.
+//!
+//! note:
+//!	The size of the new object may be inexact;
+//!	a Month object can't comprehend seconds, for instance.
+
+   static void create_unixtime(int unixtime,int len);
+   static void create_unixtime_default(int unixtime);
+   static void create_julian_day(int jd);
+
+   void create(mixed ...args)
+   {
+      if (sizeof(args)) switch (args[0])
+      {
+	 case "unix":
+	    if (sizeof(args)==2)
+	       create_unixtime_default(args[1]);
+	    else if (sizeof(args)>2)
+	       create_unixtime(@args[1..]);
+	    else break;
+	    return;
+	 case "unix_r":
+	    if (sizeof(args)==3)
+	    {
+	       rules=args[2];
+	       create_unixtime_default(args[1]);
+	    }
+	    else if (sizeof(args)>2)
+	    {
+	       rules=args[3];
+	       create_unixtime(args[1],args[2]);
+	    }
+	    else break;
+	    return;
+	 case "julian":
+	    if (sizeof(args)==2)
+	    {
+	       create_julian_day(args[1]);
+	       return;
+	    }
+	    break;
+	 case "julian_r":
+	    if (sizeof(args)==3)
+	    {
+	       rules=args[2];
+	       create_julian_day(args[1]);
+	       return;
+	    }
+	    break;
+
+	 default:
+	    if (objectp(args[0]) && args[0]->is_timerange)
+	    {
+	       convert_from([object(TimeRange)]args[0]);
+	       return;
+	    }
+	    break;
+      }
+
+      error("%O.%O: Illegal parameters %O,%O,%O...\n",
+	    function_object(object_program(this_object())),
+	    object_program(this_object()),
+	    @args,0,0,0);
+   }
+
+   static void convert_from(TimeRange other)
+   {
+// inheriting class must take care of size
+      if (other->julian_day)
+      {
+	 int|float jd=other->julian_day();
+	 if (floatp(jd) && other->unix_time)
+	    create("unix_r",other->unix_time(),other->ruleset());
+	 else
+	    create("julian_r",jd,other->ruleset());
+      }
+      else if (other->unix_time)
+	 create("unix_r",other->unix_time(),other->ruleset());
+      else 
+	 error("Can't convert %O->%s.%O\n",other,
+	       calendar_name(),
+	       object_program(this_object()));
+   }
+
+//! method TimeRange set_size(TimeRange size)
+//! method TimeRange set_size(int n,TimeRange size)
+//!	Gives back a new (or the same, if the size matches) 
+//!	timerange with the new size. 
+//!	If <i>n</i> are given, the resulting size
+//!	will be <i>n</i> amounts of the given size.
+//! note:	
+//!	A negative size is not permitted; a zero one are.
+
+// virtual
+   static TimeRange _set_size(int n,TimeRange x);
+
+   TimeRange set_size(function|TimeRange|int(0..0x7fffffff) a,
+		      void|function|TimeRange b)
+   {
+      function|object(TimeRange) x;
+      int(0..0x7fffffff) n;
+      if (!b) 
+	 if (intp(a)) 
+	    x=[function|object(TimeRange)]this_object(),
+	       n=[int(0..0x7fffffff)]a;
+	 else
+	    x=a,n=1;
+      else
+	 x=b,n=a;
+      if (functionp(x)) x=promote_program(x);
+      if (n<0)
+	 error("Negative size (%d)\n",n);
+      return _set_size(n,[object(TimeRange)]x);
+   }
+
+//! method TimeRange add(int n,void|TimeRange step)
+//!     calculates the (promoted) time period n steps away;
+//!	if no step is given, the step's length is of the
+//!	same length as the called time period.
+//!
+//!	It is not recommended to loop by adding the increment
+//!	time period to a shorter period; this can cause faults,
+//!	if the shorter time period doesn't exist in the incremented 
+//!	period. (Like week 53, day 31 of a month or the leap day of a year.)
+//!
+//!	Recommended use are like this:
+//!	<pre>
+//!	   // loop over the 5th of the next 10 months
+//!	   TimeRange month=Month()+1;
+//!	   TimeRange orig_day=month()->day(5);
+//!	   for (int i=0; i&lt;10; i++)
+//!	   {
+//!	      month++;
+//!	      TimeRange day=month->place(orig_day);
+//!	      <i>...use day...</i>
+//!	   }
+//!	</pre>
+
+// virtual
+   static this_program _add(int n,this_program step);
+
+   this_program add(function|this_program|int a,
+		 void|function|this_program b)
+   {
+      function|object(this_program) x;
+      int n;
+      if (!b) 
+	 if (intp(a)) 
+	    x=[function|object(this_program)]this_object(),
+	       n=[int]a;
+	 else
+	    x=a,n=1;
+      else
+	 x=b,n=a;
+      if (functionp(x)) x=promote_program(x);
+      return _add(n,[object(this_program)]x);
+   }
+
+//! method TimeRange place(TimeRange this)
+//! method TimeRange place(TimeRange this,int(0..1) force)
+//!	This will place the given timerange in this timerange,
+//!	for instance, day 37 in the year - 
+//!	<tt>Year(1934)->place(Day(1948 d37)) => Day(1934 d37)</tt>.
+//!
+//! note:
+//!	The rules how to place things in different timeranges
+//!	can be somewhat 'dwim'.
+
+// virtual
+   TimeRange place(TimeRange what,void|int force);
+
+//! method TimeRange `+(int n)
+//! method TimeRange `+(TimeRange offset)
+//! method TimeRange `-(int m)
+//! method TimeRange `-(TimeRange x)
+//!	This calculates the (promoted) time period 
+//!	either n step away or with a given offset.
+//!	These functions does use <ref>add</ref> to really
+//!	do the job:
+//!	<pre>
+//!	t+n         t->add(n)             t is a time period
+//!	t-n         t->add(-n)            offset is a time period
+//!	t+offset    t->add(1,offset)      n is an integer
+//!	t-offset    t->add(-1,offset)
+//!	n+t         t->add(n)
+//!	n-t         illegal
+//!	offset+t    offset->add(1,t)      | note this!
+//!	offset-t    offset->add(-1,t)     | 
+//!	</pre>
+//!
+//!	Mathematic rules:
+//!	<pre>
+//!	x+(t-x) == t    x is an integer or a time period
+//!	(x+t)-x == t    t is a time period
+//!	(t+x)-x == t
+//!	o-(o-t) == t    o is a time period 
+//!     t++ == t+1
+//!     t-- == t-1
+//!	</pre>
+//!
+//! note:
+//!	a-b does not give the distance between the start of a and b.
+//!	Use the <ref>distance</ref>() function to calculate that.
+//!
+//!	The integer used to `+, `- and add are the <i>number</i>
+//!	of steps the motion will be. It does <i>never</i> represent
+//!	any <i>fixed</i> amount of time, like seconds or days.
+
+   TimeRange `+(program|this_program|int n)
+   {
+      if (objectp(n)) return add(1,n);
+      return add(n);
+   }
+
+   TimeRange ``+(int n)
+   {
+      return add(n);
+   }
+
+   TimeRange `-(TimeRange|program|int n)
+   {
+      if (objectp(n)) return add(-1,n);
+      return add(-n);
+   }
+
+//! method TimeRange `*(int n)
+//!	This changes the amount of time in 
+//!	the time period. <tt>t*17</tt> is
+//!	the same as doing <tt>t-><ref>set_size</ref>(t,17)</tt>.
+
+   function ``* = `*;
+   TimeRange `*(int n)
+   {
+      return set_size(n,this_object());
+   }
+
+//! method array(TimeRange) `/(int n)
+//! method array(TimeRange) split(int n)
+//!	This divides the called timerange into
+//!	n pieces. The returned timerange type
+//!	is not neccesarily of the same type as the called one.
+//!
+//! known bugs:
+//!	These are currently not defined for 
+//!	<ref to=SuperTimeRange>supertimeranges</ref>.
+
+//! method int `/(TimeRange with)
+//! method int how_many(TimeRange with)
+//!	This calculates how many instances of the given
+//!	timerange has passed during the called timerange.
+//!
+//!	For instance, to figure out your age,
+//!	create the timerange of your lifespan, and divide
+//!	with the instance of a <ref to=YMD.Year>Year</ref>.
+
+// virtual
+   array(TimeRange) split(int n);
+
+   int how_many(function|TimeRange with)
+   {
+      if (functionp(with)) with=promote_program(with);
+// default method; not optimized - guessing
+
+      TimeRange start=beginning();
+      TimeRange end=end();
+      
+// find low and high 2^n
+      int nn=16;
+      int low,high;
+
+      TimeRange t=start+with*nn;
+      if (t==end) return nn; // gotcha (luck)
+      if (t>end) // scan less
+      {
+	 for (;;)
+	 {
+	    nn>>=1;
+	    t=start+with*nn;
+	    if (t==end) return nn; // gotcha (luck)
+	    if (t<end) // ok, we're limited
+	    {
+	       low=nn;
+	       high=nn*2-1;
+	       break;
+	    }
+	    if (nn==1) return 0; // can't be less
+	 }
+      }
+      else
+      {
+   // sanity check
+	 TimeRange q=start+with*(nn+1);
+	 if (q==t) error("Result is infinite - argument is zero range\n");
+	 for (;;)
+	 {
+	    nn<<=1;
+	    t=start+with*nn;
+	    if (t==end) return nn; // gotcha (luck)
+	    if (t>end) // ok, we're limited
+	    {
+	       low=(nn>>1);
+	       high=nn-1;
+	       break;
+	    }
+      // loop forever - pike can handle *big* numbers
+	 }
+      }
+
+      for (;;)
+      {
+	 nn=(low+high)/2;
+
+	 t=start+with*nn;
+  	 if (t==end) return nn; 
+	 if (t<end) low=nn+1;
+	 else high=nn-1; 
+
+	 if (low>high) return high; // can't go further
+      }
+   }
+
+   array(TimeRange)|int `/(TimeRange|program|int x)
+   {
+      if (intp(x)) return split(x);
+      else return how_many(x);
+   }
+
+//! method TimeRange beginning()
+//! method TimeRange end()
+//!	This gives back the zero-sized beginning
+//!	or end of the called time period.
+//!
+//!	rule: 
+//!	<tt>range(t->beginning(),t->end())==t</tt>
+
+   TimeRange beginning();
+   TimeRange end();
+
+//! method TimeRange range(TimeRange other)
+//! method TimeRange space(TimeRange other)
+//! method TimeRange distance(TimeRange other)
+//!	Derives different time periods in between
+//!	the called timerange and the parameter timerange.
+//!
+//!     <pre>
+//!    &gt;- the past          the future -&lt;
+//!	|--called--|         |--other--|
+//!     &gt;------------ range -----------&lt;
+//!                &gt;--space--&lt;
+//!     &gt;----- distance -----&lt;
+//!	</pre>
+//!
+//!	See also: add, TimeRanges.range, TimeRanges.space, TimeRanges.distance
+
+// virtual
+   TimeRange distance(TimeRange to);
+
+   TimeRange range(TimeRange with)
+   {
+      return distance(with->end());
+   }
+
+   TimeRange space(TimeRange to)
+   {
+      return end()->distance(to->beginning());
+   }
+
+
+//! method int(0..1) strictly_preceeds(TimeRange what);
+//! method int(0..1) preceeds(TimeRange what);
+//! method int(0..1) is_previous_to(TimeRange what);
+//! method int(0..1) overlaps(TimeRange what);
+//! method int(0..1) contains(TimeRange what);
+//! method int(0..1) equals(TimeRange what);
+//! method int(0..1) is_next_to(TimeRange what);
+//! method int(0..1) succeeds(TimeRange what);
+//! method int(0..1) strictly_succeeds(TimeRange what);
+//!	These methods exists to compare two periods
+//!	of time on the timeline.
+//!
+//! <pre>
+//!           case            predicates 
+//!
+//!  &lt;-- past       future -&gt;
+//!
+//!  |----A----|              A strictly preceeds B,
+//!               |----B----| A preceeds B
+//!
+//!  |----A----|              A strictly preceeds B, A preceeds B, 
+//!            |----B----|    A is previous to B, A touches B
+//!                           
+//!      |----A----|          A preceeds B,
+//!            |----B----|    A overlaps B, A touches B
+//!
+//!      |-------A-------|    A preceeds B, A ends with B
+//!            |----B----|    A overlaps B, A contains B, A touches B,
+//!
+//!      |-------A-------|    A preceeds B,  A succeeds B,
+//!          |---B---|        A overlaps B, A contains B, A touches B
+//!
+//!         |----A----|       A overlaps B, A touches B
+//!         |----B----|       A equals B, A starts with B, A ends with B
+//!
+//!      |-------A-------|    A succeeds B, A starts with B
+//!      |----B----|          A overlaps B, A contains B, A touches B
+//!
+//!            |----A----|    A succeeds B, 
+//!      |----B----|          A overlaps B, A touches B
+//!
+//!            |----A----|    A strictly succeeds B, A succeeds B
+//!  |----B----|              A is next to B, A touches B
+//!
+//!              |----A----|  A strictly succeeds B, 
+//!  |----B----|              A succeeds B
+//!
+//!  </pre>
+
+//- internal method 
+//- returns [-1,0,1] for comparison between
+//- (in order) begin/begin,begin/end,end/begin and end/end
+
+// virtual, default
+   array(int(-1..1)) _compare(TimeRange what)
+   {
+      if (what->is_supertimerange)
+      {
+	 array(int(-1..1)) cmp=what->_compare(this_object());
+
+	 return ({-cmp[0],
+		  -cmp[2],
+		  -cmp[1],
+		  -cmp[3]});
+      }
+      error("_compare: incompatible classes %O <-> %O\n",
+	    object_program(this_object()),object_program(what));
+   }
+
+   string _describe_compare(array(int(-1..1)) c,TimeRange a,TimeRange b)
+   {
+      mapping desc=([-1:"<",0:"=",1:">"]);
+      return sprintf("%O start %s %O start\n"
+		     "%O start %s %O end\n"
+		     "%O end   %s %O start\n"
+		     "%O end   %s %O end\n",
+		     a,desc[c[0]],b,
+		     a,desc[c[1]],b,
+		     a,desc[c[2]],b,
+		     a,desc[c[3]],b);
+   }
+
+#define BEGIN_BEGIN 0
+#define BEGIN_END 1
+#define END_BEGIN 2
+#define END_END 3
+
+   int(0..1) strictly_preceeds(TimeRange what)
+   {
+      array(int(-1..1)) a=_compare(what);
+      return a[END_BEGIN]<0;
+   }
+
+   int(0..1) preceeds(TimeRange what)
+   {
+      array(int(-1..1)) a=_compare(what);
+      return a[BEGIN_BEGIN]<0;
+   }
+
+   int(0..1) is_previous_to(TimeRange what)
+   {
+      array(int(-1..1)) a=_compare(what);
+      return a[END_BEGIN]==0;
+   }
+
+   int(0..1) overlaps(TimeRange what)
+   {
+      array(int(-1..1)) a=_compare(what);
+      return (a[END_BEGIN]>0 && a[BEGIN_END]<0);
+   }
+
+   int(0..1) contains(TimeRange what)
+   {
+      array(int(-1..1)) a=_compare(what);
+      return a[BEGIN_BEGIN]<=0 && a[END_END]>=0;
+   }
+
+   int(0..1) equals(TimeRange what)
+   {
+      if (!objectp(what)) return 0;
+      array(int(-1..1)) a=_compare(what);
+      return a[BEGIN_BEGIN]==0 && a[END_END]==0;
+   }
+
+   int(0..1) is_next_to(TimeRange what)
+   {
+      array(int(-1..1)) a=_compare(what);
+      return a[END_BEGIN]==0;
+   }
+
+   int(0..1) succeeds(TimeRange what)
+   {
+      array(int(-1..1)) a=_compare(what);
+      return a[END_END]>0;
+   }
+
+   int(0..1) strictly_succeeds(TimeRange what)
+   {
+      array(int(-1..1)) a=_compare(what);
+      return a[BEGIN_END]>0;
+   }
+
+   int(0..1) touches(TimeRange what)
+   {
+      array(int(-1..1)) a=_compare(what);
+      return 
+	 (a[BEGIN_END]<=0 && a[END_END]>=0) ||
+	 (a[END_BEGIN]>=0 && a[BEGIN_BEGIN]<=0);
+   }
+
+   int (0..1) starts_with(TimeRange what)
+   {
+      array(int(-1..1)) a=_compare(what);
+      return !a[BEGIN_BEGIN];
+   }
+
+   int (0..1) ends_with(TimeRange what)
+   {
+      array(int(-1..1)) a=_compare(what);
+      return !a[END_END];
+   }
+
+//! method int(0..1) `<(TimeRange compared_to)
+//! method int(0..1) `>(TimeRange compared_to)
+//!	These operators sorts roughty on the 
+//!	periods place in time. The major use
+//!	might be to get multiset to work, 
+//!	besides sorting events clearly defined in time.
+
+   int(0..1) `<(TimeRange compared_to)
+   {
+      array(int(-1..1)) a=_compare(compared_to);
+      if (a[0]<0) return 1;
+      if (a[0]>0) return 0;
+      if (a[3]<0) return 1;
+      return 0;
+   }
+
+   int(0..1) `>(TimeRange compared_to)
+   {
+      array(int(-1..1)) a=_compare(compared_to);
+      if (a[0]>0) return 1;
+      if (a[0]<0) return 0;
+      if (a[3]>0) return 1;
+      return 0;
+   }
+
+//! method int(0..1) `==(TimeRange compared_to)
+//! method int(0..1) _equal(TimeRange compared_to)
+//!	These two overloads the operator <tt>`==</tt> and
+//!	the result of the <tt>equal</tt> function.
+//!
+//!	a<tt>==</tt>b is considered true if the two
+//!	timeranges are of the same type, have the same rules
+//!	(language, timezone, etc) and are the same timerange.
+//!
+//!	<tt>equal(</tt>a<tt>,</tt>b<tt>)</tt> are considered
+//!	true if a and b are the same timerange, exactly the same
+//!	as the <ref>equals</ref> method.
+//!
+//!	The <tt>__hash</tt> method is also present, 
+//!	to make timeranges possible to use as keys in mappings.
+//!
+//! known bugs:
+//!	_equal is not currently possible to overload,
+//!	due to wierd bugs, so equal uses `== for now.
+
+   int(0..1) `==(TimeRange what) 
+   { 
+      return object_program(what)==object_program(this_object()) &&
+	 what->ruleset()==ruleset() &&
+	 equals(what); 
+   }
+
+   int __hash();
+
+//     int(0..1) _equal(TimeRange what) 
+//     { 
+//        return equals(what);
+//     }
+
+//! method TimeRange `&(TimeRange with)
+//!	Gives the cut on the called time period
+//!	with another time period. The result is
+//!	zero if the two periods doesn't overlap.
+//!     <pre>
+//!    &gt;- the past          the future -&lt;
+//!	|-------called-------|         
+//!	     |-------other--------|
+//!          &gt;----- cut -----&lt;
+//!	</pre>
+
+   function ``& = `&;
+   TimeRange|zero `&(TimeRange with, mixed ...extra)
+   {
+      if (with->is_nulltimerange) 
+	 return with;
+      array(int(-1..1)) a=_compare(with);
+      if (a[END_BEGIN]<0 || a[BEGIN_END]>0) 
+	 return nulltimerange; // no overlap, no extra
+
+      if (with->is_supertimerange)
+	 return predef::`&(with,this_object(),@extra); // let it handle that...
+
+      TimeRange from,to;
+
+// from the last beginning
+      if (a[BEGIN_BEGIN]>0) from=beginning(); else from=with->beginning();
+
+// to the first end
+      if (a[END_END]<0) to=end(); else to=with->end();
+
+// compute
+      TimeRange res=from->distance(to);
+      if (sizeof(extra)) return predef::`&(res,@extra);
+      return res;
+   }
+
+//! method TimeRange `|(TimeRange with)
+//!	Gives the union on the called time period
+//!	and another time period.
+//!     <pre>
+//!    &gt;- the past          the future -&lt;
+//!	|-------called-------|         
+//!	     |-------other--------|
+//!     &lt;----------union----------&gt;
+//!	</pre>
+
+   function ``| = `|;
+   TimeRange `|(TimeRange with,mixed ...extra)
+   {
+      if (with->is_nulltimerange) 
+	 return sizeof(extra)?`|(@extra):this_object();
+      array(int(-1..1)) a=_compare(with);
+      TimeRange from,to;
+
+      if (a[END_BEGIN]<0 || a[BEGIN_END]>0)
+	 from=SuperTimeRange( sort(({this_object(),with})) ); // no overlap
+      else
+      {
+	 if (with->is_supertimerange)   // let it handle that...
+	    return predef::`|(with,this_object(),@extra);
+
+   // from the first beginning
+	 if (a[BEGIN_BEGIN]<0) from=this_object(); else from=with;
+
+   // to the last end
+	 if (a[END_END]>0) to=this_object(); else to=with;
+   // compute
+	 from=from->range(to);
+      }
+      if (sizeof(extra)) return predef::`|(from,@extra);
+      return from;
+   }
+
+//! method TimeRange `^(TimeRange with)
+//!	Gives the exclusive-or on the called time period
+//!	and another time period, ie the union without
+//!	the cut. The result is zero if the 
+//!	two periods were the same.
+//!     <pre>
+//!    &gt;- the past          the future -&lt;
+//!	|-------called-------|         
+//!	     |-------other--------|
+//!     &lt;----|               |---->   - exclusive or
+//!	</pre>
+
+   function ``^ = `^;
+   TimeRange `^(TimeRange with,mixed ... extra)
+   {
+      if (with->is_supertimerange)
+	 return `^(with,this_object(),@extra); // let it handle that...
+      if (with->is_nulltimerange) 
+	 return sizeof(extra)?`^(@extra):this_object();
+
+      TimeRange res;
+
+      array(int(-1..1)) a=_compare(with);
+      
+//        write(_describe_compare(a,this_object(),with));
+
+      TimeRange first,second;
+      if (a[END_BEGIN]<0 || a[BEGIN_END]>0)
+	 res=SuperTimeRange( sort(({this_object(),with})) ); // no overlap
+      else if (a[BEGIN_END]==0 || a[END_BEGIN]==0) // bordering
+	 if (a[BEGIN_BEGIN]<0)
+	    res=range(with); // A precedes B
+	 else
+	    res=with->range(this_object()); // B precedes A
+      else if (a[BEGIN_BEGIN]==0 && a[END_END]==0)
+	 return sizeof(extra)?predef::`^(nulltimerange,@extra):nulltimerange;
+      else
+      {
+   // from the first beginning to the second beginning
+	 if (a[BEGIN_BEGIN]<0) 
+	    first=distance(with); 
+	 else 
+	    first=with->distance(this_object());
+
+// and from the first end to the last end
+	 if (a[END_END]<0) 
+	    second=end()->range(with); 
+	 else 
+	    second=with->end()->range(this_object());
+	 res=first|second;
+      }
+   // done
+      if (sizeof(extra)) return `^(res,@extra);
+      return res;
+   }
+
+//! method TimeRange subtract(TimeRange what)
+//!	This subtracts a period of time from another;
+//!     <pre>
+//!     &gt;- the past          the future -&lt;
+//!	|-------called-------|         
+//!	     |-------other--------|
+//!     &lt;----&gt;  &lt;- called-&gt;subtract(other)
+//!
+//!	|-------called-------|         
+//!	     |---third---|
+//!     &lt;----&gt;           &lt;---> &lt;- called->subtract(third)
+//!	</pre>
+
+   TimeRange subtract(TimeRange what,mixed ... extra)
+   {
+      array(int(-1..1)) a=_compare(what);
+
+      if (a[END_BEGIN]<=0 || a[BEGIN_END]>=0)
+	 return sizeof(extra)?subtract(@extra):this_object(); // no overlap
+
+      if (what->is_supertimerange)
+      {
+	 array res=map(what->parts+extra,subtract)-({nulltimerange});
+	 switch (sizeof(res))
+	 {
+	    case 0: return nulltimerange;
+	    case 1: return res[0];
+	    default: return predef::`&(@res);
+	 }
+      }
+
+      TimeRange res;
+
+//        write(_describe_compare(a,this_object(),what));
+
+      if (a[BEGIN_BEGIN]>=0)      // it preceeds us
+	 if (a[END_END]<=0) 
+	    return nulltimerange; // full overlap
+	 else                     // half overlap at start
+	    res=what->end()->range(this_object());
+      else if (a[END_END]<=0)     // it succeeds us
+	 res=distance(what);
+      else 
+      {
+//  	 werror("%O..\n..%O\n%O..\n..%O\n",
+//  		beginning(),what->beginning(),
+//  		what->end(),end());
+// it's inside us
+	 res=predef::`|(distance(what),
+			what->end()->range(this_object()));
+      }
+      if (sizeof(extra)) return res->subtract(@extra);
+      return res;
+   }
+
+//! method TimeRange set_ruleset(Ruleset r)
+//! method TimeRange ruleset(Ruleset r)
+//!	Set or get the current ruleset.
+//! note: 
+//!	this may include timezone shanges,
+//!	and change the time of day.
+
+   TimeRange set_ruleset(Ruleset r);
+   Ruleset ruleset()
+   {
+      return rules;
+   }
+
+//! method TimeRange set_timezone(Timezone tz)
+//! method TimeRange set_timezone(string tz)
+//! method TimeZone timezone()
+//!	Set or get the current timezone (including dst) rule.
+//!
+//! note: 
+//!	The time-of-day may very well
+//!	change when you change timezone.
+//!
+//!	To get the time of day for a specified timezone,
+//!	select the timezone before getting the time of day:
+//!
+//!	<tt>Year(2003)-&gt;...-&gt;set_timezone(TimeZone.CET)-&gt;...-&gt;hour(14)-&gt;...</tt>
+//!
+
+   TimeRange set_timezone(string|Ruleset.Timezone tz)
+   {
+      return set_ruleset(rules->set_timezone(tz));
+   }
+
+   Ruleset.Timezone timezone()
+   {
+      return rules->timezone;
+   }
+
+//! method TimeRange set_language(Language lang)
+//! method TimeRange set_language(string lang)
+//! method Language language()
+//!	Set or get the current language rule.
+
+   TimeRange set_language(string|Ruleset.Language lang)
+   {
+      return set_ruleset(rules->set_language(lang));
+   }
+
+   Ruleset.Language language()
+   {
+      return rules->language;
+   }
+
+//! method Calendar calendar()
+//!	Simply gives back the calendar in use, for instance
+//!	Calendar.ISO or Calendar.Discordian.
+
+   object calendar()
+   {
+      return calendar_object;
+   }
+}
+
+// ----------------------------------------------------------------
+
+//!
+//! module Calendar
+//! class SuperTimeRange
+//!     This class handles the cases where you have a time
+//!	period with holes. These can be created by the
+//!	<tt>^</tt> or <tt>|</tt> operators on time ranges.
+//! inherits TimeRange
+
+class cSuperTimeRange
+{
+   inherit TimeRange;
+
+   constant is_supertimerange=1;
+
+   array parts;
+
+//! method void create(array(TimeRange) parts)
+//!	A SuperTimeRange must have at least two parts,
+//!	two time ranges. Otherwise, it's either not
+//!	a time period at all or a normal time period.
+
+   void create(array(TimeRange) _parts)
+   {
+      if (sizeof(_parts->is_supertimerange-({0})))
+	 error("one part is super\n%O\n",_parts);
+      if (sizeof(_parts)<2)
+	 error("SuperTimeRange: Too few time periods to constructor\n");
+      parts=_parts;
+   }
+
+   TimeRange beginning()
+   {
+      return parts[0]->beginning();
+   }
+
+   TimeRange end()
+   {
+      return parts[-1]->end();
+   }
+
+   TimeRange distance(TimeRange to)
+   {
+      return beginning()->distance(to);
+   }
+
+   TimeRange mend_overlap(array parts)
+   {
+      switch (sizeof(parts))
+      {
+	 case 0: return nulltimerange;
+	 case 1: return parts[0];
+      }
+      array res=({});
+      TimeRange last=parts[0];
+      foreach (parts[1..],TimeRange part)
+      {
+	 if (last->strictly_preceeds(part))
+	 {
+	    res+=({last});
+	    last=part;
+	 }
+	 else
+	    last=last|part;
+      }
+      if (!sizeof(res)) return last;
+      return SuperTimeRange(res+({last}));
+   }
+
+   TimeRange `&(TimeRange with,mixed... extra)
+   {
+      array r=({});
+      foreach (parts,TimeRange part)
+      {
+	 TimeRange tmp=predef::`&(part,with,@extra);
+	 if (tmp)
+	    if (tmp->is_supertimerange) r+=tmp->parts;
+	    else if (!tmp->is_nulltimerange) r+=({tmp});
+      }
+      switch (sizeof(r))
+      {
+	 case 0: return nulltimerange;
+	 case 1: return r[0]; 
+	 default: return SuperTimeRange(r); 
+      }
+   }
+
+   TimeRange `|(TimeRange with,mixed ...extra)
+   {
+      TimeRange res;
+      if (with->is_supertimerange)
+	 res=mend_overlap(sort(with->parts+parts));
+      else if (with->is_nulltimerange)
+	 return this_object();
+      else
+	 res=mend_overlap(sort( ({with})+parts ));
+      if (sizeof(extra)) 
+	 return predef::`|(res,@extra);
+      return res;
+   }
+
+   TimeRange subtract(TimeRange with,mixed ...extra)
+   {
+      array r=({});
+      foreach (parts,TimeRange part)
+	 r+=({part->subtract(part,with,@extra)});
+      return predef::`|(@r);
+   }
+
+   TimeRange `^(TimeRange with,mixed ...extra)
+   {
+//        werror("1 %O\n",with);
+//        werror("2 %O\n",`|(with));
+//        werror("3 %O\n",`&(with));
+      TimeRange r=`|(with)->subtract(`&(with));
+      if (sizeof(extra)) return predef::`^(r,@extra);
+      return r;
+   }
+
+// == checks if equal 
+
+   int `==(TimeRange with,mixed ...extra)
+   {
+      if (!with->is_supertimerange)
+	 return 0; // it has to be
+      if (sizeof(parts)!=sizeof(with->parts))
+	 return 0; // it has to be
+      for (int i=0; i<sizeof(parts); i++)
+	 if (parts[i]!=with->parts[i]) return 0;
+      return sizeof(extra)?predef::`==(with,@extra):1;
+   }
+
+// _compare wrapper
+   array(int(-1..1)) _compare(TimeRange what)
+   {
+      array(int(-1..1)) a,b;
+      a=parts[0]->_compare(what);
+      b=parts[-1]->_compare(what);
+      return ({a[0],a[1],b[2],b[3]});
+   }
+
+// `< and `> sort for multiset
+// a little bit heavier for super-time-ranges
+
+   int(0..1) `<(TimeRange with)
+   {
+      array(int(-1..1)) a=_compare(with);
+      if (a[0]<0) return 1;
+      if (a[0]>0) return 0;
+      if (a[3]<0) return 1;
+      if (a[3]>0) return 0;
+      if (!with->is_supertimerange) return 1; // always
+      if (sizeof(parts)>sizeof(with->parts)) return 1; 
+      if (sizeof(parts)<sizeof(with->parts)) return 0; 
+      for (int i=0; i<sizeof(parts); i++)
+	 if (parts[i]<with->parts[i]) return 1;
+      return 0;
+   }
+
+   int(0..1) `>(TimeRange with)
+   {
+      array(int(-1..1)) a=_compare(with);
+      if (a[0]>0) return 1;
+      if (a[0]<0) return 0;
+      if (a[3]>0) return 1;
+      if (a[3]<0) return 0;
+      if (!with->is_supertimerange) return 0; // always
+      if (sizeof(parts)<sizeof(with->parts)) return 1; 
+      if (sizeof(parts)>sizeof(with->parts)) return 0; 
+      for (int i=0; i<sizeof(parts); i++)
+	 if (parts[i]>with->parts[i]) return 1;
+      return 0;
+   }
+
+   int __hash()
+   {
+      return predef::`+(@map(parts,"__hash"));
+   }
+
+   string _sprintf(int t)
+   {
+      switch (t)
+      {
+	 case 'O':
+	    return "SuperTimeRange("+
+	       map(parts,"_sprintf",'O')*", "+")";
+      }
+      return 0;
+   }
+
+   TimeRange set_timezone(string|Timezone tz)
+   {
+// fixme?
+      return `|(map(parts,"set_timezone",tz));
+   }
+}
+
+//! constant TimeRange nulltimerange
+//!	This represents the null time range, 
+//!	which, to differ from the zero time range
+//!	(the zero-length time range), isn't placed
+//!	in time. This is the result of for instance
+//!	<ref>`&</ref> between two strict non-overlapping
+//!	timeranges - no time at all.
+//!
+//! 	It has a constant, <tt>is_nulltimerange</tt>, which
+//!	is non-zero. <tt>`!</tt> on this timerange is true.
+
+
+static class NullTimeRange
+{
+   inherit TimeRange;
+
+   constant is_nulltimerange=1;
+
+// overload
+   void create()
+   {
+   }
+
+   TimeRange set_size(TimeRange|int(0..0x7fffffff) a,void|TimeRange b)
+   {
+      return this_object();
+   }
+
+   TimeRange place(TimeRange what,void|int force)
+   {
+      return this_object();
+   }
+
+   array(TimeRange) split(int n)
+   {
+      return allocate(n,this_object());
+   }
+
+   TimeRange beginning() { return this_object(); }
+   TimeRange end() { return this_object(); }
+
+   TimeRange distance(TimeRange to)
+   {
+      if (to==this_object()) return this_object();
+      error("Can't distance/space/range with the null timerange\n");
+   }
+
+   array(int(-1..1)) _compare(TimeRange with)
+   {
+      if (with==this_object()) return ({0,0,0,0});
+      return ({-1,-1,-1,-1});
+   }
+
+   int(0..1) `<(TimeRange with)
+   {
+      return !(with==this_object());
+   }
+
+   int(0..1) `>(TimeRange with)
+   {
+      return 0;
+   }
+
+   int(0..1) `==(TimeRange with)
+   {
+      return with==this_object();
+   }
+
+   int(0..1) equals(TimeRange with)
+   {
+      return with==this_object();
+   }
+
+   TimeRange `&(TimeRange with, mixed ...extra)
+   {
+      return predef::`&(with,this_object(),@extra);
+   }
+
+   TimeRange `|(TimeRange with, mixed ...extra)
+   {
+      return predef::`|(with,this_object(),@extra);
+   }
+
+   TimeRange `^(TimeRange with, mixed ...extra)
+   {
+      return predef::`^(with,this_object(),@extra);
+   }
+
+   this_program subtract(TimeRange with, mixed ...extra)
+   {
+      return this_object();
+   }
+
+   int(1..1) `!()
+   {
+      return 1;
+   }
+
+   string _sprintf(int t)
+   {
+      switch (t)
+      {
+	 case 'O': return "NullTimeRange";
+	 default: return 0;
+      }
+   }
+}
+
+NullTimeRange nulltimerange=NullTimeRange();
+
+// helper functions
+
+static mapping(function:TimeRange) program2stuff=([]);
+
+static TimeRange promote_program(function p)
+{
+   TimeRange x;
+   if ( (x=program2stuff[p]) ) return x;
+   x=[object(TimeRange)]p();
+   if (!x->is_timerange)
+      error("Not a timerange program: %O\n",p);
+   return program2stuff[p]=x;
+}
diff --git a/lib/modules/Calendar.pmod/Timezone.pmod b/lib/modules/Calendar.pmod/Timezone.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..e04da785723257b8a45fb71b7ebc40209d4c07ea
--- /dev/null
+++ b/lib/modules/Calendar.pmod/Timezone.pmod
@@ -0,0 +1,244 @@
+//! module Calendar
+//! submodule Timezone
+//!
+//! 	This module contains all the predefined timezones. 	
+//!	Index it with whatever timezone you want to use.
+//!
+//!	Example:
+//!	<tt>Calendar.Calendar my_cal=
+//!	    Calendar.ISO->set_timezone(Calendar.Timezone["Europe/Stockholm"]);
+//!	</tt>
+//!
+//!	A simpler way of selecting timezones might be 
+//!	to just give the string to
+//!	<ref to=Ruleset.set_timezone>set_timezone</ref>;
+//!	<ref to=Ruleset.set_timezone>it</ref> indexes by itself:
+//!
+//!	<tt>Calendar.Calendar my_cal=
+//!	    Calendar.ISO->set_timezone("Europe/Stockholm");
+//!	</tt>
+//!
+//! note
+//!	Do not confuse this module with <ref>Ruleset.Timezone</ref>,
+//!	which is the base class of a timezone object.
+//!
+//!	<tt>"CET"</tt> and some other standard abbreviations work too,
+//!	but not all of them (due to more then one country using them).
+//!
+//!	Do not call <ref to=Calendar.Time.set_timezone>set_timezone</ref>
+//!	too often, but remember the result if possible. It might take
+//!	some time to initialize a timezone object.
+//!
+//!	There are about 504 timezones with 127 different daylight
+//!	saving rules. Most of them historic.
+//!
+//!	The timezone information comes from 
+//!	<a href=ftp://elsie.nci.nih.gov/pub/>ftp://elsie.nci.nih.gov/pub/</a>
+//!	and are not made up from scratch. Timezone bugs may be reported
+//!	to the timezone mailing list, 
+//!	<a href=mailto:tz@elsie.nci.nih.gov>tz@elsie.nci.nih.gov</a>,
+//!	preferable with a <tt>cc</tt> to 
+//!	<a href=mailto:mirar@mirar.org>mirar@mirar.org</a>. /Mirar
+//!
+//! see also: TZnames, Ruleset.Timezone
+
+//! constant Ruleset.Timezone locale
+//!	This contains the local timezone, found from
+//!	various parts of the system, if possible.
+
+//! constant Ruleset.Timezone localtime
+//!	This is a special timezone, that uses <ref>localtime</ref>()
+//!	and <ref>tzname</ref>
+//!	to find out what current offset and timezone string to use.
+//!	
+//!	<ref>locale</ref> uses this if there is no other
+//!	way of finding a better timezone to use.
+//!
+//!	This timezone is limited by <ref>localtime</ref> and 
+//!	libc to the range of <tt>time_t</tt>, 
+//!	which is a MAXINT on most systems - 13 Dec 1901 20:45:52
+//!	to 19 Jan 2038 3:14:07, UTC.
+
+//! module Calendar
+//! submodule TZnames
+//!	This module is a mapping of the names of 
+//!	all the geographical (political) 
+//!	based timezones. It looks mainly like
+//!	<pre>
+//!	(["Europe":({"Stockholm","Paris",...}),
+//!       "America":({"Chicago","Panama",...}),
+//!	  ...
+//!     ])
+//!     </pre>
+//!
+//!	It is mainly there for easy and reliable ways
+//!	of making user interfaces to select timezone.
+//!
+//!	The Posix and standard timezones (like CET, PST8PDT, etc)
+//!	are not listed.
+
+
+import ".";
+
+// ----------------------------------------------------------------
+
+static class TZHistory
+{
+   constant is_timezone=1;
+   constant is_dst_timezone=1;
+
+// figure out what timezone to use
+   Ruleset.Timezone whatrule(int ux);
+
+   string name=sprintf("%O",object_program(this_object()));
+
+   array(int) tz_ux(int ux)
+   {
+//        werror("tz_ux %O\n",ux);
+//        object z=whatrule(ux);
+//        werror("%O %O\n",z->offset_to_utc,z->name);
+//        return z->tz_ux(ux);
+      return whatrule(ux)->tz_ux(ux);
+   }
+
+   array(int) tz_jd(int jd)
+   {
+//        werror("tz_jd %O\n",jd);
+//        object z=whatrule((jd-2440588)*86400-86400/2);
+//        werror("%O %O\n",z->offset_to_utc,z->name);
+//        return z->tz_jd(jd);
+      return whatrule((jd-2440588)*86400-86400/2)->tz_jd(jd);
+   }
+
+   string _sprintf(int t) { return (t=='O')?"Timezone("+name+")":0; }
+   
+   int raw_utc_offset();
+}
+
+#include "TZs.h";
+
+// ----------------------------------------------------------------
+// from the system
+
+Ruleset.Timezone locale=_locale();
+
+static function _locale()
+{
+   Ruleset.Timezone tz;
+
+// try to get the real local time settings
+
+#if 1
+   string s;
+
+   if ( (s=getenv("TZ")) )
+   {
+      tz=`[](s);
+      if (tz) return tz;
+   }
+
+// Linux RedHat
+   if ( (s=Stdio.read_bytes("/etc/sysconfig/clock")) )
+   {
+      sscanf(s,"%*sZONE=\"%s\"",s);
+      tz=`[](s);
+//        werror("=>%O\n",tz);
+      if (tz) return tz;
+   }
+
+#if constant(tzname)
+   mapping l=predef::localtime(time()); 
+   array(string) tzn=tzname();
+
+   tz=::`[](tzn[0]);
+   if (tz && l->timezone==tz->raw_utc_offset()) return tz;
+#endif
+#endif
+
+   return localtime(); // default - use localtime
+};
+
+class localtime
+{
+   constant is_timezone=1;
+   constant is_dst_timezone=1;
+
+#if constant(tzname)
+   static array(string) names=tzname();
+#endif
+
+   string name="local";
+
+// is (midnight) this julian day dst?
+   array tz_jd(int jd)
+   {
+      return tz_ux((jd-2440588)*86400);
+   }
+
+// is this unixtime (utc) dst?
+   array tz_ux(int ux)
+   {
+      if (ux<-0x80000000 || ux>0x7fffffff)
+	 error("Time is out of range for Timezone.localtime()\n");
+
+      int z0=ux%86400;
+      mapping ll=predef::localtime(ux);
+      int zl=ll->hour*3600+ll->min*60+ll->sec;
+      int tz=z0-zl;
+      if (tz>86400/2) tz-=86400;
+      else if (tz<-86400/2) tz+=86400;
+#if constant(tzname)
+      return ({tz,names[ll->isdst]});
+#else
+      return ({tz,"local"});
+#endif
+   }
+
+   string _sprintf(int t) { return (t=='O')?"Timezone.localtime()":0; }
+
+   int raw_utc_offset(); // N/A but needed for interface
+}
+
+// ----------------------------------------------------------------
+// magic timezones
+
+static private Ruleset.Timezone _make_new_timezone(string tz,float plusminus)
+{
+   object(Ruleset.Timezone) z=`[](tz);
+   if (!z) return ([])[0];
+   if (plusminus>14.0 || plusminus<-14.0)
+      error("difference out of range -14..14 h\n");
+   if (plusminus==0.0)
+      return z;
+   return 
+      object_program(z)(z->offset_to_utc-((int)(3600*plusminus)),
+			sprintf("%s%+g",z->name||"",plusminus));
+}
+
+static private constant _military_tz=
+([ "Y":"UTC-12", "X":"UTC-11", "W":"UTC-10", "V":"UTC-9", "U":"UTC-8", 
+   "T":"UTC-7", "S":"UTC-6", "R":"UTC-5", "Q":"UTC-4", "P":"UTC-3", 
+   "O":"UTC-2", "N":"UTC-1", "Z":"UTC", "A":"UTC+1", "B":"UTC+2", 
+   "C":"UTC+3", "D":"UTC+4", "E":"UTC+5", "F":"UTC+6", "G":"UTC+7", 
+   "H":"UTC+8", "I":"UTC+9", "K":"UTC+10", "L":"UTC+11", "M":"UTC+12",
+   "J":"locale" ]);
+
+static private Ruleset.Timezone _magic_timezone(string tz)
+{
+   float d;
+   string z;
+   if (sscanf(tz,"%s+%f",z,d)==2)
+      return _make_new_timezone(z,d);
+   if (sscanf(tz,"%s-%f",z,d)==2)
+      return _make_new_timezone(z,-d);
+   if ((z=_military_tz[tz])) return `[](z);
+   return ::`[](replace(tz,"-/+"/1,"__p"/1));
+}
+
+Ruleset.Timezone `[](string tz)
+{
+   mixed p=::`[](tz);
+   if (!p) p=_magic_timezone(tz);
+   if (programp(p) || functionp(p)) return p();
+   return p;
+}
diff --git a/lib/modules/Calendar.pmod/YMD.pmod b/lib/modules/Calendar.pmod/YMD.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..ca9bbd0c0dc246036353263bdbd74c08bc1bd0fe
--- /dev/null
+++ b/lib/modules/Calendar.pmod/YMD.pmod
@@ -0,0 +1,2631 @@
+//!
+//! module Calendar
+//! submodule YMD
+//!
+//! base for all Roman-kind of Calendars,
+//! ie, one with years, months, weeks and days
+//!
+
+//  #pragma strict_types
+
+import ".";
+inherit Time:Time;
+
+#define this this_object()
+
+// ----------------
+// virtual methods to tell how this calendar works
+// ----------------
+
+static array(int) year_from_julian_day(int jd);
+static int julian_day_from_year(int year);
+static int year_remaining_days(int y,int yday);
+
+static array(int) year_month_from_month(int y,int m); // [y,m,ndays,myd]
+static int month_from_yday(int y,int yday);
+
+static array(int) week_from_week(int y,int w);   // [y,w,wd,ndays,wjd]
+static array(int) week_from_julian_day(int jd);  // [y,w,wd,ndays,wjd]
+
+static string f_month_name_from_number;
+static string f_month_shortname_from_number;
+static string f_month_number_from_name;
+static string f_month_day_name_from_number;
+static string f_week_name_from_number;
+static string f_week_day_number_from_name;
+static string f_week_day_shortname_from_number;
+static string f_week_day_name_from_number;
+static string f_year_name_from_number;
+static string f_year_number_from_name;
+
+
+static int(0..1) year_leap_year(int y);
+
+static int compat_week_day(int n);
+
+//------------------------------------------------------------------------
+//! class YMD
+//! 	Base (virtual) time period of the Roman-kind of calendar.
+//! inherits TimeRange
+//------------------------------------------------------------------------
+
+class YMD
+{
+   inherit TimeRange;
+
+// --- generic for all YMD:
+
+   int y;   // year
+   int yjd; // julian day of the first day of the year
+
+   int n;   // number of this in the period
+
+   int jd;  // julian day of first day
+   int yd;  // day of year (1..)
+   int m;   // [*] month of year (1..12?), like
+   int md;  // [*] day of month (1..)
+   int wy;  // [*] week year
+   int w;   // [*] week of week year (1..) 
+   int wd;  // [*] day of week (1..7?)
+
+   int mnd=CALUNKNOWN;  // days in current month
+   int utco=CALUNKNOWN; // [*] distance to UTC
+   string tzn=0;        // timezone name
+
+//          // ^^^ might be uninitialized (CALUNKNOWN)
+
+   Ruleset rules;
+   constant is_ymd=1;
+
+// ----------------------------------------
+// basic Y-M-D stuff
+// ----------------------------------------
+
+   void create_now()
+   {
+      rules=default_rules;
+      create_unixtime_default(time());
+   }
+
+   void create_unixtime_default(int unixtime)
+   {
+// 1970-01-01 is julian day 2440588
+      create_julian_day( 2440588+unixtime/86400 ); 
+// we can't reuse this; it might not be start of day
+      [int mutco,string mtzn]=rules->timezone->tz_ux(unixtime);
+      int uxo=unixtime%86400-mutco;
+      if (uxo<0)
+	 create_julian_day( 2440588+unixtime/86400-1 ); 
+      else if (uxo>=86400)
+	 create_julian_day( 2440588+unixtime/86400+1 ); 
+      else if (uxo==0)
+	 utco=mutco,tzn=mtzn; // reuse, it *is* start of day
+   }
+
+   void make_month() // set m and md from y and yd
+   {
+      int myd;
+      [m,md,mnd,myd]=month_from_yday(y,yd);
+   }
+
+   void make_week() // set w from y and yd
+   {
+      int wnd,wjd;
+      [wy,w,wd,wnd,wjd]=week_from_julian_day(jd);
+   }
+
+   int __hash() { return jd; }
+
+// --- query
+
+//! method float fraction_no()
+//! method int hour_no()
+//! method int julian_day()
+//! method int leap_year()
+//! method int minute_no()
+//! method int month_day()
+//! method int month_no()
+//! method int second_no()
+//! method int unix_time()
+//! method int utc_offset()
+//! method int week_day()
+//! method int week_no()
+//! method int year_day()
+//! method int year_no()
+//! method string month_name()
+//! method string month_shortname()
+//! method string month_day_name()
+//! method string week_day_name()
+//! method string week_day_shortname()
+//! method string week_name()
+//! method string year_name()
+//! method string tzname()
+//! method string tzname_iso()
+
+   int julian_day()
+   {
+      return jd;
+   }
+
+   int unix_time()
+   {
+// 1970-01-01 is julian day 2440588
+      int ux=(jd-2440588)*86400;
+      if (utco==CALUNKNOWN) 
+	 [utco,tzn]=rules->timezone->tz_jd(jd);
+      return ux+utco;
+   }
+
+   int utc_offset()
+   {
+      if (utco==CALUNKNOWN) 
+	 [utco,tzn]=rules->timezone->tz_jd(jd);
+      return utco;
+   }
+
+   string tzname()
+   {
+      if (!tzn)
+	 [utco,tzn]=rules->timezone->tz_jd(jd);
+      return tzn;
+   }
+
+   string tzname_iso()
+   {
+      int u=utc_offset();
+      if (!(u%3600))
+	 return sprintf("UTC%+d",-u/3600);
+      if (!(u%60))
+	 return 
+	    (u<0)
+	    ?sprintf("UTC+%d:%02d",-u/3600,(-u/60)%60)
+	    :sprintf("UTC-%d:%02d",u/3600,(u/60)%60);
+      return 
+	 (u<0)
+	 ?sprintf("UTC+%d:%02d:%02d",-u/3600,(-u/60)%60,(-u)%60)
+	 :sprintf("UTC-%d:%02d:%02d",u/3600,(u/60)%60,u%60);
+   }
+
+   int year_no()
+   {
+      return y>0?y:-1+y;
+   }
+
+   int month_no()
+   {
+      if (m==CALUNKNOWN) make_month();
+      return m;
+   }
+
+   int week_no()
+   {
+      if (w==CALUNKNOWN) make_week();
+      return w;
+   }
+
+   int month_day()
+   {
+      if (md==CALUNKNOWN) make_month();
+      return md;
+   }
+
+   int week_day()
+   {
+      if (wd==CALUNKNOWN) make_week();
+      return wd;
+   }
+
+   int year_day()
+   {
+      return yd;
+   }
+
+   string year_name()
+   {
+      return rules->language[f_year_name_from_number](y);
+   }
+
+   string week_name()
+   {
+      if (w==CALUNKNOWN) make_week();
+      return rules->language[f_week_name_from_number](w);
+   }
+
+   string month_name()
+   {
+      if (m==CALUNKNOWN) make_month();
+      return rules->language[f_month_name_from_number](m);
+   }
+
+   string month_shortname()
+   {
+      if (m==CALUNKNOWN) make_month();
+      return rules->language[f_month_shortname_from_number](m);
+   }
+
+   string month_day_name()
+   {
+      if (mnd==CALUNKNOWN) make_month();
+      return rules->language[f_month_day_name_from_number](md,mnd);
+   }
+
+   string week_day_name()
+   {
+      if (wd==CALUNKNOWN) make_week();
+      return rules->language[f_week_day_name_from_number](wd);
+   }
+
+   string week_day_shortname()
+   {
+      if (wd==CALUNKNOWN) make_week();
+      return rules->language[f_week_day_shortname_from_number](wd);
+   }
+
+   int leap_year() { return year_leap_year(y); }
+
+   int hour_no() { return 0; }
+   int minute_no() { return 0; }
+   int second_no() { return 0; }
+   float fraction_no() { return 0.0; }
+   
+//! function method datetime()
+//!     This gives back a mapping with the relevant
+//!	time information (representing the start of the period);
+//!	<pre>
+//!	 ([ "year":     int        // year number (2000 AD=2000, 1 BC==0)
+//!	    "month":    int(1..)   // month of year
+//!	    "day":      int(1..)   // day of month
+//!	    "yearday":  int(0..)   // day of year
+//!	    "week":	int(1..)   // week of year
+//!	    "week_day": int(0..)   // day of week
+//!	    "timezone": int        // offset to utc, including dst
+//!
+//!	    "unix":     int        // unix time
+//!	    "julian":   int        // julian day
+//!      // for compatibility:
+//!	    "hour":     0          // hour of day, including dst
+//!	    "minute":   0          // minute of hour
+//!	    "second":   0          // second of minute 
+//!	    "fraction": 0.0        // fraction of second
+//!	 ]);
+//!	</pre>
+//!
+//! note:
+//!	Day of week is compatible with old versions,
+//!	ie, 0 is sunday, 6 is saturday, so it shouldn't be
+//!	used to calculate the day of the week with the given 
+//!	week number. Year day is also backwards compatible,
+//!	ie, one (1) less then from the year_day() function.
+
+   mapping datetime(void|int skip_stuff)
+   {
+      if (m==CALUNKNOWN) make_month();
+      if (w==CALUNKNOWN) make_week();
+      if (skip_stuff) // called from timeofday
+	 return ([ "year":     y,
+		   "month":    m,
+		   "day":      md,
+		   "yearday":  yd-1,
+		   "week":     w,
+		   "week_day": compat_week_day(wd)
+	 ]);
+      else
+      {
+	 return ([ "year":     y,
+		   "month":    m,
+		   "day":      md,
+		   "yearday":  yd-1,
+		   "week":     w,
+		   "week_day": compat_week_day(wd),
+		   "timezone": utc_offset(),
+		   "julian":   jd,
+		   "unix":     unix_time(),
+	     // for compatibility:
+		   "hour":     0,
+		   "minute":   0,
+		   "second":   0,
+		   "fraction": 0.0
+	 ]);
+      }
+   }
+
+// --- string format ----
+
+//! method string format_iso_ymd();
+//! method string format_ymd();
+//! method string format_ymd_short();
+//! method string format_ymd_xshort();
+//! method string format_iso_week();
+//! method string format_iso_week_short();
+//! method string format_week();
+//! method string format_week_short();
+//! method string format_month();
+//! method string format_month_short();
+//! method string format_iso_time();
+//! method string format_time();
+//! method string format_time_short();
+//! method string format_time_xshort();
+//! method string format_mtime();
+//! method string format_xtime();
+//! method string format_tod();
+//! method string format_todz();
+//! method string format_xtod();
+//! method string format_mod();
+//!	Format the object into nice strings;
+//!	<pre>
+//!	iso_ymd        "2000-06-02 (Jun) -W22-5 (Fri)" [2]
+//!	ext_ymd        "Friday, 2 June 2000" [2]
+//!     ymd            "2000-06-02" 
+//!     ymd_short      "20000602"
+//!     ymd_xshort     "000602" [1]
+//!	iso_week       "2000-W22"
+//!	iso_week_short "2000W22"
+//!	week           "2000-w22" [2]
+//!	week_short     "2000w22" [2]
+//!	month          "2000-06"
+//!	month_short    "200006" [1]
+//!	iso_time       "2000-06-02 (Jun) -W22-5 (Fri) 00:00:00 UTC+1" [2]
+//!	ext_time       "Friday, 2 June 2000, 00:00:00" [2]
+//!	ctime          "Fri Jun  2 00:00:00 2000\n" [2] [3]
+//!	http           "Fri, 02 Jun 2000 00:00:00 GMT" [4]
+//!     time           "2000-06-02 00:00:00" 
+//!	time_short     "20000602 00:00:00"
+//!	time_xshort    "000602 00:00:00"
+//!     mtime          "2000-06-02 00:00" 
+//!     xtime          "2000-06-02 00:00:00.000000" 
+//!     tod            "00:00:00"
+//!     tod_short      "000000"
+//!     todz           "00:00:00 CET"
+//!     todz_iso       "00:00:00 UTC+1"
+//!     xtod           "00:00:00.000000"
+//!     mod            "00:00"
+//!	</pre>
+//!	<tt>[1]</tt> note conflict (think 1 February 2003)
+//!	<br><tt>[2]</tt> language dependent
+//!	<br><tt>[3]</tt> as from the libc function ctime()
+//!	<br><tt>[4]</tt> as specified by the HTTP standard;
+//!	not language dependent.
+
+   string format_iso_ymd()
+   {
+      if (m==CALUNKNOWN) make_month();
+      if (w==CALUNKNOWN) make_week();
+      return sprintf("%04d-%02d-%02d (%s) -W%02d-%d (%s)",
+		     y,m,md,
+		     month_shortname(),
+		     w,wd, // fixme - what weekday?
+		     week_day_shortname());
+   }
+
+   string format_ext_ymd()
+   {
+      if (m==CALUNKNOWN) make_month();
+      return sprintf("%s, %s %s %s",
+		     week_day_name(),
+		     month_day_name(),month_name(),year_name());
+   }
+
+   string format_ctime()
+   {
+      return sprintf("%s %s %2d 00:00:00 %s\n",
+		     week_day_shortname(),
+		     month_shortname(),
+		     md,
+		     year_name());
+   }
+
+   string format_http()
+   {
+      if (wd==CALUNKNOWN) make_week();
+      if (md==CALUNKNOWN) make_month();
+
+      return
+	 sprintf("%s, %02d %s %04d 00:00:00 GMT",
+		 ("SunMonTueWedThuFriSat"/3)[compat_week_day(wd)],
+		 md,
+		 ("zzzJanFebMarAprMayJunJulAugSepOctNovDec"/3)[m],
+		 y);
+   }
+
+   string format_ymd()
+   {
+      if (m==CALUNKNOWN) make_month();
+      return sprintf("%04d-%02d-%02d",y,m,md);
+   }
+
+   string format_ymd_short()
+   {
+      if (m==CALUNKNOWN) make_month();
+      return sprintf("%04d%02d%02d",y,m,md);
+   }
+
+   string format_ymd_xshort()
+   {
+      if (m==CALUNKNOWN) make_month();
+      return sprintf("%02d%02d%02d",y%100,m,md);
+   }
+
+   string format_iso_week()
+   {
+      if (w==CALUNKNOWN) make_week();
+      return sprintf("%04d-W%02d",y,w);
+   }
+
+   string format_iso_week_short()
+   {
+      if (w==CALUNKNOWN) make_week();
+      return sprintf("%04d%02d",y,w);
+   }
+
+   string format_week()
+   {
+      return sprintf("%04d-%s",y,week_name());
+   }
+
+   string format_week_short()
+   {
+      return sprintf("%04d%s",y,week_name());
+   }
+
+   string format_month()
+   {
+      if (m==CALUNKNOWN) make_month();
+      return sprintf("%04d-%02d",y,m);
+   }
+
+   string format_month_short()
+   {
+      if (m==CALUNKNOWN) make_month();
+      return sprintf("%04d%02d",y,m);
+   }
+
+   string format_iso_time()
+   {
+      return format_iso_ymd()+" 00:00:00";
+   }
+
+   string format_ext_time()
+   {
+      return format_ext_ymd()+" 00:00:00";
+   }
+
+   string format_time()
+   {
+      return format_ymd()+" 00:00:00";
+   }
+
+   string format_time_short()
+   {
+      return format_ymd_short()+" 00:00:00";
+   }
+
+   string format_time_xshort()
+   {
+      return format_ymd_xshort()+" 00:00:00";
+   }
+
+   string format_mtime()
+   {
+      return format_ymd_short()+" 00:00";
+   }
+
+   string format_xtime()
+   {
+      return format_ymd_short()+" 00:00:00.000000";
+   }
+
+   string format_tod()
+   {
+      return "00:00:00";
+   }
+
+   string format_tod_short()
+   {
+      return "000000";
+   }
+
+   string format_todz()
+   {
+      return "00:00:00 "+tzname();
+   }
+
+   string format_todz_iso()
+   {
+      return "00:00:00 "+tzname_iso();
+   }
+
+   string format_mod()
+   {
+      return "00:00";
+   }
+
+   string format_xtod()
+   {
+      return "00:00:00.000000";
+   }
+
+   string format_elapsed()
+   {
+      return sprintf("%dd",number_of_days());
+   }
+
+// --- size and move ---
+
+   static TimeRange _set_size(int n,TimeRange t)
+   {
+      if (t->is_timeofday)
+	 return second()->set_size(n,t);
+
+      if (yd==1 && t->is_year)
+	 return Year("ymd_y",rules,y,yjd,t->n*n)
+	    ->autopromote();
+
+// months are even on years
+      if (t->is_year || t->is_month)
+      {
+	 if (md==CALUNKNOWN) make_month();
+	 if (md==1) 
+	    return Month("ymd_yjmw",rules,y,yjd,jd,m,
+			 t->number_of_months()*n,wd,w)
+	       ->autopromote();
+      }
+
+// weeks are not
+      if (t->is_week)
+      {
+	 if (wd==CALUNKNOWN) make_week();
+	 if (wd==1) return Week("ymd_yjwm",rules,y,yjd,jd,w,t->n*n,md,m,mnd);
+      }
+
+// fallback on days
+      if (t->is_ymd)
+	 return Day("ymd_ydmw",rules,y,yjd,jd,yd,
+		    n*t->number_of_days(),m,md,w,wd,mnd);
+
+      error("set_size: incompatible class %O\n",
+	    object_program(t));
+   }
+
+   static TimeRange _add(int n,TimeRange step)
+   {
+      if (step->is_ymd)
+	 return _move(n,step);
+      if (step->is_timeofday)
+	 return second()->range(second(-1))->add(n,step);
+
+      error("add: incompatible class %O\n",
+	    object_program(step));
+   }
+
+   array(int(-1..1)) _compare(TimeRange with)
+   {
+      if (with->is_timeofday)
+      {
+   // wrap
+	 array(int(-1..1)) cmp=with->_compare(this_object());
+
+	 return ({-cmp[0],
+		  -cmp[2],
+		  -cmp[1],
+		  -cmp[3]});
+      }
+      else if (with->is_ymd || with->julian_day)
+      {
+#define CMP(A,B) ( ((A)<(B))?-1:((A)>(B))?1:0 )
+
+	 int b1=julian_day();
+	 int e1=b1+number_of_days();
+
+	 int b2=with->julian_day();
+	 int e2=b2+with->number_of_days();
+
+	 return ({ CMP(b1,b2),CMP(b1,e2),CMP(e1,b2),CMP(e1,e2) });
+      }
+      return ::_compare(with);
+   }
+
+// --- to other YMD
+
+// years
+
+   int number_of_years()
+   {
+      int m=number_of_days();
+      if (m<=1 || m+yd-1<year()->number_of_days()) return 1;
+      return 1+y-year_from_julian_day(jd+m-1)[0];
+   }
+
+   array(cYear) years(int ...range)
+   {
+      int from=1,n=number_of_years(),to=n;
+
+      if (sizeof(range)) 
+	 if (sizeof(range)<2)
+	    error("Illegal numbers of arguments to days()\n");
+	 else
+	 {
+	    [from,to]=range;
+	    if (from>=n) return ({}); else if (from<0) from=0;
+	    if (to>=n) to=n; else if (to<from) return ({});
+	 }
+
+      return map(enumerate(1+to-from,1,y+from),
+		 lambda(int x) 
+		 { return Year("ymd_yn",rules,x,1); });
+   }
+
+   cYear year(void|int m) 
+   { 
+      if (!m || (!n&&m==-1))
+	 return Year("ymd_y",rules,y,yjd,1);
+
+      if (m<0) m=number_of_years()+m;
+
+      array(TimeRange) res=years(m,m);
+      if (sizeof(res)==1) return res[0];
+      error("not in range (Year 0..%d exist)\n",
+	    number_of_years()-1);
+   }
+   
+
+// days
+
+   int number_of_days();
+
+   array(cDay) days(int ...range)   
+   {
+      int from=1,n=number_of_days(),to=n;
+
+      if (sizeof(range)) 
+	 if (sizeof(range)<2)
+	    error("Illegal numbers of arguments to days()\n");
+	 else
+	 {
+	    [from,to]=range;
+	    if (from>n) return ({}); else if (from<1) from=1;
+	    if (to>n) to=n; else if (to<from) return ({});
+	 }
+
+      int zy=y;
+      int zyd=yd+from-1;
+      int zjd=jd+from-1;
+      int zyjd=yjd;
+      array(cDay) res=({});
+
+      to-=from-1;
+
+      if (zyd<1)
+      {
+	 [zy,zyjd]=year_from_julian_day(zjd);
+	 zyd=zjd-zyjd+1;
+      }
+
+      for (;;)
+      {
+	 int rd=year_remaining_days(zy,zyd)+1;
+	 
+	 if (rd>0)
+	 {
+	    if (rd>to) rd=to;
+	    res+=map(enumerate(rd,1,zyd),
+		     lambda(int x) 
+		     { return Day("ymd_yd",rules,zy,zyjd,zyjd+x-1,x,1); });
+	    if (rd==to) break;
+	    zjd+=rd;
+	    to-=rd;
+	 }
+
+	 [zy,zyjd]=year_from_julian_day(zjd);
+	 zyd=zjd-zyjd+1;
+      }
+      return res;
+   }
+
+   cDay day(int ... mp) 
+   { 
+      if (!sizeof(mp))
+	 return Day("ymd_yd",rules,y,yjd,jd,yd,1);
+
+      int m=mp[0];
+
+      if (m==-1 && !n)
+	 return Day("ymd_yd",rules,y,yjd,jd,yd,1);
+
+      if (m<0) m+=1+number_of_days();
+
+      array(TimeRange) res=days(m,m);
+      if (sizeof(res)==1) return res[0];
+      error("not in range (Day 1..%d exist)\n",
+	    number_of_days());
+   }
+
+// --- months
+
+   int number_of_months();
+
+   array(cMonth) months(int ...range)   
+   {
+      int from=1,n=number_of_months(),to=n;
+
+      if (sizeof(range)) 
+	 if (sizeof(range)<2)
+	    error("Illegal numbers of arguments to months()\n");
+	 else
+	 {
+	    [from,to]=range;
+	    if (from>n) return ({}); else if (from<1) from=1;
+	    if (to>n) to=n; else if (to<from) return ({});
+	 }
+
+      if (md==CALUNKNOWN) make_month();
+
+      return map(enumerate(1+to-from,1,from+m-1),
+		 lambda(int x) 
+		 { return Month("ymd_ym",rules,y,x,1); });
+   }
+
+   cMonth month(int ... mp) 
+   { 
+      if (md==CALUNKNOWN) make_month();
+
+      if (!sizeof(mp))
+	 return Month("ymd_ym",rules,y,m,1);
+      
+      int num=mp[0];
+
+      if (num==-1 && !n)
+	 return Month("ymd_ym",rules,y,m,1);
+
+      if (num<0) num+=1+number_of_months();
+
+      array(TimeRange) res=months(num,num);
+      if (sizeof(res)==1) return res[0];
+      error("not in range; Month 1..%d exist in %O\n",
+	    number_of_months(),this_object());
+   }
+
+//---- week
+
+   int number_of_weeks();
+
+   array(cWeek) weeks(int ...range)   
+   {
+      int from=1,n=number_of_weeks(),to=n;
+
+      if (sizeof(range)) 
+	 if (sizeof(range)<2)
+	    error("Illegal numbers of arguments to weeks()\n");
+	 else
+	 {
+	    [from,to]=range;
+	    if (from>n) return ({}); else if (from<1) from=1;
+	    if (to>n) to=n; else if (to<from) return ({});
+	 }
+
+      if (wd==CALUNKNOWN) make_week();
+
+      return map(enumerate(1+to-from,1,from+w-1),
+		 lambda(int x) 
+		 { return Week("ymd_yw",rules,wy,x,1); });
+   }
+
+   cWeek week(int ... mp) 
+   { 
+      if (wd==CALUNKNOWN) make_week();
+
+      if (!sizeof(mp))
+	 return Week("ymd_yw",rules,wy,w,1);
+
+      int num=mp[0];
+
+      if (num==-1 && !n)
+	 return Week("ymd_yw",rules,wy,w,1);
+
+      if (num<0) num+=1+number_of_weeks();
+
+      array(TimeRange) res=weeks(num,num);
+      if (sizeof(res)==1) return res[0];
+      error("not in range (Week 1..%d exist)\n",
+	    number_of_weeks());
+   }
+
+
+// --- functions to conform to Time.*
+
+   static TimeRange get_unit(string unit,int m)
+   {
+      if (!n) return day()[unit]();
+      if (m<0) m+=::`[]("number_of_"+unit+"s")();
+      array(TimeRange) res=::`[](unit+"s")(m,m);
+      if (sizeof(res)==1) return res[0];
+      error("not in range ("+unit+" 0..%d exist)\n",
+	    ::`[]("number_of_"+unit+"s")()-1);
+   }
+
+   static array(TimeRange) get_timeofday(string unit,
+					 int start,int step,program p,
+					 int ... range)
+   {
+      int from=0,n=::`[]("number_of_"+unit)(),to=n-1;
+
+      if (sizeof(range)) 
+	 if (sizeof(range)<2)
+	    error("Illegal numbers of arguments to "+unit+"()\n");
+	 else
+	 {
+	    [from,to]=range;
+	    if (from>=n) return ({}); else if (from<0) from=0;
+	    if (to>=n) to=n-1; else if (to<from) return ({});
+	 }
+      
+      from*=step;
+      to*=step;
+
+      to-=from-step;
+
+      from+=unix_time();
+
+      array z=
+	 map(enumerate(to/step,step,from),
+	     lambda(int x)
+	     { return p("timeofday",rules,x,step); });
+
+//        return z;
+
+      if (sizeof(z)>1 &&
+	  ((p==cHour && z[0]->utc_offset()%3600 != z[-1]->utc_offset()%3600) ||
+	   (p==cMinute && z[0]->utc_offset()%60 != z[-1]->utc_offset()%60)))
+      {
+   // we're in a zone shifting, and we shift a non-hour (or non-minute)
+	 cSecond sec=Second();
+	 int i,uo=z[0]->utc_offset();
+	 for (i=1; i<sizeof(z); i++)
+	    if (z[i]->utc_offset()!=uo)
+	    {
+	       int uq=(z[i]->utc_offset()-uo);
+	       werror("%O %O\n",z[i],z);
+	       if (uq<0)
+	       {
+		  if (uq<=-step) uq=-(-uq%step);
+		  z= z[..i-1]+
+		  ({z[i]->set_size(step+uq,sec)})+
+		     map(z[i+1..],"add",uq,sec);
+	       }
+	       else
+	       {
+		  if (uq>=step) uq%=step;
+		  z= z[..i-1]+
+		  ({z[i]->set_size(uq,sec)})+
+		     map(z[i..sizeof(z)-2],"add",uq,sec);
+		  i++;
+	       }
+	       werror("=> %O %O\n",z[i],z);
+	       uo=z[i]->utc_offset();
+	    }
+      }
+      return z;
+   }
+
+
+   int number_of_hours() { return (number_of_seconds()+3599)/3600; }
+   cHour hour(void|int n) { return get_unit("hour",n); }
+   array(cHour) hours(int ...range)
+   { return get_timeofday("hours",0,3600,Hour,@range); }
+
+   int number_of_minutes() { return (number_of_seconds()+59)/60; }
+   cMinute minute(void|int n) { return get_unit("minute",n); }
+   array(cMinute) minutes(int ...range)
+   { return get_timeofday("minutes",0,60,Minute,@range); }
+
+   int number_of_seconds() { return end()->unix_time()-unix_time(); }
+   cSecond second(void|int n,int ...time) 
+   { 
+      if (sizeof(time)==2)
+	 return hour(n)->minute(time[0])->second(time[1]);
+      return get_unit("second",n); 
+   }
+   array(cSecond) seconds(int ...range)
+   { return get_timeofday("seconds",0,1,Second,@range); }
+
+   float number_of_fractions() { return (float)number_of_seconds(); }
+   cSecond fraction(void|float|int n) 
+   {
+      return fractions()[0];
+   }
+   array(cSecond) fractions(int|float ...range)
+   { 
+      float from,to,n=number_of_fractions();
+      if (sizeof(range)==2)
+	 from=(float)range[0],to=(float)range[1]; 
+      else if (sizeof(range)==0)
+	 from=0.0,to=n;
+      else 
+	 error("Illegal arguments\n");
+      if (from<0.0) from=0.0;
+      if (to>n) to=n;
+      return ({Fraction("timeofday_f",rules,unix_time(),0,
+			(int)to,(int)(inano*(to-(int)to)))
+	       ->autopromote()});
+   }
+
+// ----------------------------------------
+// virtual functions needed
+// ----------------------------------------
+
+   string nice_print();
+   string _sprintf(int t);
+
+   void create_julian_day(int|float jd);
+   static TimeRange _move(int n,YMD step);
+   TimeRange place(TimeRange what,void|int force);
+
+// not needed
+
+   YMD autopromote() { return this; }
+}
+
+//------------------------------------------------------------------------
+//! class Year
+//! 	This is the time period of a year.
+//! inherits TimeRange
+//! inherits YMD
+//------------------------------------------------------------------------
+
+function(mixed...:cYear) Year=cYear;
+class cYear
+{
+   inherit YMD;
+
+   constant is_year=1;
+
+// --- 
+   
+//!
+//! method void create("unix",int unix_time)
+//! method void create("julian",int|float julian_day)
+//! method void create(int year)
+//! method void create(string year)
+//!	It's possible to create the standard week
+//!	by using three different methods; either the normal
+//!	way - from standard unix time or the julian day,
+//!	and also, for more practical use, from the year number.
+//!
+
+   void create(mixed ...args)
+   {
+      if (!sizeof(args))
+      {
+	 create_now();
+	 return;
+      }
+      else switch (args[0])
+      {
+	 case "ymd_y":
+	    rules=args[1];
+	    y=args[2];
+	    jd=yjd=args[3];
+	    n=args[4];
+	    m=md=w=wd=CALUNKNOWN;
+	    yd=1;
+	    return;
+	 case "ymd_yn":
+	    rules=args[1];
+	    y=args[2];
+	    jd=yjd=julian_day_from_year(y);
+	    n=args[3];
+	    m=md=w=wd=CALUNKNOWN;
+	    yd=1;
+	    return;
+	 default:
+	    if (intp(args[0]) && sizeof(args)==1)
+	    {
+	       rules=default_rules;
+	       y=args[0];
+	       jd=yjd=julian_day_from_year(y);
+	       n=1;
+	       m=md=w=wd=CALUNKNOWN;
+	       yd=1;
+	       return;
+	    }
+	    else if (stringp(args[0]))
+	    {
+	       y=default_rules->language[f_year_number_from_name](args[0]);
+	       rules=default_rules;
+	       jd=yjd=julian_day_from_year(y);
+	       n=1;
+	       m=md=w=wd=CALUNKNOWN;
+	       yd=1;
+	       return;
+	    }
+	    break;
+
+      }
+      rules=default_rules;
+      ::create(@args);
+   }
+
+   void create_julian_day(int|float _jd)
+   {
+      if (floatp(_jd))
+	 create_unixtime_default((int)((jd-2440588)*86400));
+      else
+      {
+	 [y,yjd]=year_from_julian_day(_jd);
+	 jd=yjd;
+	 n=1;
+	 md=yd=m=1;
+	 wd=w=CALUNKNOWN; // unknown
+      }
+   }
+
+   TimeRange beginning()
+   {
+      return Year("ymd_y",rules,y,yjd,0);
+   }
+   
+   TimeRange end()
+   {
+      return Year("ymd_yn",rules,y+n,0);
+   }
+   
+// ----------------
+
+   string _sprintf(int t)
+   {
+      switch (t)
+      {
+	 case 'O':
+	    if (n!=1) 
+	       return sprintf("Year(%s)",nice_print_period());
+	    return sprintf("Year(%s)",nice_print());
+	 default:
+	    return 0;
+      }
+   }
+
+   string nice_print_period()
+   {
+      if (!n) return nice_print()+" sharp";
+      return sprintf("%s..%s",nice_print(),year(-1)->nice_print());
+   }
+
+   string nice_print()
+   {
+      return year_name();
+   }
+
+// --- Year _move
+
+   TimeRange _move(int m,YMD step)
+   {
+      if (!step->n || !m) 
+	 return this;
+
+      if (step->is_year)
+	 return Year("ymd_yn",rules,y+m*step->n,n)
+	    ->autopromote();
+
+      if (step->is_month)
+	 return month()->add(m,step)->set_size(this_object());
+
+//        if (step->is_week)
+//  	 return week()->add(m,step)->set_size(this_object());
+
+      if (step->is_ymd)
+	 return Day("ymd_jd",rules,
+		    yjd+m*step->number_of_days(),number_of_days())
+	    ->autopromote();
+      
+      error("_move: Incompatible type %O\n",step);
+   }
+
+   static void convert_from(TimeRange other)
+   {
+      ::convert_from(other);
+      if (other->number_of_years)
+	 n=other->number_of_years();
+      else
+	 n=0;
+   }
+
+   TimeRange place(TimeRange what,void|int force)
+   {
+      if (what->is_day)
+      {
+	 int yd=what->yd;
+	 return Day("ymd_yd",rules,y,yjd,yjd+yd-1,yd,what->n);
+      }
+
+      if (what->is_week)
+      {
+	 cWeek week=Week("ymd_yw",rules,y,what->w,what->n);
+	 if (!force && week->y!=y) return 0; // not this year
+	 return week;
+      }
+
+      error("place: Incompatible type %O\n",what);
+   }
+
+   TimeRange distance(TimeRange to)
+   {
+      if (to->is_timeofday)
+      {
+	 return hour()->distance(to);
+      }
+      if (to->is_ymd)
+      {
+	 if (to->is_year)
+	 {
+	    int y1=y;
+	    int y2=to->y;
+	    if (y2<y1)
+	       error("distance: negative distance\n");
+	    return Year("ymd_yn",rules,y,y2-y1)
+	       ->autopromote();
+	 }
+	 if (to->is_month)
+	    return month()->distance(to);
+	 return day()->distance(to);
+      }
+
+      error("distance: Incompatible type %O\n",to);
+   }
+
+// ---   
+
+   int number_of_years()
+   {
+      return n;
+   }
+
+   int number_of_weeks();
+
+//! method Month month()
+//! method Month month(int n)
+//! method Month month(string name)
+//!	The Year type overloads the month() method,
+//!	so it is possible to get a specified month
+//!	by string:
+//!
+//!	<tt>year-&gt;month("April")</tt>
+//!
+//!	The integer and no argument behavior is inherited
+//!	from <ref to=YMD.month>YMD</ref>().
+
+   cMonth month(int|string ... mp)
+   {
+      if (sizeof(mp) && 
+	  stringp(mp[0]))
+      {
+	 int num=((int)mp[0]) || 
+	    rules->language[f_month_number_from_name](mp[0]);
+	 if (!num)
+	    error("no such month %O in %O\n",mp[0],this_object());
+
+	 return ::month(num);
+      }
+      else
+	 return ::month(@mp);
+   }
+
+//! method Week	week()
+//! method Week	week(int n)
+//! method Week	week(string name)
+//!	The Year type overloads the week() method,
+//!	so it is possible to get a specified week
+//!	by name:
+//!
+//!	<tt>year-&gt;week("17")</tt>
+//!	<tt>year-&gt;week("w17")</tt>
+//!
+//!	The integer and no argument behavior is inherited
+//!	from <ref to=YMD.week>YMD</ref>().
+//!
+//!	This is useful, since the first week of a year
+//!	not always (about half the years, in the ISO calendar) 
+//!	is numbered '1'.
+//!
+
+   cWeek week(int|string ... mp)
+   {
+      if (sizeof(mp) && 
+	  stringp(mp[0]))
+      {
+	 int num;
+	 sscanf(mp[0],"%d",num);
+	 sscanf(mp[0],"w%d",num);
+
+	 cWeek w=::week(num);
+	 if (w->week_no()==num) return w;
+	 return ::week(num-(w->week_no()-num));
+      }
+      else
+	 return ::week(@mp);
+   }
+
+   cYear set_ruleset(Ruleset r)
+   {
+      return Year("ymd_y",r,y,yjd,n);
+   }
+}
+
+
+// ----------------------------------------------------------------
+//   Month
+// ----------------------------------------------------------------
+
+function(mixed...:cMonth) Month=cMonth;
+class cMonth
+{
+   inherit YMD;
+
+   constant is_month=1;
+
+   int nd; // number of days
+   int nw; // number of weeks
+
+   void create(mixed ...args)
+   {
+      if (!sizeof(args))
+      {
+	 rules=default_rules;
+	 create_unixtime_default(time());
+	 return;
+      }
+      else
+	 switch (args[0])
+	 {
+	    case "ymd_ym":
+	       rules=args[1];
+	       y=args[2];
+	       m=args[3];
+	       n=args[4];
+	       md=1;
+	       w=wd=CALUNKNOWN;
+	       [y,m,nd,yd]=year_month_from_month(y,m);
+	       yjd=julian_day_from_year(y);
+	       jd=yjd+yd-1;
+	       if (n!=1) nd=CALUNKNOWN;
+	       nw=CALUNKNOWN;
+	       return;
+	    case "ymd_yjmw":
+	       rules=args[1];
+	       y=args[2];
+	       yjd=args[3];
+	       jd=args[4];
+	       yd=1+jd-yjd;
+	       m=args[5];
+	       n=args[6];
+	       wd=args[7];
+	       w=args[8];
+	       md=1;
+	       nw=nd=CALUNKNOWN;
+	       return;
+	    case "ymd_jd":
+	       rules=args[1];
+	       create_julian_day(args[2]);
+	       n=args[3];
+	       return;
+	    default:
+	       if (intp(args[0]) && sizeof(args)==2)
+	       {
+		  create("ymd_ym",default_rules,args[0],args[1],1);
+		  if (y!=args[0])
+		     error("month %d doesn't exist in %d\n",args[1],args[0]);
+		  return;
+	       }
+	       break;
+	 }
+
+      rules=default_rules;
+      ::create(@args);
+   }
+
+   void create_julian_day(int|float _jd)
+   {
+      if (floatp(_jd))
+	 create_unixtime_default((int)((jd-2440588)*86400));
+      else
+      {
+	 int zmd;
+	 [y,yjd]=year_from_julian_day(jd=_jd);
+	 [m,zmd,nd,yd]=month_from_yday(y,1+jd-yjd);
+	 jd=yd+yjd-1;
+
+	 n=1;
+	 md=1;
+	 nw=wd=w=CALUNKNOWN; // unknown
+      }
+   }
+
+   string _sprintf(int t)
+   { 
+//        return sprintf("month y=%d yjd=%d m=%d jd=%d yd=%d n=%d nd=%d",
+//  		     y,yjd,m,jd,yd,n,number_of_days());
+      switch (t)
+      {
+	 case 'O':
+	    if (n!=1) 
+	       return sprintf("Month(%s)",nice_print_period());
+	    return sprintf("Month(%s)",nice_print());
+	 default:
+	    return 0;
+      }
+   }
+
+   string nice_print()
+   {
+      return 
+	 sprintf("%s %s",
+		 month_name(),
+		 year_name());
+   }
+
+   string nice_print_period()
+   {
+      if (!n) return day()->nice_print()+" 0:00 sharp";
+      cMonth mo=month(-1);
+      if (mo->y==y)
+	 return sprintf("%s..%s %s",
+			month_shortname(),
+			mo->month_shortname(),
+			year_name());
+      return nice_print()+" .. "+month(-1)->nice_print();
+   }
+
+   cDay beginning()
+   {
+      return Month("ymd_yjmw",rules,y,yjd,jd,m,0,wd,w)
+	 ->autopromote();
+   }
+
+   cDay end()
+   {
+      return Month("ymd_ym",rules,y,m+n,0)
+	 ->autopromote();
+   }
+
+// --- month position and distance
+
+   TimeRange distance(TimeRange to)
+   {
+      if (to->is_timeofday)
+	 return hour()->distance(to);
+      
+      if (to->is_ymd)
+      {
+	 if (to->is_month || to->is_year)
+	 {
+	    int n1=months_to_month(to->y,to->is_year?1:to->m);
+	    if (n1<0)
+	       error("distance: negative distance (%d months)\n",n1);
+	    return Month("ymd_yjmw",rules,y,yjd,jd,m,n1,wd,w)
+	       ->autopromote();
+	 }
+
+	 int d1=jd;
+	 int d2=to->jd;
+	 if (d2<d1)
+	    error("distance: negative distance (%d days)\n",d2-d1);
+	 return Day("ymd_ydmw",rules,y,yjd,jd,yd,d2-d1,m,1,w,wd,mnd)
+	    ->autopromote();
+      }
+
+      error("distance: Incompatible type %O\n",to);
+   }
+
+   static void convert_from(TimeRange other)
+   {
+      ::convert_from(other);
+      if (other->number_of_months)
+	 n=other->number_of_months();
+      else
+	 n=0;
+   }
+
+   TimeRange _move(int x,YMD step)
+   {
+      if (step->is_year)
+	 return Month("ymd_ym",rules,y+x*step->n,m,n)
+	    ->autopromote();
+      if (step->is_month)
+	 return Month("ymd_ym",rules,y,m+x*step->n,n)
+	    ->autopromote();
+
+      return Day("ymd_jd",rules,jd+x*step->number_of_days(),number_of_days())
+	 ->autopromote();
+   }
+
+   TimeRange place_day(int day,int day_n,void|int force)
+   {
+      if (day>number_of_days()) return 0; // doesn't exist
+      return Day("ymd_jd",rules,jd+day-1,day_n)->autopromote();
+   }
+
+   TimeRange place(TimeRange what,void|int force)
+   {
+      if (what->is_year) 
+	 return year()->place(what,force); // just fallback
+      
+      if (what->is_day)
+	 return place_day(what->month_day(),what->n,force);
+
+      error("place: Incompatible type %O\n",what);
+   }
+
+// --- Month to other units
+
+   int number_of_years()
+   {
+      if (n<=1) return 1;
+
+      [int y2,int m2,int nd2,int yd2]=year_month_from_month(y,m+n);
+      return 1+y2-y;
+   }
+
+   int number_of_days()
+   {
+      if (nd!=CALUNKNOWN) return nd;
+      
+      [int y2,int m2,int nd2,int yd2]=year_month_from_month(y,m+n);
+      return nd=julian_day_from_year(y2)+yd2-jd-1;
+   }
+
+   int number_of_weeks()
+   {
+      if (nw!=CALUNKNOWN) return nw;
+
+      [int y2,int m2,int nd2,int yd2]=year_month_from_month(y,m+n);
+
+      return nw=
+	 Week("julian_r",jd,rules)
+	 ->range(Week("julian_r",julian_day_from_year(y2)+yd2-2,rules))
+	 ->number_of_weeks();
+   }
+
+   int number_of_months()
+   {
+      return n;
+   }
+
+   cMonth set_ruleset(Ruleset r)
+   {
+      return Month("ymd_yjmw",r,y,yjd,jd,m,n,wd,w);
+   }
+
+// --- needs to be defined
+
+   static int months_to_month(int y,int m);
+}
+
+// ----------------------------------------------------------------
+//! class Week
+//!	The Calendar week represents a standard time period of
+//!	a week. In the Gregorian calendar, the standard week
+//!	starts on a sunday and ends on a saturday; in the ISO
+//!	calendar, it starts on a monday and ends on a sunday.
+//!
+//!	The week are might not be aligned to the year, and thus
+//!	the week may cross year borders and the year of 
+//!	the week might not be the same as the year of all the
+//!	days in the week. The basic rule is that the week year
+//!	is the year that has the most days in the week, but
+//!	since week number only is specified in the ISO calendar
+//!	- and derivates - the week number of most calendars
+//!	is the week number of most of the days in the ISO
+//!	calendar, which modifies this rule for the Gregorian calendar;
+//!	the week number and year is the same as for the ISO calendar,
+//!	except for the sundays.
+//!
+//!	When adding, moving and subtracting months
+//!	to a week, it falls back to using days.
+//!
+//!	When adding, moving or subtracting years,
+//!	if tries to place the moved week in the 
+//!	resulting year.
+// ----------------------------------------------------------------
+
+function(mixed...:cWeek) Week=cWeek;
+class cWeek
+{
+   inherit YMD;
+
+   constant is_week=1;
+
+//!
+//! method void create("unix",int unix_time)
+//! method void create("julian",int|float julian_day)
+//! method void create(int year,int week)
+//!	It's possible to create the standard week
+//!	by using three different methods; either the normal
+//!	way - from standard unix time or the julian day,
+//!	and also, for more practical use, from year and week
+//!	number.
+//!
+
+   void create(mixed ...args)
+   {
+      if (!sizeof(args))
+      {
+	 rules=default_rules;
+	 create_unixtime_default(time());
+	 return;
+      }
+      else
+	 switch (args[0])
+	 {
+	    case "ymd_yw":
+	       rules=args[1];
+	       y=args[2];
+	       w=args[3];
+	       n=args[4];
+	       m=md=CALUNKNOWN;
+	       [y,w,wd,int nd,jd]=week_from_week(y,w);
+	       yjd=julian_day_from_year(y);
+	       yd=1+jd-yjd;
+	       wy=y;
+	       if (n!=1) nd=CALUNKNOWN;
+	       return;
+	    case "ymd_yjwm":
+	       rules=args[1];
+	       y=args[2];
+	       yjd=args[3];
+	       jd=args[4];
+	       yd=1+jd-yjd;
+	       w=args[5];
+	       n=args[6];
+	       md=args[7];
+	       m=args[8];
+	       mnd=args[9];
+	       wd=1;
+	       wy=y;
+	       nd=CALUNKNOWN;
+	       return;
+	    case "ymd_jd":
+	       rules=args[1];
+	       create_julian_day(args[2]);
+	       n=args[3];
+	       return;
+	    default:
+	       if (intp(args[0]) && sizeof(args)==2)
+	       {
+		  create("ymd_yw",default_rules,args[0],args[1],1);
+		  if (y!=args[0])
+		     error("month %d doesn't exist in %d\n",args[1],args[0]);
+		  return;
+	       }
+	       break;
+	 }
+
+      rules=default_rules;
+      ::create(@args);
+   }
+
+   void create_julian_day(int|float _jd)
+   {
+      if (floatp(_jd))
+	 create_unixtime_default((int)((jd-2440588)*86400));
+      else
+      {
+	 int zwd;
+	 [y,w,zwd,int nd,jd]=week_from_julian_day(_jd);
+	 yjd=julian_day_from_year(y);
+	 yd=1+jd-yjd;
+
+	 n=1;
+	 wd=1;
+	 wy=y;
+	 md=m=CALUNKNOWN; // unknown
+      }
+   }
+
+   string _sprintf(int t)
+   { 
+//        return sprintf("week y=%d yjd=%d w=%d jd=%d yd=%d n=%d nd=%d",
+//  		     y,yjd,w,jd,yd,n,number_of_days());
+      switch (t)
+      {
+	 case 'O':
+	    if (n!=1) 
+	       return sprintf("Week(%s)",nice_print_period());
+	    return sprintf("Week(%s)",nice_print());
+	 default:
+	    return 0;
+      }
+   }
+
+   string nice_print()
+   {
+      return 
+	 sprintf("%s %s",
+		 week_name(),
+		 year_name());
+   }
+
+
+   string nice_print_period()
+   {
+      if (!n) return day()->nice_print()+" 0:00 sharp";
+      cWeek wo=week(-1);
+      if (wo->y==y)
+	 return sprintf("%s..%s %s",
+			week_name(),
+			wo->week_name(),
+			year_name());
+      return nice_print()+" .. "+week(-1)->nice_print();
+   }
+
+   cDay beginning()
+   {
+      return Week("ymd_yjwm",rules,y,yjd,jd,w,0,md,m,mnd)
+	 ->autopromote();
+   }
+
+   cDay end()
+   {
+      return Week("ymd_yw",rules,y,w+n,0)
+	 ->autopromote();
+   }
+
+// --- week position and distance
+
+   TimeRange distance(TimeRange to)
+   {
+      if (to->is_timeofday)
+	 return hour()->distance(to);
+      
+      if (to->is_week)
+      {
+	 int n1=weeks_to_week(to->y,to->w);
+	 if (n1<0)
+	    error("distance: negative distance (%d weeks)\n",n1);
+	 return Week("ymd_yjwm",rules,y,yjd,jd,w,n1,md,m,mnd)
+	    ->autopromote();
+      }
+
+      if (to->julian_day)
+      {
+	 int d1=jd;
+	 int d2=to->julian_day();
+	 if (d2<d1)
+	    error("distance: negative distance (%d days)\n",d2-d1);
+	 return Day("ymd_ydmw",rules,y,yjd,jd,yd,d2-d1,m,md,w,1,mnd)
+	    ->autopromote();
+      }
+
+      error("distance: Incompatible type %O\n",to);
+   }
+
+   static void convert_from(TimeRange other)
+   {
+      ::convert_from(other);
+      if (other->number_of_weeks)
+	 n=other->number_of_weeks();
+      else
+	 n=0;
+   }
+
+   TimeRange _move(int x,YMD step)
+   {
+      if (step->is_week)
+	 return Week("ymd_yw",rules,y,w+x*step->n,n)
+	    ->autopromote();
+
+      if (step->is_year)
+	 return year()->add(x,step)->place(this_object(),1);
+
+      if (step->number_of_days)
+	 return Day("ymd_jd",rules,
+		    jd+x*step->number_of_days(),number_of_days())
+	    ->autopromote();
+
+      error("add: Incompatible type %O\n",step);
+   }
+
+   TimeRange place_day(int day,int day_n,int force)
+   {
+      if (day>number_of_days()) 
+	 if (!force) 
+	    return 0;
+	 else 
+	    return Day("ymd_jd",rules,jd+day-1,max(0,day_n-1))->autopromote();
+      return Day("ymd_jd",rules,jd+day-1,day_n)->autopromote();
+   }
+
+   TimeRange place(TimeRange what,void|int force)
+   {
+      if (what->is_year) 
+	 return year()->place(what,force); // just fallback
+      
+      if (what->is_day)
+	 return place_day(what->week_day(),what->n,force);
+
+      error("place: Incompatible type %O\n",what);
+   }
+
+// --- Week to other units
+
+   int number_of_years()
+   {
+      if (n<=1) return 1;
+
+      [int y2,int w2,int wd2,int nd2,int jd2]=week_from_week(y,w+n);
+      return 1+y2-y;
+   }
+
+   int number_of_months()
+   {
+      if (!n) return 1;
+      
+// cheat
+      return Day("ymd_jd",rules,jd,number_of_days())
+	 ->number_of_months();
+   }
+
+   int number_of_weeks()
+   {
+      return n;
+   }
+
+   int number_of_days();
+
+//! method Day day()
+//! method Day day(int n)
+//! method Day day(string name)
+//!	The Week type overloads the day() method,
+//!	so it is possible to get a specified weekday
+//!	by string:
+//!
+//!	<tt>week-&gt;day("sunday")</tt>
+//!
+//!	The integer and no argument behavior is inherited
+//!	from <ref to=YMD.day>YMD</ref>().
+//!
+//! note:
+//!	the weekday-from-string routine is language dependent.
+
+   cDay day(int|string ... mp)
+   {
+      if (sizeof(mp) && 
+	  stringp(mp[0]))
+      {
+	 int num=((int)mp[0]) || 
+	    rules->language[f_week_day_number_from_name](mp[0]);
+	 if (!num)
+	    error("no such day %O in %O\n",mp[0],this_object());
+
+	 return ::day(num);
+      }
+      else
+	 return ::day(@mp);
+   }
+
+   cWeek set_ruleset(Ruleset r)
+   {
+      return Week("ymd_yjwm",r,y,yjd,jd,w,n,md,m,mnd);
+   }
+
+// --- needs to be defined
+
+   static int weeks_to_week(int y,int m);
+}
+
+// ----------------------------------------------------------------
+//   Day
+// ----------------------------------------------------------------
+
+function(mixed...:cDay) Day=cDay;
+class cDay
+{
+   inherit YMD;
+
+   constant is_day=1;
+   int nw;
+
+//!
+//! method void create("unix",int unix_time)
+//! method void create("julian",int|float julian_day)
+//! method void create(int year,int month,int day)
+//! method void create(int year,int year_day)
+//! method void create(int julian_day)
+//!	It's possible to create the day
+//!	by using five different methods; either the normal
+//!	way - from standard unix time or the julian day,
+//!	and also, for more practical use, from year, month and day,
+//!	from year and day of year, and from julian day
+//!	without extra fuzz.
+
+   void create(mixed ...args)
+   {
+      if (!sizeof(args))
+      {
+	 rules=default_rules;
+	 create_unixtime_default(time());
+	 return;
+      }
+      else
+	 switch (args[0])
+	 {
+	    case "ymd_ydmw":
+	       rules=args[1];
+	       y=args[2];
+	       yjd=args[3];
+	       jd=args[4];
+	       yd=args[5];
+	       n=args[6];
+	       m=args[7];
+	       md=args[8];
+	       w=args[9];
+	       wd=args[10];
+	       mnd=args[11];
+	       nw=CALUNKNOWN;
+	       return;
+	    case "ymd_yd":
+	       rules=args[1];
+	       y=args[2];
+	       yjd=args[3];
+	       jd=args[4];
+	       yd=args[5];
+	       n=args[6];
+	       wd=nw=md=m=w=CALUNKNOWN;
+	       return;
+	    case "ymd_jd":
+	       rules=args[1];
+	       create_julian_day(args[2]);
+	       n=args[3];
+	       wd=nw=md=m=w=CALUNKNOWN;
+	       return;
+	    case "unix_r":
+	    case "julian_r":
+	    case "unix":
+	    case "julian":
+	       break;
+	    default:
+	       rules=default_rules;
+	       wd=nw=md=m=w=CALUNKNOWN;
+	       n=1;
+	       switch (sizeof(args))
+	       {
+		  case 1:
+		     if (intp(args[0])) 
+		     {
+			create_julian_day(args[0]);
+			return;
+		     }
+		     break;
+		  case 2:
+		     if (stringp(args[0])) 
+			y=default_rules->language[f_year_number_from_name]
+			   (args[0]);
+		     else if (intp(args[0]))
+			y=args[0];
+		     else 
+			break;
+		     if (!intp(args[1])) 
+			break;
+		     yd=args[1];
+		     yjd=julian_day_from_year(y);
+		     jd=yjd+yd-1;
+		     return;
+		  case 3:
+		     if (stringp(args[0])) 
+			y=default_rules->language[f_year_number_from_name]
+			   (args[0]);
+		     else if (intp(args[0]))
+			y=args[0];
+		     else 
+			break;
+		     if (!intp(args[1]) ||
+			 !intp(args[2])) break;
+		     md=args[2];
+		     [y,m,int nmd,int myd]=
+			year_month_from_month(y,args[1]);
+		     if (m!=args[1] || y!=args[0])
+			error("No such month (%d-%02d)\n",args[0],args[1]);
+		     yjd=julian_day_from_year(y);
+		     md=args[2];
+		     jd=yjd+myd+md-2;
+		     yd=jd-yjd+1;
+		     if (md>nmd || md<1)
+			error("No such day of month (%d-%02d-%02d)\n",
+			      @args);
+		     return;
+	       }
+	 }
+
+      rules=default_rules;
+      ::create(@args);
+   }
+
+   void create_julian_day(int|float _jd)
+   {
+      n=1;
+      nw=md=m=wd=w=CALUNKNOWN; // unknown
+
+      if (floatp(_jd))
+      {
+	 create_unixtime_default((int)((jd-2440588)*86400));
+      }
+      else
+      {
+	 [y,yjd]=year_from_julian_day(jd=_jd);
+	 yd=1+jd-yjd;
+      }	 
+   }
+
+   string _sprintf(int t)
+   {
+      switch (t)
+      {
+	 case 'O':
+	    if (n!=1) 
+	       return sprintf("Day(%s)",nice_print_period());
+	    return sprintf("Day(%s)",nice_print());
+	 default:
+	    return 0;
+      }
+   }
+
+   string nice_print()
+   {
+      if (m==CALUNKNOWN) make_month();
+      if (wd==CALUNKNOWN) make_week();
+      return 
+	 sprintf("%s %s %s %s",
+		 week_day_shortname(),
+		 month_day_name(),month_shortname(),
+		 year_name());
+   }
+
+   string nice_print_period()
+   {
+//        return nice_print()+" n="+n+"";
+      if (!n) return nice_print()+" 0:00 sharp";
+      return nice_print()+" .. "+day(-1)->nice_print();
+   }
+
+   cDay beginning()
+   {
+      return Day("ymd_ydmw",rules,y,yjd,jd,yd,0,m,md,w,wd,mnd);
+   }
+
+   cDay end()
+   {
+      return Day("ymd_jd",rules,jd+n,0)
+	 ->autopromote();
+   }
+
+   static void convert_from(TimeRange other)
+   {
+      ::convert_from(other);
+      if (other->number_of_days)
+	 n=other->number_of_days();
+      else
+	 n=0;
+   }
+
+// --- Day _move
+
+   static TimeRange _move(int x,YMD step)
+   {
+      if (step->is_year)
+	 return year()->add(x,step)->place(this_object(),1);
+
+      if (step->is_month)
+	 return month()->add(x,step)->place(this_object(),1);
+
+      if (step->is_week)
+	 return week()->add(x,step)->place(this_object(),1);
+
+      if (step->is_day)
+	 return Day("ymd_jd",rules,jd+x*step->n,n)
+	    ->autopromote();
+
+      error("_move: Incompatible type %O\n",step);
+   }
+
+   TimeRange place(TimeRange what)
+   {
+      if (what->is_timeofday)
+      {
+	 int lux=
+	    what->ux-
+	    Day("unix_r",what->unix_time(),what->ruleset())
+	    ->unix_time();
+
+	 if (what->is_timeofday_f)
+	    return 
+	       Fraction("timeofday_f",rules,
+			lux+unix_time(),what->ns,what->s_len,what->ns_len)
+	       ->autopromote();
+
+	 return Second("timeofday",rules,unix_time()+lux,what->len)
+	    ->autopromote();
+      }
+
+      error("place: Incompatible type %O\n",what);
+   }
+
+   TimeRange distance(TimeRange to)
+   {
+      if (to->is_timeofday)
+	 return hour()->distance(to);
+      if (to->is_ymd)
+      {
+	 int d1=jd;
+	 int d2=to->jd;
+	 if (d2<d1)
+	    error("distance: negative distance (%d days)\n",d2-d1);
+	 return Day("ymd_ydmw",rules,y,yjd,jd,yd,d2-d1,m,md,w,wd,mnd)
+	    ->autopromote();
+      }
+
+      error("distance: Incompatible type %O\n",to);
+   }
+
+// --- Day to other YMD
+
+   int number_of_days()
+   {
+      return n;
+   }
+
+   int number_of_years()
+   {
+      if (n<=1) return 1;
+      return 1+year_from_julian_day(jd+n-1)[0]-y;
+   }
+
+   int number_of_weeks()
+   {
+      if (nw!=CALUNKNOWN) return nw;
+
+      if (n<=1) return nw=1;
+
+      return nw=
+	 Week("julian_r",jd,rules)
+	 ->range(Week("julian_r",jd+n-1,rules))
+	 ->number_of_weeks();
+   }
+
+   cDay set_ruleset(Ruleset r)
+   {
+      return Day("ymd_ydmw",r,y,yjd,jd,yd,n,m,md,w,wd,mnd);
+   }
+
+// backwards compatible with calendar I
+   string iso_name() { return format_ymd(); }
+   string iso_short_name() { return format_ymd_short(); }
+}
+
+//------------------------------------------------------------------------
+//- class YMD_Time
+//------------------------------------------------------------------------
+
+class YMD_Time
+{
+#define MKRBASE								     \
+	do								     \
+	{								     \
+	   int n;							     \
+	   if (!rbase)							     \
+               rbase=Day("unix_r",this->ux,this->rules)->range(Day("unix_r",this->ux+this->len,this->rules)); \
+	} while (0)
+
+#define RBASE (this->base || this->make_base())
+	
+   cDay day(int ...n) { return RBASE->day(@n); }
+   cDay number_of_days() { return RBASE->number_of_days(); }
+   array(cDay) days(int ...r) { return RBASE->days(@r); }
+
+   cMonth month(int ...n) { return RBASE->month(@n); }
+   cMonth number_of_months() { return RBASE->number_of_months(); }
+   array(cMonth) months(int ...r) { return RBASE->months(@r); }
+
+   cWeek week(int ...n) { return RBASE->week(@n); }
+   cWeek number_of_weeks() { return RBASE->number_of_weeks(); }
+   array(cWeek) weeks(int ...r) { return RBASE->weeks(@r); }
+   
+   cYear year(int ...n) { return RBASE->year(@n); }
+   cYear number_of_years() { return RBASE->number_of_years(); }
+   array(cYear) years(int ...r) { return RBASE->years(@r); }
+
+   int year_no() { return RBASE->year_no(); }
+   int month_no() { return RBASE->month_no(); }
+   int week_no() { return RBASE->week_no(); }
+   int month_name() { return RBASE->month_name(); }
+   int month_shortname() { return RBASE->month_shortname(); }
+   int month_day() { return RBASE->month_day(); }
+   int month_day_name() { return RBASE->month_day_name(); }
+   int week_day() { return RBASE->week_day(); }
+   int year_day() { return RBASE->year_day(); }
+   string week_name() { return RBASE->week_name(); }
+   string week_day_name() { return RBASE->week_day_name(); }
+   string week_day_shortname() { return RBASE->week_day_shortname(); }
+   int leap_year() { return RBASE->leap_year(); }
+
+   string format_iso_ymd() { return RBASE->format_iso_ymd(); }
+   string format_ext_ymd() { return RBASE->format_ext_ymd(); }
+   string format_ymd() { return RBASE->format_ymd(); }
+   string format_ymd_short() { return RBASE->format_ymd_short(); }
+   string format_ymd_xshort() { return RBASE->format_ymd_xshort(); }
+   string format_iso_week() { return RBASE->format_iso_week(); }
+   string format_iso_week_short() 
+   { return RBASE->format_iso_week_short(); }
+   string format_week() { return RBASE->format_week(); }
+   string format_week_short() { return RBASE->format_week_short(); }
+   string format_month() { return RBASE->format_month(); }
+   string format_month_short() { return RBASE->format_month_short(); }
+
+#undef RBASE
+}
+
+#define OVERLOAD_TIMEOFDAY						\
+									\
+   static int(0..1) create_backtry(mixed ... args)			\
+   {									\
+      if (sizeof(args)>=5 &&						\
+	  (intp(args[0])||stringp(args[0])) &&				\
+	  intp(args[1]) &&						\
+	  intp(args[2]))						\
+      {									\
+	 base=Day(@args[..2]);						\
+	 return ::create_backtry(@args[3..]);				\
+      }									\
+      return ::create_backtry(@args);					\
+   }
+
+
+//------------------------------------------------------------------------
+//! class Hour
+//! inherits Time.Hour
+//! inherits YMD
+//------------------------------------------------------------------------
+
+class cHour
+{
+   inherit Time::cHour;
+   inherit YMD_Time;
+   OVERLOAD_TIMEOFDAY;
+}
+
+class cMinute
+{
+   inherit Time::cMinute;
+   inherit YMD_Time;
+   OVERLOAD_TIMEOFDAY;
+}
+
+class cSecond
+{
+   inherit Time::cSecond;
+   inherit YMD_Time;
+   OVERLOAD_TIMEOFDAY;
+}
+
+class cFraction
+{
+   inherit Time::cFraction;
+   inherit YMD_Time;
+   OVERLOAD_TIMEOFDAY;
+}
+
+class cSuperTimeRange
+{
+   inherit Time::cSuperTimeRange;
+
+   array(cYear) years(int ...range) { return get_units("years",@range); }
+   cYear year(void|int n) { return get_unit("years",n); }
+   int number_of_years() { return num_units("years"); }
+
+   array(cMonth) months(int ...range) { return get_units("months",@range); }
+   cMonth month(void|int n) { return get_unit("months",n); }
+   int number_of_months() { return num_units("months"); }
+
+   array(cWeek) weeks(int ...range) { return get_units("weeks",@range); }
+   cWeek week(void|int n) { return get_unit("weeks",n); }
+   int number_of_weeks() { return num_units("weeks"); }
+
+   array(cDay) days(int ...range) { return get_units("days",@range); }
+   cDay day(void|int n) { return get_unit("days",n); }
+   int number_of_days() { return num_units("days"); }
+
+#define RBASE parts[0]
+
+   int year_no() { return RBASE->year_no(); }
+   int month_no() { return RBASE->month_no(); }
+   int week_no() { return RBASE->week_no(); }
+   int month_name() { return RBASE->month_name(); }
+   int month_shortname() { return RBASE->month_shortname(); }
+   int month_day() { return RBASE->month_day(); }
+   int month_day_name() { return RBASE->month_day_name(); }
+   int week_day() { return RBASE->week_day(); }
+   int year_day() { return RBASE->year_day(); }
+   string week_name() { return RBASE->week_name(); }
+   string week_day_name() { return RBASE->week_day_name(); }
+   string week_day_shortname() { return RBASE->week_day_shortname(); }
+   int leap_year() { return RBASE->leap_year(); }
+
+   string format_iso_ymd() { return RBASE->format_iso_ymd(); }
+   string format_ext_ymd() { return RBASE->format_ext_ymd(); }
+   string format_ymd() { return RBASE->format_ymd(); }
+   string format_ymd_short() { return RBASE->format_ymd_short(); }
+   string format_ymd_xshort() { return RBASE->format_ymd_xshort(); }
+   string format_iso_week() { return RBASE->format_iso_week(); }
+   string format_iso_week_short() { return RBASE->format_iso_week_short(); }
+   string format_week() { return RBASE->format_week(); }
+   string format_week_short() { return RBASE->format_week_short(); }
+   string format_month() { return RBASE->format_month(); }
+   string format_month_short() { return RBASE->format_month_short(); }
+
+#undef RBASE
+}
+
+//------------------------------------------------------------------------
+//! global convinience functions
+//------------------------------------------------------------------------
+
+//! method TimeRange 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:
+//!	<pre>
+//!	%Y absolute year 
+//!	%y dwim 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)
+//!	%d short date (20000304, 000304)
+//!	%a day (needs %y)
+//!	%e weekday (needs %y, %w)
+//!	%h hour (needs %d, %D or %W)
+//!	%m minute (needs %h)
+//!	%s second (needs %m)
+//!     %f fraction of a second (needs %s)
+//!	%t short time (205314, 2053)
+//!	</pre>
+//!
+//! note:
+//!	Returns 0 if format doesn't match data.
+
+TimeRange parse(string fmt,string arg)
+{
+   string nfmt;
+   nfmt=replace(fmt," %","%*[ \t]%"); // whitespace -> whitespace
+#define ALNU "%[^ -,./:-?[-`{-¿]"
+#define NUME "%[0-9]"
+   nfmt=replace(nfmt,
+		({"%Y","%y","%M","%W","%D","%a","%e","%h","%m","%s",
+		  "%t","%f","%d","%z"}),
+		({ALNU,ALNU,ALNU,"%d","%d","%d",ALNU,"%d","%d","%d",
+		  NUME,NUME,NUME,"%[-+0-9A-Za-z/]"}));
+   array q=Array.map(replace(fmt,({"%*","%%"}),({"",""}))/"%",
+		     lambda(string s){ return s[..0];})-({""});
+   array res=array_sscanf(arg,nfmt);
+
+   if (sizeof(res)<sizeof(q)) 
+      return 0; // parse error
+
+   mapping m=mkmapping(q,res);
+
+   TimeRange low;
+
+   werror("%O\n",m);
+
+   Calendar cal=this_object();
+
+   if (catch {
+
+      if (m->z) 
+	 cal=cal->set_timezone(m->z);
+      werror("%O\n",m->z);
+
+      string x;
+      if (m->Y) 
+	 m->Y=default_rules->language[f_year_number_from_name](m->Y);
+
+      if (!zero_type(m->Y) && m->D && (int)m->M)
+	 low=m->day=cal->Day(m->Y,(int)m->M,m->D);
+
+      if (m->d)
+      {
+	 int y,mo,d;
+      
+	 if (strlen(m->d)==6)
+	 {
+	    [y,mo,d]=(array(int))(m->d/2);
+	    if (y<70) y+=2000; else y+=1900;
+	 }
+	 else if (strlen(m->d)==8)
+	    [y,mo,d]=(array(int))array_sscanf(m->d,"%4s%2s%2s");
+	 else return 0;
+
+	 low=m->day=cal->Day(y,mo,d);
+      }
+      else
+      {
+	 if (!zero_type(m->Y)) m->year=cal->Year(m->Y);
+	 else if (m->y)
+	 {
+	    if (strlen(m->y)<3) 
+	    {
+	       m->y=(int)m->y;
+	       if (m->y<70) m->y+=2000;
+	       else if (m->y<100) m->y+=1900;
+	    }
+	    low=m->year=cal->Year(m->y);
+	 }
+	 else low=m->year=cal->Year();
+
+	 if (m->M)
+	 {
+	    m->month=low=m->year->month(m->M);
+	 }
+	 if (m->W) 
+	    m->week=low=m->year->week("w"+m->W);
+
+	 if (!zero_type(m->D))
+	    if (stringp(m->D)) return 0;
+	    else m->day=low=(m->month||cal->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||cal->Week())->day(m->e);
+	 else
+	    low=m->day=cal->Day();
+      }
+
+      if (m->t)
+      {
+	 int h,mi,s;
+      
+	 if (strlen(m->t)==6)
+	    [h,mi,s]=(array(int))(m->t/2);
+	 else if (strlen(m->t)==4)
+	    [h,mi]=(array(int))(m->t/2),s=0;
+	 else return 0;
+      
+	 low=m->second=m->day->second(h,mi,s);
+      }
+      else if (!zero_type(m->h) && !zero_type(m->m) && !zero_type(m->s))
+	 low=m->second=m->day->second(m->h,m->m,m->s);
+      else
+      {
+	 if (!zero_type(m->h))
+	    low=m->hour=(m->day||cal->Day())->hour(m->h);
+	 if (!zero_type(m->m))
+	    low=m->minute=(m->hour||cal->Hour())->minute(m->m);
+	 if (!zero_type(m->s))
+	    low=m->second=(m->minute||cal->Minute())->second(m->s);
+      }
+      return low;
+
+   })
+       return 0;
+}
+
+//! function Day dwim_day(string date)
+//!	Tries a number of different formats on the given date (in order):
+//!	<pre>
+//!     <ref>parse</ref> format                  as in
+//!	"%y-%M-%D (%M) -W%W-%e (%e)"  "2000-03-20 (Mar) -W12-1 (Mon)"
+//!	"%D%*[ /]%M%*[ /-,]%y"	      "20/3/2000" "20 mar 2000" "20/3 -00"
+//!	"%e%*[ ]%D%*[ /]%M%*[ /-,]%y" "Mon 20 Mar 2000" "Mon 20/3 2000"
+//!	"%y-%M-%D"		      "2000-03-20", "00-03-20"
+//!     "%d"                          "20000320", "000320"
+//!	"-%y%*[ /]%D%*[ /]%M"	      "-00 20/3" "-00 20 mar"
+//!	"-%y%*[ /]%M%*[ /]%D"	      "-00 3/20" "-00 march 20"
+//!	"%y%*[ /]%D%*[ /]%M"	      "00 20 mar" "2000 20/3"
+//!	"%y%*[ /]%M%*[ /]%D"	      "2000 march 20"
+//!	"%D%*[ -/]%M"                 "20/3" "20 mar" "20-03"
+//!	"%M%*[ -/]%D"		      "3/20" "march 20"
+//!	"%e%*[ -/wv]%W%*[ -/]%y"      "mon w12 -00" "1 w12 2000"
+//!	"%e%*[ -/wv]%W"               "mon w12"
+//!     "%e"                          "monday" "1"
+//!     "today"                       "today"
+//!	"last %e"                     "last monday"
+//!	"next %e"                     "next monday"
+//!	</pre>
+//!
+//! note:
+//!	Casts exception if it fails to dwim out a day.
+//!	"dwim" means do-what-i-mean.
+
+/* tests:
+
+Calendar.dwim_day("2000-03-20 (Mar) -W12-1 (Mon)");
+Calendar.dwim_day("20/3/2000");
+Calendar.dwim_day("20 mar 2000"); 
+Calendar.dwim_day("20/3 -00");
+Calendar.dwim_day("Mon 20 Mar 2000" );
+Calendar.dwim_day("Mon 20/3 2000");
+Calendar.dwim_day("2000-03-20");
+Calendar.dwim_day("00-03-20");
+Calendar.dwim_day("20000320");
+Calendar.dwim_day("000320");
+Calendar.dwim_day("-00 20/3" );
+Calendar.dwim_day("-00 20 mar");
+Calendar.dwim_day("-00 3/20" );
+Calendar.dwim_day("-00 march 20");
+Calendar.dwim_day("00 20 mar" );
+Calendar.dwim_day("2000 20/3");
+Calendar.dwim_day("2000 march 20");
+Calendar.dwim_day("20/3" );
+Calendar.dwim_day("20 mar" );
+Calendar.dwim_day("20-03");
+Calendar.dwim_day("3/20" );
+Calendar.dwim_day("march 20");
+Calendar.dwim_day("mon w12 -00" );
+Calendar.dwim_day("1 w12 2000");
+Calendar.dwim_day("mon w12");
+Calendar.dwim_day("monday" );
+Calendar.dwim_day("1");
+Calendar.dwim_day("today");
+Calendar.dwim_day("last monday");
+Calendar.dwim_day("next monday");
+
+*/
+
+cDay dwim_day(string day)
+{
+   cDay d;
+
+   foreach ( ({ "%y-%M-%D (%*s) -W%W-%e (%e)",
+		"%D%*[ /]%M%*[- /,]%y",
+		"%M %D%*[- /,]%y",
+		"%e%*[ ]%D%*[ /]%M%*[-/ ,]%y",
+		"%y-%M-%D",
+		"-%y%*[ /]%D%*[ /]%M",
+		"-%y%*[ /]%M%*[ /]%D",
+		"%y%*[ /]%D%*[ /]%M",
+		"%y%*[ /]%M%*[ /]%D",
+		"%D%*[- /]%M",
+		"%M%*[- /]%D",
+		"%e%*[- /wv]%W%*[ -/]%y",
+		"%e%*[- /wv]%W",
+		"%d"}), 
+	     string dayformat)
+      if ( (d=parse(dayformat,day)) ) return d;
+
+   cDay t=Day();
+   if ( (d=parse("%e",day)) )
+   {
+      if (d>=t) return d;
+      else return (d->week()+1)->place(d);
+   }
+
+   if (strlen(day)==4) catch { return parse("%M/%D",day/2*"/"); };
+
+   if (day=="today") return t;
+   if (day=="tomorrow") return t+1;
+   if (day=="yesterday") return t-1;
+   if (sscanf(day,"last %s",day))
+   {
+      cDay d=dwim_day(day);
+      return (d->week()-1)->place(d);
+   }
+   if (sscanf(day,"next %s",day))
+   {
+      cDay d=dwim_day(day);
+      return (d->week()+1)->place(d);
+   }
+   
+   error("Failed to dwim day from %O\n",day);
+}
+
+TimeofDay dwim_time(string what)
+{
+   string a,h,m,s;
+   TimeofDay t;
+
+   foreach ( ({ " %z","%z",""}),
+	     string zone )
+   foreach ( ({ "%t",
+		"%h:%*[ :]%m%*[ :]:%s",
+		"%h:%*[ :]%m" }),
+	     string todformat )
+      foreach ( ({ "%y-%M-%D (%*s) -W%W-%e (%e)",
+		   "%D%*[ /]%M%*[- /,]%y",
+		   "%M %D%*[- /,]%y",
+		   "%e%*[ ]%D%*[ /]%M%*[-/ ,]%y",
+		   "%y-%M-%D",
+		   "%d",
+		   "-%y%*[ /]%D%*[ /]%M",
+		   "-%y%*[ /]%M%*[ /]%D",
+		   "%y%*[ /]%D%*[ /]%M",
+		   "%y%*[ /]%M%*[ /]%D",
+		   "%D%*[- /]%M",
+		   "%M%*[- /]%D",
+		   "%e%*[- /wv]%W%*[ -/]%y",
+		   "%e%*[- /wv]%W" }),
+		string dayformat )
+      {
+	 if ( (t=parse(dayformat+" "+todformat+zone,what)) ) return t;
+	 if ( (t=parse(todformat+zone+" "+dayformat,what)) ) return t;
+      }
+
+   error("Failed to dwim time from %O\n",what);
+}
+
+//-- auxillary functions------------------------------------------------
+
+//!
+//! function datetime(int|void unix_time)
+//!     Replacement for localtime; gives back a mapping:
+//!	<pre>
+//!	 ([ "year":     int        // year number (2000 AD=2000, 1 BC==0)
+//!	    "month":    int(1..)   // month of year
+//!	    "day":      int(1..)   // day of month
+//!	    "yearday":  int(1..)   // day of year
+//!	    "week":	int(1..)   // week of year
+//!	    "week_day": int(1..)   // day of week (depending on calendar)
+//!	    "unix":     int        // unix time
+//!	    "julian":   float      // julian day
+//!	    "hour":     int(0..)   // hour of day, including dst
+//!	    "minute":   int(0..59) // minute of hour
+//!	    "second":   int(0..59) // second of minute 
+//!	    "fraction": float      // fraction of second
+//!	    "timezone": int        // offset to utc, including dst
+//!	 ]);
+//!	</pre>
+//!	This is the same as calling <ref>Second</ref>()-><ref to=Second.datetime>datetime</ref>().
+//!
+//! function datetime_name(int|void unix_time)
+//! function datetime_short_name(int|void unix_time)
+//!     Compat functions; same as <ref>format_iso</ref>
+//!	and <ref>format_iso_short</ref>.
+//!	
+//! function string format_iso(void|int unix_time)
+//! function string format_iso_short(void|int unix_time)
+//! function string format_iso_tod(void|int unix_time)
+//! function string format_day_iso(void|int unix_time)
+//! function string format_day_iso_short(void|int unix_time)
+//!	Format the object into nice strings;
+//!	<pre>
+//!	iso    "2000-06-02 (Jun) -W22-5 (Fri) 11:57:18 CEST"
+//!     iso_short   "2000-06-02 11:57:18"
+//!	iso_tod     "11:57:18"
+//!	</pre>
+
+// Sane replacement for localtime().
+mapping(string:int) datetime(int|void unix_time)
+{
+   return Second("unix",unix_time||time())->datetime();
+}
+
+string datetime_name(int|void unix_time)
+{
+   return Second("unix",unix_time||time())->format_iso();
+}
+
+string datetime_short_name(int|void unix_time)
+{
+   return Second("unix",unix_time||time())->format_iso_short();
+}
+
+string format_iso(int|void unix_time)
+{
+   return Second("unix",unix_time||time())->format_iso();
+}
+
+string format_iso_short(int|void unix_time)
+{
+   return Second("unix",unix_time||time())->format_iso_short();
+}
+
+string format_iso_tod(int|void unix_time)
+{
+   return Second("unix",unix_time||time())->format_iso_tod();
+}
+
+string format_day_iso(int|void unix_time)
+{
+   return Day("unix",unix_time||time())->format_iso();
+}
+
+string format_day_iso_short(int|void unix_time)
+{
+   return Day("unix",unix_time||time())->format_iso_short();
+}
+
diff --git a/lib/modules/Calendar.pmod/localization.h b/lib/modules/Calendar.pmod/localization.h
new file mode 100644
index 0000000000000000000000000000000000000000..29c0cccc1becb6ab6ce36eef595f5628a1fa92ad
--- /dev/null
+++ b/lib/modules/Calendar.pmod/localization.h
@@ -0,0 +1,48 @@
+// This file is for the user or installer of pike
+// to modify after the local setup.
+
+// Note that you should modify this file
+// in pike's source location 
+// (.../lib/modules/Calendar.pmod/localization.pmod)
+// and reinstall, so the byte-compiling gets correct.
+
+
+
+// This should be the default calendar. Americans
+// use the Gregorian calendar as default - the big
+// difference is that the Gregorian calendar starts
+// the weeks on sundays, ISO on mondays.
+// Programs will probably get confused if this isn't
+// a year-month-day calendar, so don't put "Stardate" here.
+
+string default_calendar="ISO";
+// string default_calendar="Gregorian";
+
+
+// The timezone name is strings like "Europe/Stockholm" or "UTC".
+// There are two magic timezones, "locale", which
+// tries to do the best of the situation, and
+// "localtime" which uses localtime for rules (slow!).
+//
+// Check the TZs.h or TZnames.pmod for correct timezone names.
+//
+// Also note that "CET" or stuff like that shouldn't be
+// used unless you mean it - that summer time ruleset
+// might not be what you want.
+
+string default_timezone="locale"; 
+// string default_timezone="Europe/Stockholm";
+
+
+
+// The default language to use. This should probably
+// not be modified, since more then one program will
+// assume the language is english (=ISO).
+
+string default_language="ISO"; 
+
+
+
+
+
+
diff --git a/lib/modules/Calendar.pmod/mkrules.pike b/lib/modules/Calendar.pmod/mkrules.pike
new file mode 100644
index 0000000000000000000000000000000000000000..84d46b82b1c1b084066490c941988eb17a93aa32
--- /dev/null
+++ b/lib/modules/Calendar.pmod/mkrules.pike
@@ -0,0 +1,919 @@
+// this is a script to generate rules
+// from timezone data files;
+// ftp://elsie.nci.nih.gov/pub/ 
+// (timezone mailing list: tz@elsie.nci.nih.gov)
+//
+// source datafile are usually found somewhere around zic(8),
+// if they exist in the system.
+//
+// Most systems only have compiled files, just like pike,
+// and zic(8) is the usual compiler.
+
+// pike mkrules.pike ../data/{africa,antarctica,asia,australasia,backward,etcetera,europe,northamerica,pacificnew,southamerica,systemv}
+// $Id: mkrules.pike,v 1.1 2000/07/12 19:36:16 mirar Exp $
+
+
+object cal=Calendar.ISO->set_timezone("UTC");
+function Year=cal->Year;
+object nleapy=Year(1999);
+
+object tzrules; // needed to make timezones, compiled below
+
+mapping rules=([]);
+mapping zones=([]);
+mapping links=([]);
+array arules=({});
+array azones=({});
+
+#define FIXED(D)   (yjd+((D)-1))
+#define FIX_L(D)   (yjd+leap+((D)-1))
+#define LDAY(D,W)  (yjd+((D)-1)-( (yjd+((D)+(8-W)-1)) % 7))
+#define LDAYL(D,W) (yjd+((D)-1)+leap-( (yjd+leap+((D)+(8-W)-1)) % 7))
+
+#define FIXID(id) replace(id,"/-+"/1,"__p"/1)
+
+int parse_offset(string t)
+{
+   int h,m,s;
+   string res;
+
+   if (t=="0") return 0;
+
+   res="";
+   if (sscanf(t,"-%d:%d:%d%s",h,m,s,res)&&res=="")
+      return -(h*3600+m*60+s);
+   res="";
+   if (sscanf(t,"-%d:%d%s",h,m,res)&&res=="")
+      return -(h*3600+m*60);
+   res="";
+   if (sscanf(t,"%d:%d:%d%s",h,m,s,res)&&res=="")
+      return h*3600+m*60+s;
+   res="";
+   if (sscanf(t,"-%d:%d%s",h,m,res)&&res=="")
+      return h*3600+m*60;
+
+   complain("failed to parse offset %O\n",t);
+}
+
+array parse_tod(string t)
+{
+   int h,m,s;
+   string res;
+
+   if (t=="0") return 0;
+
+   if (sscanf(t,"%d:%d:%d%s",h,m,s,res)==4)
+      return ({h*3600+m*60+s,res});
+   res="";
+   if (sscanf(t,"%d:%d%s",h,m,res)==3)
+      return ({h*3600+m*60,res});
+   if (sscanf(t,"%d%s",h,res)==2)
+      return ({h*3600,res});
+
+   complain("failed to parse time of day %O\n",t);
+}
+
+class Shift
+{
+   string dayrule;
+   int time;
+   string timetype;
+   int offset;
+   string s;
+   string comment;
+
+   void create(array a)
+   {
+      switch (sizeof(a))
+      {
+	 case 5:
+	    dayrule=think_day(a[0],a[1]);
+	    comment=a[0]+" "+a[1];
+	    [time,timetype]=parse_tod(a[2]);
+	    switch (timetype)
+	    {
+	       case "": timetype="w"; break;
+	       case "s": case "u": case "w": break;
+	       default: complain("unknown time of day type %O\n",timetype);
+	    }
+	    offset=parse_offset(a[3]);
+	    s=(a[4]=="-")?"":a[4];
+	    break;
+	 case 6:
+	    [dayrule,comment,time,timetype,offset,s]=a;
+	    break;
+	 default:
+	    error("illegal size of a\n");
+      }
+   }
+
+   string _sprintf(int t) 
+   { 
+      return (t=='O')?
+	 sprintf("Shift(%s,%d%s,%+d,%O)",
+		 dayrule,time,timetype,offset,s):
+	 0;
+   }
+
+   int `==(Shift other)
+   {
+      return ( dayrule==other->dayrule &&
+	       time==other->time &&
+	       timetype==other->timetype &&
+	       offset==other->offset &&
+	       s==other->s );
+   }
+   function(Shift:int) __equal=`==;
+
+   constant wday=(["Mon":1,"Tue":2,"Wed":3,"Thu":4,"Fri":5,"Sat":6,"Sun":7]);
+   constant vmonth=(<"Jan","Feb","Mar","Apr","May","Jun",
+		     "Jul","Aug","Sep","Nov","Dec">);
+
+   string think_day(string mon,string rule)
+   {
+      int d;
+      string ds;
+
+      if (mon=="") return "0";
+      if (rule==(string)(d=(int)rule))
+      {
+	 if (mon=="Feb") return "FIXED("+(31+d)+")";
+	 if (mon=="Jan") return "FIXED("+(d)+")";
+	 return "FIX_L("+nleapy->month(mon)->day(d)->year_day()+")";
+      }
+      else if (sscanf(rule,"last%s",ds))
+      {
+	 int wd=wday[ds];
+	 if (!wd) complain("unknown weekday %O (last%s)\n",ds,ds);
+
+	 if (mon=="Jan") 
+	    return "LDAY ("+31+","+wd+")";
+
+	 return "LDAYL("+nleapy->month(mon)->day(-1)->year_day()+
+	    ","+wd+")";
+      }
+      else if (sscanf(rule,"%s>=%d",ds,d))
+      {
+	 int wd=wday[ds];
+	 if (!wd) complain("unknown weekday %O (last%s)\n",ds,ds);
+
+	 if (d>24 && mon=="Feb")
+	     complain("can't handle Feb %d in a >= rule\n",d);
+
+	 if (mon=="Jan") 
+	    return "LDAY ("+(nleapy->month(mon)->day(d)->year_day()+6)+
+	       ","+wd+")";
+
+	 return "LDAYL("+(nleapy->month(mon)->day(d)->year_day()+6)+
+	    ","+wd+")";
+      }
+      else if (sscanf(rule,"%s<=%d",ds,d))
+      {
+	 int wd=wday[ds];
+	 if (!wd) complain("unknown weekday %O (last%s)\n",ds,ds);
+
+	 if (d>24 && mon=="Feb")
+	     complain("can't handle Feb %d in a <= rule\n",d);
+
+	 if (mon=="Jan" || mon=="Feb")
+	    return "LDAY ("+(nleapy->month(mon)->day(d)->year_day())+
+	       ","+wd+")";
+
+	 return "LDAYL("+(nleapy->month(mon)->day(d)->year_day())+
+	    ","+wd+")";
+      }
+      else
+	 complain("unknown rule method %O\n",rule);
+   }
+
+   Shift|array ``+(array|Shift s)
+   {
+      if (!s) return this_object();
+      if (!arrayp(s)) s=({s});
+      return s+({this_object()});
+   }
+
+   int ldayl_is_fix_l(int d1,int wd,int d2,int yn1,int yn2)
+   {
+      object y1=Year(yn1);
+      object y2=Year(yn2);
+      int yjd,leap;
+
+      yjd=y1->julian_day();
+      leap=y1->leap_year();
+      int d1=LDAYL(d1,wd);
+
+      yjd=y2->julian_day();
+      leap=y2->leap_year();
+      int d2=FIX_L(d2);
+
+      return d1==d2;
+   }
+
+   Shift try_promote(Shift t,int y0,int y1)
+   {
+// this is year y0
+// t is year y1
+      if (t==this_object()) return t; // same!
+      if (t->time!=time ||
+	  t->timetype!=timetype ||
+	  t->offset!=offset ||
+	  t->s!=s) return 0; // no chance
+
+      int a,b,c;
+      if (sscanf(dayrule,"LDAYL(%d,%d)",a,b)==2 &&
+	  sscanf(t->dayrule,"FIX_L(%d)",c)==1)
+	 if (ldayl_is_fix_l(a,b,c,y0,y1)) 
+	    return this_object(); // ldayl
+	 else
+	    return 0; // no
+      if (sscanf(t->dayrule,"LDAYL(%d,%d)",a,b)==2 &&
+	  sscanf(dayrule,"FIX_L(%d)",c)==1)
+	 if (ldayl_is_fix_l(a,b,c,y1,y0)) 
+	    return t; // ldayl
+	 else
+	    return 0; // no
+
+      return 0;
+   }
+
+   string dump(int lastoffset,multiset ys)
+   {
+      string t;
+      array z=(array)ys;
+      int l=Year(z[0])->leap_year();
+      foreach (z[1..],int y) if (Year(y)->leap_year()!=l) { l=2; break; }
+      switch (timetype)
+      {
+	 case "s": t=sprintf("UO%+d",time); break;
+	 case "u": t=""+time; break;
+	 case "w": t=sprintf("UO%+d",(time-lastoffset)); break;
+	 default: error("illegal state\n");      
+      }
+      string r=dayrule;
+      if (l!=2)
+      {
+	 int d,w;
+	 if (sscanf(r,"FIX_L(%d)",d)) r=sprintf("FIXED(%d)",d+l);
+	 else if (sscanf(r,"LDAYL(%d,%d)",d,w)==2) 
+	    r=sprintf("LDAY (%d,%d)",d+l,w);
+      }
+      return sprintf("({%-12s,%-10s,%-5d,%-6O}),  %s",
+		     r,t,offset,s,comment!=""?"// "+comment:"");
+   }
+}
+
+class Rule
+{
+   string id;
+
+   mapping rules=([]);
+
+   int amt=0;
+
+   void create(string _id) { id=_id; }
+   
+   void add(string line)
+   {
+      array a= array_sscanf(line, replace("%s %s %s %s %s %s %s %[^\t ]",
+					  " ","%*[ \t]"));
+
+      if (sizeof(a)<8) complain("illegal rule line format\n");
+
+      if (!(int)a[0] && a[0]!="min")
+	 complain("unknown year %O\n",a[0]);
+
+// ---
+
+#define INF_YEAR 2050
+#define NUL_YEAR 1850
+
+      int y1=(int)a[0] || NUL_YEAR;
+      int y2;
+      if (a[1]=="max") y2=INF_YEAR; 
+      else if (a[1]=="only") y2=y1; 
+      else if (!(y2=(int)a[1]))
+	 complain("unknown year %O\n",a[1]);
+      else if (y2>=INF_YEAR)
+	 complain("big year\n");
+
+      Shift sh=Shift(a[3..]);
+
+      switch (a[2])
+      {
+	 case "-": for (;y1<=y2;y1++) rules[y1]+=sh; break;
+	 case "odd": 
+	    if (!(y1&1)) y1++;
+	    for (;y1<=y2;y1+=2) rules[y1]+=sh; 
+	    break;
+	 case "even": 
+	    if ((y1&1)) y1++;
+	    for (;y1<=y2;y1+=2) rules[y1]+=sh; 
+	    break;
+	 default:
+	    complain("unknown year type %O\n",a[2]);
+      }
+   }
+
+   string dump()
+   {
+      mapping r2=([]);
+      Shift last=Shift(({"0","?",0,"u",0,"?"}));
+      Shift first=last;
+      string res="";
+
+      if (!r2[NUL_YEAR]) r2[NUL_YEAR]=({last});
+
+      int y=min(@indices(rules));
+      for (;y<=INF_YEAR; y++)
+	 [r2[y],last]=mkperiods(rules[y],last,first);
+
+      res+=("class "+
+	    FIXID(id)+"\n"
+	    "{\n"
+	    "   inherit TZRules;\n"
+	    "   static array(array(string|int)) jd_year_periods(int jd)\n"
+	    "   {\n"
+	    "      [int y,int yjd,int leap]=gregorian_yjd(jd);\n"
+	    "      switch (y)\n"
+	    "      {\n");
+
+      string s="",t;
+
+      int y,mn=min(@indices(rules-(<NUL_YEAR>)));
+
+      for (y=INF_YEAR;sizeof(r2);y--)
+	 if (r2[y])
+	 {
+	    array z=r2[y];
+	    multiset my=(<y>);
+
+	    foreach (indices(r2),int y2)
+	       if (join_periods(z,r2[y2],y,y2))
+		  my[y2]=1;
+
+	    foreach ((array)my,int y2) m_delete(r2,y2);
+
+	    string t="";
+
+	    int y0=min(@(array)my);
+	    int y2=max(@(array)my);
+	    for (; y0<=y2; y0++)
+	       if (my[y0])
+	       {
+		  int y1=y0;
+		  while (my[++y1]);
+
+		  y1--;
+		  
+		  if (y0==NUL_YEAR)
+		  {
+		     if (my[INF_YEAR])
+			t+="         default: // .."+max(y1,mn-1)+
+			   " and ½½½..\n";
+		     else
+			t+="         default: // .."+max(y1,mn-1)+":\n";
+		  }
+		  else if (y0==y1)
+		     t+="         case "+y0+":\n";
+		  else if (y1==2050)
+		     { 
+			if (!my[NUL_YEAR]) t+="         case "+y0+"..:\n"; 
+			else t=replace(t,"½½½",(string)y0); 
+		     }
+		  else 		  
+		     t+="         case "+y0+".."+y1+":\n";
+
+		  y0=y1;
+	       }
+
+	    int lastoffset=0;
+	    string res=" "*12+"return ({";
+	    foreach (z,Shift s)
+	    {
+	       res+=s->dump(lastoffset,my)+("\n"+" "*21);
+	       lastoffset=s->offset;
+	    }
+	    array resa=res/"\n";
+	    resa[-2]=replace(resa[-2],",  ","});");
+	 
+	    t+=resa[..sizeof(resa)-2]*"\n"+"\n";
+	    s=t+s;
+	 }
+      res+=(s+
+	    "      }\n"
+	    "   }\n"
+	    "}\n\n");
+
+      return res;
+   }
+
+   int join_periods(array s,array t,int y0,int y1)
+   {
+      if (equal(s,t)) 
+	 return 1;
+      if (sizeof(s)!=sizeof(t)) return 0;
+      if (s[0]!=t[0]) return 0;
+// try promote
+      array q=s[..0];
+      int i;
+      for (i=1; i<sizeof(s); i++)
+      {
+	 Shift u=s[i]->try_promote(t[i],y0,y1);
+	 if (!u) return 0;
+	 q+=({u});
+      }
+      for (i=1; i<sizeof(s); i++)
+	 s[i]=q[i]; // destructive
+      return 1;
+   }
+
+   array(array(Shift)|Shift) mkperiods(array|Shift s,Shift last,Shift first)
+   {
+      if (!s) s=({});
+      if (!arrayp(s)) s=({s});
+      
+      sort(map(s,lambda(Shift s)
+		 {
+		    return array_sscanf(s->dayrule,"%*[^(](%d")[0];
+		 }),s);
+
+      if (first->s=="?")
+	 foreach (s,Shift d) if (!d->offset) first->s=d->s;
+
+      s=({last,@s});
+
+      last=Shift( ({"0","",0,"u",
+		    s[-1]->offset,s[-1]->s}) );
+
+      return ({s, last});
+   }
+}
+
+class Zone
+{
+   string id;
+
+   array rules=({});
+
+   void create(string _id) { id=_id; }
+
+   void add(string line)
+   {
+      array a= array_sscanf(line, replace("%s %s %s %s",
+					  " ","%*[ \t]"));
+      if (sizeof(a)<4)
+	 complain("parse error\n");
+      
+      array a=({parse_offset(a[0]), // offset
+		a[1], // rule or added offset
+		a[2], // string
+		a[3],
+		0, 0, "tz", 0}); // until
+      a[5]=rule_shift(a);
+      a[4]=clone_rule(a);
+
+      rules+=({a});
+   }
+
+   string clone_rule(array a)
+   {
+      int h,m,s,roff=-17;
+      if (a[1]=="-") roff=0;
+      else if (sscanf(a[1],"-%d:%d:%d",h,m,s)==3) roff=h*3600+m*60+s;
+      else if (sscanf(a[1],"%d:%d:%d",h,m,s)==3) roff=h*3600+m*60+s;
+      else if (sscanf(a[1],"-%d:%d",h,m)==2) roff=h*3600+m*60;
+      else if (sscanf(a[1],"%d:%d",h,m)==2) roff=h*3600+m*60;
+
+      if (roff==-17) // based on DST rule 
+	 return sprintf(
+	    "TZrules.%s(%d,%O)",
+	    FIXID(a[1]),-a[0],a[2]);
+      else // simple timezone
+	 return sprintf(
+	    "Ruleset.Timezone(%d,%O)",
+	    -(roff+a[0]),a[2]);
+   }
+
+   string rule_shift(array a)
+   {
+      if (a[3]=="" || a[3][0]=='#') return "forever";
+
+      string in=a[3];
+      sscanf(in,"until %s",in);
+      sscanf(in,"%s#",in);
+
+//        werror("%O\n",in);
+
+      int y,d=1,t=0;
+      string mn="Jan",ty="w";
+      if (sscanf(in,"%d%*[ \t]%s%*[ \t]%d%*[ \t]%[^# \t]",
+		 y,mn,d,string tod)==7 &&
+	  tod!="")
+	 [t,ty]=parse_tod(tod);
+      else if (!(sscanf(in,"%d%*[ \t]%[A-Za-z]%*[ \t]%d",y,mn,d)==5 ||
+		 (sscanf(in,"%d%*[ \t]%[A-Za-z]",y,mn)==3 && mn!="") ||
+		 (mn="Jan",sscanf(in,"%d",y))))
+      {
+//  	 werror("%O\n",array_sscanf(in,"%d%*[ \t]%[A-Za-z]"));
+	 complain("failed to understand UNTIL %O\n",in);
+	 y=2000;
+      }
+
+      int utc0=Year(y)->month(mn)->day(d)->unix_time();
+      switch (ty)
+      {
+	 case "u":     // utc time
+//  	    a[3]=sprintf("[%d+%d=%d] %s\n",utc0,t,utc0+t,a[3]);
+	    return (string)(utc0+t); break;  
+	 case "s":     // local standard time
+//  	    a[3]=sprintf("[%d+%d-%d=%d] %s\n",utc0,t,a[0],utc0+t-a[0],a[3]);
+	    return (string)(utc0+t-a[0]); break; 
+	 case "w": case "":       // with rule; check rule
+	    int h,m,s,roff=-17;
+	    if (a[1]=="-") roff=0;
+	    else if (sscanf(a[1],"-%d:%d:%d",h,m,s)==3) roff=h*3600+m*60+s;
+	    else if (sscanf(a[1],"%d:%d:%d",h,m,s)==3) roff=h*3600+m*60+s;
+	    else if (sscanf(a[1],"-%d:%d",h,m)==2) roff=h*3600+m*60;
+	    else if (sscanf(a[1],"%d:%d",h,m)==2) roff=h*3600+m*60;
+
+	    if (roff==-17) // based on DST rule
+	    {
+	       if (!tzrules) return 0; // can't do that now
+	       object|program rules=tzrules[FIXID(a[1])];
+	       if (!rules)
+	       {
+		  werror("ERROR: Missing rule %O (used in Zone %O)\n",a[1],id);
+		  return "[err]";
+	       }
+	       rules=rules(-a[0],"-");
+
+	       roff=rules->tz_jd(Year(y)->month(mn)->day(d)->julian_day())[0];
+
+//  	       werror("Using %O:%O\n",rules,roff);
+
+	       return (string)(utc0+t-roff); 
+	    }
+	    return (string)(utc0+t-a[0]-roff); 
+
+	 default:
+	    complain("unknown time of day modifier %O\n",ty);
+      }
+   }
+
+   string dump()
+   {
+      string cid=FIXID(id);
+      string res="";
+
+      if (!sizeof(rules))
+      {
+	 res+=("// skipped %O due to errors\n",id);
+	 return res;
+      }
+	       
+      if (sizeof(rules)==1) // simple zone
+      {
+	 res+=("Ruleset.Timezone "+cid+"="+
+	       rules[0][4]+";\n");
+	 return res;
+      }
+
+      mapping rname=([]);
+      int n=1;
+      
+      foreach (rules,array a)
+	 if (rname[a[4]]) a[6]=rname[a[4]];
+	 else a[6]=rname[a[4]]="tz"+n++;
+      
+      res+=("class "+cid+"\n"
+	    "{\n"
+	    "   inherit TZHistory;\n"
+	    "   Ruleset.Timezone "+
+	    sort(values(rname))*","+";\n"
+	    "   Ruleset.Timezone whatrule(int ux)\n"
+	    "   {\n"
+	    );
+
+      foreach (rules,array a)
+      {
+	 if (!a[5]) a[5]=rule_shift(a);
+
+	 string s="";
+	 sscanf(a[3],"%s#%*[ \t]%s",a[3],s);
+	 a[3]="from "+reverse(array_sscanf(reverse(a[3]),"%*[ \t]%s")[0]);
+	 a[7]=s;
+      }
+
+      array last=rules[-1];
+      int n=sizeof(rules);
+      foreach (reverse(rules)[1..],array a)
+      {
+	 res+=sprintf("      if (ux>=%s) // %s %s\n"
+		      "         return %s || (%s=%s);\n",
+		      a[5],a[3],last[7],last[6],last[6],last[4]);
+	 n--;
+	 last=a;
+      }
+      if (last[7]!="")
+	 res+=sprintf("      // %s\n",last[7]);
+      res+=sprintf("      return %s || (%s=%s);\n",
+		   last[6],last[6],last[4]);
+
+      res+=("   }\n"
+	    "}\n");
+      
+      return res;
+   }
+}
+
+void complain(string fmt,mixed ... args)
+{
+   throw( sprintf(fmt,@args) );
+}
+
+void collect_rules(string file)
+{
+   int n=0;
+   werror("reading %O...\n",file);
+   string s=Stdio.read_bytes(file),t;
+   if (!s) 
+   {
+      werror("%s:-: Failed to open file: %s\n",file,strerror(errno()));
+      return;
+   }
+
+   Zone lastz;
+   Rule lastr;
+
+   foreach (s/"\n",string line)
+   {
+      n++;
+      mixed err=catch 
+      {
+	 if (line[..0]!="#") 
+	    if (sscanf(line,"Zone%*[ \t]%[^ \t]%*[ \t]%s",s,t)==4)
+	    {
+	       if (zones[s]) lastz=zones[s]->add(t);
+	       else (lastz=zones[s]=Zone(s))->add(t),azones+=({lastz});
+	    }
+	    else if (sscanf(line,"Rule%*[ \t]%[^ \t]%*[ \t]%s",s,t)==4)
+	    {
+	       if (rules[s]) rules[s]->add(t);
+	       else (lastr=rules[s]=Rule(s))->add(t),arules+=({lastr});
+	       lastz=0;
+	    }
+	    else if (sscanf(line,"Link%*[ \t]%[^ \t]%*[ \t]%[^ \t]",s,t)==4)
+	    {
+	 // link t to s
+	       if (links[s]) links[s]+=({t});
+	       else links[s]=({t});
+	    }
+	    else if (sscanf(line,"%*[ \t]%[-0-9]%s",s,t)==3 && strlen(s))
+	    {
+	       if (!lastz) complain("implicit zone line w/o zone\n");
+	       lastz->add(s+t);
+	    }
+	    else if ((t="",sscanf(line,"%[ \t]",t),t==line))
+	       ;
+	    else if (sscanf(line,"%*[ \t]#%s",t,s)==2)
+	       ;
+	    else
+	       complain("unknown keyword %O...\n",line[..10]);
+      };
+      if (err)
+	 if (stringp(err))
+	    werror("%s:%d: %s",file,n,err);
+	 else
+	    throw(err);
+   }
+}
+
+int main(int ac,array(string) am)
+{
+   if (sizeof(am)<1)
+   {
+      werror("USAGE: %s datafile [datafile ...]\n",am[0]);
+      return 1;
+   }
+   map(am[1..],collect_rules);
+
+   write("thinking...\n");
+
+   string t=TZrules_base;
+
+   foreach (arules,Rule r)
+      t+=r->dump();
+
+   tzrules=compile_string(t)();
+
+   mv("TZrules.pmod","TZrules.pmod~");
+   werror("writing TZrules.pmod (%d bytes)...",strlen(t));
+   Stdio.File("TZrules.pmod","wtc")->write(t);
+   werror("\n");
+
+   t="// ----------------------------------------------------------------\n"
+      "// Timezones\n"
+      "//\n"
+      "// NOTE: this file is generated by mkrules.pike;\n"
+      "//       please do not edit manually /Mirar\n"
+      "// ----------------------------------------------------------------\n"
+      "\n"
+      "import \".\";\n\n";
+
+   t+=("// "+"-"*70+"\n"
+       "// Timezones\n"
+       "// "+"-"*70+"\n\n");
+
+   mixed err=catch {
+      foreach (azones,Zone z)
+         if (sizeof(z->rules)==1) 
+	 {
+	    t+=z->dump();
+	    if (links[z->id])
+	       foreach(links[z->id],string s)
+		  t+="Ruleset.Timezone "+FIXID(s)+"="+
+		     FIXID(z->id)+";\n";
+	 }
+   };
+   if (err) if (stringp(err)) error(err); else throw(err);
+
+   t+=("\n"
+       "// "+"-"*70+"\n"
+       "// Timezones with an attitude\n"
+       "// "+"-"*70+"\n"
+       "\n");
+
+   mixed err=catch {
+      foreach (azones,Zone z)
+	 if (sizeof(z->rules)!=1) 
+	 {
+	    t+=z->dump();
+	    if (links[z->id])
+	       foreach(links[z->id],string s)
+		  t+="constant "+FIXID(s)+"="+
+		     FIXID(z->id)+";\n";
+	    t+="\n";
+	 }
+   };
+   if (err) if (stringp(err)) error(err); else throw(err);
+
+   t+=("\n"
+       "// "+"-"*70+"\n");
+
+   mv("TZs.pike","TZs.pike~");
+   werror("writing TZs.h (%d bytes)...",strlen(t));
+   Stdio.File("TZs.h","wtc")->write(t);
+   werror("\n");
+
+   mapping zs=([]);
+   foreach (azones,Zone z)
+      if (sscanf(z->id,"%s/%s",string s,string t)==2)
+	 zs[s]=(zs[s]||({}))+({t});
+
+   t="// ----------------------------------------------------------------\n"
+      "// Timezone names\n"
+      "//\n"
+      "// NOTE: this file is generated by mkrules.pike;\n"
+      "//       please do not edit manually /Mirar\n"
+      "// ----------------------------------------------------------------\n"
+      "\n"
+      "mapping _module_value=\n"
+      "([\n";
+   foreach (indices(zs)-({"SystemV","Etc"}),string co)
+      t+=(replace(
+	 sprintf("   %-13s({%-=63s\n",
+		 sprintf("%O:",co),
+		 map(zs[co],lambda(string s) { return sprintf("%O",s); })
+		 *", "+"}),"),({",                 ",", "}),",,"/1));
+   t+="]);\n\n";
+   
+   mv("TZnames.pike","TZnames.pike~");
+   werror("writing TZnames.pmod (%d bytes)...",strlen(t));
+   Stdio.File("TZnames.pmod","wtc")->write(t);
+   werror("\n");
+
+   return 0;
+}
+
+
+string TZrules_base=
+#"// ----------------------------------------------------------------
+// Daylight savings and war time rules
+//
+// NOTE: this file is generated by mkrules.pike;
+//       please do not edit manually /Mirar
+// ----------------------------------------------------------------
+
+// ----------------------------------------------------------------
+// all rules are based on the gregorian calendar, so 
+// this is the gregorian rule:
+// ----------------------------------------------------------------
+
+static array gregorian_yjd(int jd)
+{
+   int d=jd-1721426;
+
+   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;
+
+   int y=century*100+century_year+1;
+
+   return 
+   ({
+      y,
+      1721426+century_year*365+century_year/4+century_jd,
+      (!(((y)%4) || (!((y)%100) && ((y)%400))))
+   });
+}
+
+// ----------------------------------------------------------------
+// Base \"Timezone with rules\" class
+// ----------------------------------------------------------------
+
+class TZRules
+{
+   constant is_timezone=1;
+   constant is_dst_timezone=1;
+   static int offset_to_utc;  
+   string name;
+
+   static function(string:string) tzformat;
+   static array names;
+
+   static void create(int offset,string _name) 
+   { 
+      offset_to_utc=offset; 
+      name=_name;
+      if (search(name,\"/\")!=-1)
+      {
+	 names=name/\"/\";
+	 tzformat=lambda(string s)
+		  {
+		     if (s==\"\") return names[0]; else return names[1];
+		  };
+      }
+      else
+	 tzformat=lambda(string s) { return sprintf(name,s); };
+   }
+
+// the Rule:
+// which julian day does dst start and end this year?
+   static array(array(string|int)) jd_year_periods(int jd);
+
+// is (midnight) this julian day dst?
+   array tz_jd(int jd)
+   {
+      array(array(string|int)) a=jd_year_periods(jd);
+
+      int i=0,n=sizeof(a)-1;
+      while (i<n)
+      {
+	 array b=a[i+1];
+	 if (jd<b[0]) break;
+	 if (jd==b[0] && -offset_to_utc+b[1]>=0) break;
+	 i++;
+      }
+
+      return ({offset_to_utc-a[i][2],tzformat(a[i][3])});
+   }
+
+// is this unixtime (utc) dst?
+   array tz_ux(int ux)
+   {
+      int jd=2440588+ux/86400;
+      array(array(string|int)) a=jd_year_periods(jd);
+
+      int i=0,n=sizeof(a)-1;
+      while (i<n)
+      {
+	 array b=a[i+1];
+	 if (jd<b[0]-1) break;
+	 if (jd<b[0]+1 &&
+	     ux<(b[0]-2440588)*86400+b[1]) break;
+	 i++;
+      }
+
+      return ({offset_to_utc-a[i][2],tzformat(a[i][3])});
+   }
+
+   string _sprintf(int t) { return (t=='O')?\"Timezone(\"+name+\")\":0; }
+
+   int raw_utc_offset() { return offset_to_utc; }
+}
+
+// ----------------------------------------------------------------------
+// DST Rules
+// ----------------------------------------------------------------------
+
+// useful macros
+#define FIXED(D)   (yjd+((D)-1))
+#define FIX_L(D)   (yjd+leap+((D)-1))
+#define LDAY(D,W)  (yjd+((D)-1)-( (yjd+((D)+(8-W)-1)) % 7))
+#define LDAYL(D,W) (yjd+((D)-1)+leap-( (yjd+leap+((D)+(8-W)-1)) % 7))
+#define UO offset_to_utc
+
+// ----------------------------------------------------------------------
+";
diff --git a/lib/modules/Calendar.pmod/module.pmod b/lib/modules/Calendar.pmod/module.pmod
index 302ac793ecb0d90c75c69a52141294345dfc2cc0..08b8d17334326d414b639f011a02c221d2c56084 100644
--- a/lib/modules/Calendar.pmod/module.pmod
+++ b/lib/modules/Calendar.pmod/module.pmod
@@ -1,167 +1,21 @@
+static private int stage=0;
+static private object defcal;
+static private multiset protect=(<"YMD">);
 
-//! 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>.
-//!
-//!	
-//!	Ie:<pre>
-//!	array(string) lesser()    - gives back a list of possible xxx's.
-//!	object xxxs()     	  - gives back a list of possible n's.
-//!	object xxx(mixed n)       - gives back xxx n
-//!	object xxx(object(Xxx) o) - gives back the corresponing xxx 
-//!	</pre>
-//!
-//!	The list of n's (as returned from xxxs) are always in order.
-//!
-//!	There are two n's with special meaning, 0 and -1.
-//!	0 always gives the first xxx, equal to 
-//!	my_obj->xxx(my_obj->xxxs()[0]), and -1 gives the last,
-//!	equal to my_obj->xxx(my_obj->xxxs()[-1]).
-//!
-//!	To get all xxxs in the object, do something like
-//!	<tt>Array.map(my_obj->xxxs(),my_obj->xxx)</tt>.
-//!
-//!	xxx(object) may return zero, if there was no correspondning xxx.
-//!
-//! 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.
+#include "localization.h"
 
-#define error(X) throw(({(X),backtrace()}))
-
-class _TimeUnit
-{
-   object this=this_object();
-
-   array(string) greater() { return ({}); }
-   array(string) lesser() { return ({}); }
-
-   int `<(object x) { error("'< undefined\n"); }
-   int `>(object x) { error("'> undefined\n"); }
-   int `==(object x) { error("'== undefined\n"); }
-
-   object `+(int n) { error("`+ undefined\n"); }
-   object|int `-(int n) { error("`- undefined\n"); }
-
-   object next() { return this+1; }
-   object prev() { return this+(-1); }
-}
-
-
-
-
-
-string print_month(void|object month,void|mapping options)
+#if 1
+mixed `[](string what)
 {
-   object w;
-   object today;
-   string res="";
-
-   if (!month)  // resolv thing here is to avoid compile-time resolve
-      month=master()->resolv("Calendar")["Gregorian"]["Month"]();
-
-   options=(["mark_today":1,
-	     "week_space":3,
-	     "weeks":1,
-	     "days":1,
-	     "title":1,
-	     "notes":([])]) | (options || ([]));
-   options=(["date_space":(options->mark_today?3:2)])|options;
-
-
-   today=function_object(object_program(month))->Day();
-
-   w=month->day(1)->week();
-
-   res="";
-   if (options->weeks) res+=" "+" "*options->week_space;
-   if (options->title)
-      res+=sprintf("%|*s\n",
-		   (1+options->date_space)*sizeof(w->days())-1,
-		   intp(options->title)
-		   ?(String.capitalize(month->name()+" ")
-		     +month->year()->name())
-		   :options->title);
-
-   if (options->days)
+   if ( protect[what] ) return ([])[0];
+   if (!defcal)
    {
-      if (options->weeks) res+=" "+" "*options->week_space;
-      foreach (Array.map(w->days(),w->day)->week_day_name(),string n)
-	 res+=sprintf("%*s ",options->date_space,n[0..options->date_space-1]);
-      res+="\n";
+      if (stage) return ([])[0];
+      stage++;
+      defcal=master()->resolv("Calendar")[default_calendar];
    }
-
-   string daynotes="";
-
-   if (sizeof(Array.filter(
-      Array.map(month->days(),month->day),
-      lambda(object d) { return !!options->notes[d]; })))
-      daynotes="\n%-|"+options->date_space+"s";
-
-   do
-   {
-      array a;
-      array b;
-      object d;
-      string format="";
-
-      a=Array.map(Array.map(w->days(),w->day),
-		  lambda(object d) 
-		  { if (d->month()!=month) return 0; else return d; });
-
-      if (options->weeks)
-	 res+=sprintf("%*s ",options->week_space,w->name());
-      foreach (a,d)
-	 if (d)
-	    if (!options->mark_today || d!=today) 
-	       res+=sprintf("%* |d ",
-			    options->date_space,
-			    d->month_day());
-	    else 
-	       res+=sprintf(">%* |d<",
-			    options->date_space-1,
-			    d->month_day());
-	 else res+=" "+" "*options->date_space;
-
-      if (options->notes[w])
-	 res+=sprintf("%-=*s",
-		      options->week_note_column_width,
-		      options->notes[w]);
-
-      res+="\n";
-
-      if (daynotes)
-      {
-	 
-      }
-
-      w++;
-   }
-   while (w->day(0)->month()==month);
-
-   return res;
+   if (what=="II") return 1; // Calendar.II
+   return defcal[what];
 }
+mixed `-> = `[];
+#endif
diff --git a/lib/modules/Calendar_I.pmod/Austrian.pmod b/lib/modules/Calendar_I.pmod/Austrian.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..216139e91bcd13c9dab722b6ca239bc9e29f965c
--- /dev/null
+++ b/lib/modules/Calendar_I.pmod/Austrian.pmod
@@ -0,0 +1,36 @@
+// by Martin Baehr <mbaehr@email.archlab.tuwien.ac.at>
+
+inherit Calendar.ISO:ISO;
+
+void create()
+{
+   month_names=
+      ({"jänner","feber","märz","april","mai","juni","juli","august",
+        "september","oktober","november","dezember"});
+
+   week_day_names=
+      ({"montag","dienstag","mittwoch","donnerstag",
+        "freitag","samstag","sonntag"});
+}
+
+class Week
+{
+   inherit ISO::Week;
+
+   string name()
+   {
+      return "w"+(string)this->number();
+   }
+}
+
+class Year
+{
+   inherit ISO::Year;
+
+   string name()
+   {
+      if (this->number()<=0)
+         return (string)(1-this->number())+" v. Chr.";
+      return (string)this->number();
+   }
+}
diff --git a/lib/modules/Calendar_I.pmod/Gregorian.pmod b/lib/modules/Calendar_I.pmod/Gregorian.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..c4d170c5d23fd7cd6dbb59dca476abaa2b68b502
--- /dev/null
+++ b/lib/modules/Calendar_I.pmod/Gregorian.pmod
@@ -0,0 +1,1543 @@
+// 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>. 
+//!
+//!	Lesser units: <ref>Month</ref>, <ref>Week</ref>, <ref>Day</ref>
+//!	Greater units: none
+//!
+//!     
+   inherit _TimeUnit;
+
+//-- variables ------------------------------------------------------
+
+   int y;
+
+   array days_per_month;
+   array month_start_day;
+
+//-- standard methods -----------------------------------------------
+
+   string is()
+   {
+      return "year";
+   }
+
+   array(string) lesser() 
+   { 
+      return ({"month","week","day"});
+   }
+
+   array(string) greater()
+   {
+      return ({});
+   }
+
+   void create(int ... arg)
+   {
+      if (!sizeof(arg))
+      {
+	 object yp=vDay()->year();
+	 y=yp->y;
+      }
+      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 hash() { return y*113; }
+
+   int `>(object x)
+   {
+      return y>(int)x;
+   }
+
+   object next()
+   {
+      return vYear(y+1);
+   }
+
+   object prev()
+   {
+      return vYear(y-1);
+   }
+
+   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 leap_day()
+   {
+      return 31+24-1; // 24 Feb
+   }
+
+   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(object|string|int n)
+   {
+      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);
+	 }
+	 n=month_mapping[lower_case(n)];
+	 if (!n) return 0;
+      }
+
+      if (n<0)
+	 return vMonth(y,13+n);
+      else
+	 return vMonth(y,n||1);
+   }
+
+   array(mixed) months()
+   {
+      return month_names;
+   }
+
+   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 */
+	 }
+
+      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(object|int n)
+   {
+      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++;
+	    }
+	    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()
+   {
+       return indices(allocate(this->number_of_days()));
+   }
+
+//-- 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()
+   {
+      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|object n)
+   {
+      if (objectp(n))
+	 if (object_program(n)==vDay)
+	 {
+	    n=n->month_day();
+	    if (n>number_of_days()) return 0; /* no such day */
+	 }
+
+      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
+{
+   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)
+   {
+      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 hash() { return y*811+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);
+   }
+
+//-- 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()
+   {
+      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|object n)
+   {
+      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];
+      }
+      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()
+   {
+       return ({0,1,2,3,4,5,6});
+   }
+
+//-- more -----------------------------------------------------------
+     
+   object year()
+   {
+      return vYear(y);
+   }
+};
+
+//
+//== Day =====================================================================
+
+class Day
+{
+   inherit _TimeUnit;
+
+//-- variables ------------------------------------------------------
+
+   int y;
+   int d;
+
+//-- standard methods -----------------------------------------------
+
+   string is()
+   {
+      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)());
+	 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");
+
+	 }
+	 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];
+      } 
+   }
+
+   int `<(object x)
+   {
+      return 
+	 (object_program(x)==object_program(this) &&
+	  (x->y==y && x->d<d) || (x->y<y)) ||
+	 (x->julian_day()<julian_day());
+   }
+
+   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)
+   {
+      return 
+	 (object_program(x)==object_program(this) &&
+	  (x->y==y && x->d>d) || (x->y>y)) ||
+	 (x->julian_day()>julian_day());
+   }
+
+   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);
+   }
+
+//-- 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;
+   }
+};
+
+
+//
+//== Minute ===================================================================
+
+class Minute
+{
+   inherit _TimeUnit;
+
+//-- variables ------------------------------------------------------
+
+   object h;
+   int m;
+
+//-- standard methods -----------------------------------------------
+
+   string is()
+   {
+      return "minute";
+   }
+
+   array(string) greater()
+   {
+      return ({"hour"});
+   } 
+
+   array(string) lesser()
+   {
+      return ({"second"});
+   }
+
+   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);
+}
diff --git a/lib/modules/Calendar_I.pmod/ISO.pmod b/lib/modules/Calendar_I.pmod/ISO.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..214f6a709b30af38922540416953b0a83cceab53
--- /dev/null
+++ b/lib/modules/Calendar_I.pmod/ISO.pmod
@@ -0,0 +1,247 @@
+// IS-8601, international standard
+
+inherit Calendar.Gregorian:Gregorian;
+
+class Year
+{
+   inherit Gregorian::Year;
+
+   int leap_day()
+   {
+      if (y>1999) return 31+29-1; // 29 Feb
+      return 31+24-1; // 24 Feb
+   }
+
+   string name()
+   {
+      return (string)y;
+   }
+}
+
+class Month
+{
+   inherit Gregorian::Month;
+
+   string iso_name()
+   {
+      return sprintf("%04d-%02d",
+		     (int)this->year(),
+		     (int)this);
+   }
+  
+   string iso_short_name()
+   {
+      return name()-"-";
+   }
+}
+  
+class Week
+{
+   inherit Gregorian::Week;
+
+   int yday()
+   {
+      return 
+	 ({0,-1,-2,-3,3,2,1})[this->year()->julian_day(0)%7]
+         +7*(w-1);
+   }
+
+   array(mixed) days()
+   {
+       return ({1,2,3,4,5,6,7});
+   }
+  
+   string iso_name()
+   {
+      return sprintf("%04d-W%02d",
+		     (int)this->year(),
+		     (int)this);
+   }
+  
+   string iso_short_name()
+   {
+      return name()-"-";
+   }
+  
+   object day(int|string|object n)
+   {
+      if (stringp(n)) 
+      {
+	 if (!week_day_mapping)
+	    week_day_mapping=
+	       mkmapping(Array.map(week_day_names,lower_case),
+			 ({1,2,3,4,5,6,7}));
+	 n=week_day_mapping[n];
+      }
+      else if (objectp(n))
+	 if (object_program(n)==vDay)
+	    n=n->week_day();
+	 else return 0;
+
+      if (n<0) n=8+n;
+      else if (!n) n=1;
+      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);
+   }
+}
+
+class Day
+{
+   inherit Gregorian::Day;
+
+   int week_day()
+   {
+      return julian_day()%7+1;
+   }
+
+   string week_day_name()
+   {
+//       werror("week_days: %O\n",week_day_names);
+      return week_day_names[(this->week_day()+6)%7];
+   }
+
+   string iso_name()
+   {
+      return sprintf("%04d-%02d-%02d",
+		     (int)this->year(),
+		     (int)this->month(),
+		     (int)this->month_day());
+   }
+
+   string iso_short_name()
+   {
+      return iso_name()-"-";
+   }
+
+   string iso_name_by_week()
+   {
+      return sprintf("%04d-W%02d-%d",
+		     (int)this->year(),
+		     (int)this->week(),
+		     (int)this->week_day());
+   }
+  
+   string iso_name_by_yearday()
+   {
+      return sprintf("%04d-%03d",
+		     (int)this->year(),
+		     (int)this->year_day());
+   }
+  
+   string iso_short_name_by_yearday()
+   {
+      return iso_name_by_yearday()-"-";
+   }
+  
+   object week()
+   {
+      int n;
+      object ye=this->year();
+      n=(-({0,-1,-2,-3,3,2,1})[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);
+   }
+}
+
+static private class _Day
+{
+   // FIXME: Kludge because the day object does not exist in
+   // Minute and Second. This function will be shadowed in Hour.
+   object day()
+   {
+      return this_object()->hour()->day();
+   }
+}
+
+static private class Name
+{
+   object this = this_object();
+
+   string iso_name()
+   {
+      return this->day()->iso_name()+this->_iso_name();
+   }
+  
+   string iso_short_name()
+   {
+      return this->day()->iso_short_name()+this->_iso_short_name();
+   }
+  
+   string iso_name_by_week()
+   {
+      return this->day()->iso_name_by_week()+this->_iso_name();
+   }
+  
+   string iso_name_by_yearday()
+   {
+      return this->day()->iso_name_by_yearday()+this->_iso_name();
+   }
+  
+   string iso_short_name_by_yearday()
+   {
+      return this->day()->iso_short_name_by_yearday()+this->_iso_short_name();
+   }
+}
+
+class Hour
+{
+   inherit Gregorian::Hour;
+   inherit Name;
+
+   string _iso_name()
+   {
+      return sprintf("T%02d",
+		     (int)this);
+   }
+
+   string _iso_short_name()
+   {
+      return _iso_name();
+   }
+}
+
+class Minute
+{
+   inherit _Day;
+   inherit Gregorian::Minute;
+   inherit Name;
+
+   string _iso_name()
+   {
+      return sprintf("T%02d:%02d",
+		     (int)this->hour(),
+		     (int)this);
+   }
+
+   string _iso_short_name()
+   {
+      return _iso_name()-":";
+   }
+}
+
+class Second
+{
+   inherit _Day;
+   inherit Gregorian::Second;
+   inherit Name;
+
+   string _iso_name()
+   {
+      return sprintf("T%02d:%02d:%02d",
+		     (int)this->hour(),
+		     (int)this->minute(),
+		     (int)this);
+   }
+
+   string _iso_short_name()
+   {
+      return _iso_name()-":";
+   }
+}
+
diff --git a/lib/modules/Calendar_I.pmod/Julian.pmod b/lib/modules/Calendar_I.pmod/Julian.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..7c03a20b858cc0e31f5795e7de6f5f34fd9b1a64
--- /dev/null
+++ b/lib/modules/Calendar_I.pmod/Julian.pmod
@@ -0,0 +1,35 @@
+inherit Calendar.Gregorian;
+
+class Year
+{
+  inherit Calendar.Gregorian.Year;
+
+  int julian_day(int d) // jd%7 gives weekday, mon=0, sun=6
+  {
+    return 1721424 + d + (36525*(y-1))/100;
+  }
+
+  int leap()
+  {
+    return !(y%4);
+  }
+
+}
+
+class Day
+{
+  inherit Calendar.Gregorian.Day;
+
+  void create(int ... arg)
+  {
+    if (!sizeof(arg))
+    {
+      int jd = Calendar.Gregorian.Day()->julian_day()-1721424;
+      y = jd*100/36525+1;
+      d = jd-(y-1)*36525/100;
+    }
+    else
+      ::create(@arg);
+  }
+
+}
diff --git a/lib/modules/Calendar_I.pmod/Orthodox.pmod b/lib/modules/Calendar_I.pmod/Orthodox.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..faa7de36e9f5f085cd08301914476fcda1d0969c
--- /dev/null
+++ b/lib/modules/Calendar_I.pmod/Orthodox.pmod
@@ -0,0 +1,25 @@
+// by Mirar 
+
+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_I.pmod/Stardate.pmod b/lib/modules/Calendar_I.pmod/Stardate.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..a91e964fca62279d71949e5522cb65a7fa45aa73
--- /dev/null
+++ b/lib/modules/Calendar_I.pmod/Stardate.pmod
@@ -0,0 +1,106 @@
+//! submodule Stardate
+//!	time unit: TNGDate
+
+//! class TNGDate
+//!	implements ST:TNG stardates
+//!	can be used as create argument to Day 
+
+class TNGDate
+{
+   inherit Calendar._TimeUnit;
+
+   // 40759.5  2363-10-05  2584405
+   // 47391.2  2370-05-23  2586827
+
+   // 50893.5  2373-11-23  2588107
+
+   //  6631.7  ----------  2422 
+   // 10134.0  ----------  3702
+   //  1000.0  ----------  365.2425
+   //     0.0      -  -    2569519
+#define TNGSTARPERJULIAN (1000.0/365.2425)
+
+//-- variables ------------------------------------------------------
+
+   float jd;
+   float tics;
+   
+//-- standard methods -----------------------------------------------
+
+   void create(int|float|object ... day)
+   {
+      float jd;
+      if (!sizeof(day))
+	 day=({Calendar.Gregorian.Second()});
+      else if (floatp(day[0]))
+      {
+	 from_stardate(day[0]);
+	 return;
+      }
+      if (!intp(day[0]))
+      {
+	 object o=day[0];
+
+	 if (o->julian_day || o->julian_day_f)
+	    jd=(float)(o->julian_day_f||o->julian_day)();
+	 else // dig
+	    if (o->day) // larger
+	    {
+	       o=o->day(0);
+	       if (o->julian_day_f)
+		  jd=o->julian_day_f();
+	       else if (o->julian_day)
+		  jd=(float)o->julian_day();
+	       else
+		  ; // error, like
+	    }
+	    else // smaller
+	    {
+	       float z=1.0;
+	       while (sizeof(o->greater()))
+	       {
+		  string name=o->is();
+		  o=o[o->greater()[0]]();
+		  z*=o["number_of_"+name+"s"]();
+		  if (o->julian_day_f || o->julian_day) 
+		  {
+		     jd=(o->julian_day||o->julian_day_f)()/z;
+		     break;
+		  }
+	       }
+	    }
+      }
+      else 
+	 jd=(float)day[0];
+      from_julian_day(jd);
+   }
+
+   static void from_stardate(float f)
+   {
+      tics=f;
+      jd=f/TNGSTARPERJULIAN+2569518.5;
+   }
+
+   static void from_julian_day(float f)
+   {
+      jd=f;
+      tics=(f-2569518.5)*TNGSTARPERJULIAN;
+   }
+
+//-- nonstandard methods --------------------------------------------
+
+   float number()
+   {
+      return tics;
+   }
+   
+   int julian_day()
+   {
+      return (int)jd;
+   }
+
+   float julian_day_f()
+   {
+      return jd;
+   }
+}
diff --git a/lib/modules/Calendar_I.pmod/Swedish.pmod b/lib/modules/Calendar_I.pmod/Swedish.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..861bd0a7f8fb3c7690cf34fc7407f1c5452d66c2
--- /dev/null
+++ b/lib/modules/Calendar_I.pmod/Swedish.pmod
@@ -0,0 +1,238 @@
+// by Mirar 
+
+inherit Calendar.ISO:ISO;
+
+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 ISO::Week;
+
+   string name()
+   {
+      return "v"+(string)this->number();
+   }
+}
+
+class Year
+{
+   inherit ISO::Year;
+
+   array(array(string)) _namedays;
+   mapping(string:int) _nameday_lookup;
+
+   string name()
+   {
+      if (this->number()<=0) 
+	 return (string)(1-this->number())+" fk";
+      return (string)this->number();
+   }
+
+   array(array(string)) namedays()
+   {
+      if (_namedays) return _namedays;
+
+      array(array(string)) a;
+
+      // insert test for year here
+      if (!(a=namedays_cache[this->leap()+" "+this->leap_day()]))
+      {
+      // insert test for year here
+	 a=namedays_1993;
+
+	 if (this->leap())
+	 {
+	    a=a[..this->leap_day()-1]+
+	       Array.map(allocate(this->leap()),
+			 lambda(int x) { return ({}); })+
+	       a[this->leap_day()..];
+	 }
+
+	 namedays_cache[this->leap()+" "+this->leap_day()]=a;
+      }
+
+      return _namedays=a;
+   }
+
+   object nameday(string name)
+   {
+      if (!_nameday_lookup
+	 && !(_nameday_lookup=
+	      namedays_lookup_cache[this->leap()+" "+this->leap_day()]))
+      {
+	 mapping m=([]);
+	 int i;
+	 foreach (this->namedays(),array a)
+	 {
+	    foreach (a,string name) m[lower_case(name)]=i;
+	    i++;
+	 }
+	 _nameday_lookup =
+	    namedays_lookup_cache[this->leap()+" "+this->leap_day()] = m;
+      }
+      
+      if (zero_type(_nameday_lookup[lower_case(name)])) return 0;
+      return this->day(_nameday_lookup[lower_case(name)]);
+   }
+}
+
+class Day
+{
+   inherit ISO::Day;
+
+   array(string) names()
+   {
+      return this->year()->namedays()[this->year_day()];
+   }
+}
+
+// --- namnsdagar, data -------------------------------------------------
+
+mapping namedays_cache=([]);
+mapping namedays_lookup_cache=([]);
+
+/**
+
+Name database from alma-1.0, 
+http://www.lysator.liu.se/~tab/alma-1.0.tar.gz
+
+Permission to use from Kent Engström, 1998-01-28
+
+ **/
+
+
+array(array(string)) namedays_1993= 
+({ ({}), ({"Svea","Sverker"}), ({"Alfred","Alfrida"}),
+   ({"Rut","Ritva"}), ({"Hanna","Hannele"}), ({"Baltsar","Kasper"}),
+   ({"August","Augusta"}), ({"Erland","Erhard"}), ({"Gunnar","Gunder"}),
+   ({"Sigurd","Sigmund"}), ({"Hugo","Hagar"}), ({"Frideborg","Fridolf"}),
+   ({"Knut"}), ({"Felix","Felicia"}), ({"Laura","Liv"}),
+   ({"Hjalmar","Hervor"}), ({"Anton","Tony"}), ({"Hilda","Hildur"}),
+   ({"Henrik","Henry"}), ({"Fabian","Sebastian"}), ({"Agnes","Agneta"}),
+   ({"Vincent","Veine"}), ({"Emilia","Emilie"}), ({"Erika","Eira"}),
+   ({"Paul","Pål"}), ({"Bodil","Boel"}), ({"Göte","Göta"}),
+   ({"Karl","Karla"}), ({"Valter","Vilma"}), ({"Gunhild","Gunilla"}),
+   ({"Ivar","Joar"}), ({"Max","Magda"}), ({"Marja","Mia"}),
+   ({"Disa","Hjördis"}), ({"Ansgar","Anselm"}), ({"Lisa","Elise"}),
+   ({"Dorotea","Dora"}), ({"Rikard","Dick"}), ({"Berta","Berthold"}),
+   ({"Fanny","Betty"}), ({"Egon","Egil"}), ({"Yngve","Ingolf"}),
+   ({"Evelina","Evy"}), ({"Agne","Agnar"}), ({"Valentin","Tina"}),
+   ({"Sigfrid","Sigbritt"}), ({"Julia","Jill"}),
+   ({"Alexandra","Sandra"}), ({"Frida","Fritz"}), ({"Gabriella","Ella"}),
+   ({"Rasmus","Ruben"}), ({"Hilding","Hulda"}), ({"Marina","Marlene"}),
+   ({"Torsten","Torun"}), ({"Mattias","Mats"}), ({"Sigvard","Sivert"}),
+   ({"Torgny","Torkel"}), ({"Lage","Laila"}), ({"Maria","Maja"}),
+   ({"Albin","Inez"}), ({"Ernst","Erna"}), ({"Gunborg","Gunvor"}),
+   ({"Adrian","Ada"}), ({"Tora","Tor"}), ({"Ebba","Ebbe"}),
+   ({"Isidor","Doris"}), ({"Siv","Saga"}), ({"Torbjörn","Ambjörn"}),
+   ({"Edla","Ethel"}), ({"Edvin","Elon"}), ({"Viktoria","Viktor"}),
+   ({"Greger","Iris"}), ({"Matilda","Maud"}), ({"Kristofer","Christel"}),
+   ({"Herbert","Gilbert"}), ({"Gertrud","Görel"}), ({"Edvard","Eddie"}),
+   ({"Josef","Josefina"}), ({"Joakim","Kim"}), ({"Bengt","Benny"}),
+   ({"Viking","Vilgot"}), ({"Gerda","Gert"}), ({"Gabriel","Rafael"}),
+   ({"Mary","Marion"}), ({"Emanuel","Manne"}), ({"Ralf","Raymond"}),
+   ({"Elma","Elmer"}), ({"Jonas","Jens"}), ({"Holger","Reidar"}),
+   ({"Ester","Estrid"}), ({"Harald","Halvar"}), ({"Gunnel","Gun"}),
+   ({"Ferdinand","Florence"}), ({"Irene","Irja"}), ({"Nanna","Nanny"}),
+   ({"Vilhelm","Willy"}), ({"Irma","Mimmi"}), ({"Vanja","Ronja"}),
+   ({"Otto","Ottilia"}), ({"Ingvar","Ingvor"}), ({"Ulf","Ylva"}),
+   ({"Julius","Gillis"}), ({"Artur","Douglas"}), ({"Tiburtius","Tim"}),
+   ({"Olivia","Oliver"}), ({"Patrik","Patricia"}), ({"Elias","Elis"}),
+   ({"Valdemar","Volmar"}), ({"Olaus","Ola"}), ({"Amalia","Amelie"}),
+   ({"Annika","Anneli"}), ({"Allan","Alida"}), ({"Georg","Göran"}),
+   ({"Vega","Viveka"}), ({"Markus","Mark"}), ({"Teresia","Terese"}),
+   ({"Engelbrekt","Enok"}), ({"Ture Tyko"}), ({"Kennet","Kent"}),
+   ({"Mariana","Marianne"}), ({"Valborg","Maj"}), ({"Filip","Filippa"}),
+   ({"John","Jack"}), ({"Monika","Mona"}), ({"Vivianne","Vivan"}),
+   ({"Marit","Rita"}), ({"Lilian","Lilly"}), ({"Åke","Ove"}),
+   ({"Jonatan","Gideon"}), ({"Elvira","Elvy"}), ({"Märta","Märit"}),
+   ({"Charlotta","Lotta"}), ({"Linnea","Nina"}), ({"Lillemor","Lill"}),
+   ({"Sofia","Sonja"}), ({"Hilma","Hilmer"}), ({"Nore","Nora"}),
+   ({"Erik","Jerker"}), ({"Majken","Majvor"}), ({"Karolina","Lina"}),
+   ({"Konstantin","Conny"}), ({"Henning","Hemming"}),
+   ({"Desiree","Renee"}), ({"Ivan","Yvonne"}), ({"Urban","Ursula"}),
+   ({"Vilhelmina","Helmy"}), ({"Blenda","Beda"}),
+   ({"Ingeborg","Borghild"}), ({"Jean","Jeanette"}),
+   ({"Fritiof","Frej"}), ({"Isabella","Isa"}), ({"Rune","Runa"}),
+   ({"Rutger","Roger"}), ({"Ingemar","Gudmar"}),
+   ({"Solveig","Solbritt"}), ({"Bo","Boris"}), ({"Gustav","Gösta"}),
+   ({"Robert","Robin"}), ({"Eivor","Elaine"}), ({"Petra","Petronella"}),
+   ({"Kerstin","Karsten"}), ({"Bertil","Berit"}), ({"Eskil","Esbjörn"}),
+   ({"Aina","Eila"}), ({"Håkan","Heidi"}), ({"Margit","Mait"}),
+   ({"Axel","Axelina"}), ({"Torborg","Torvald"}), ({"Björn","Bjarne"}),
+   ({"Germund","Jerry"}), ({"Linda","Linn"}), ({"Alf","Alva"}),
+   ({"Paulina","Paula"}), ({"Adolf","Adela"}), ({"Johan","Jan"}),
+   ({"David","Salomon"}), ({"Gunni","Jim"}), ({"Selma","Herta"}),
+   ({"Leo","Leopold"}), ({"Petrus","Peter"}), ({"Elof","Leif"}),
+   ({"Aron","Mirjam"}), ({"Rosa","Rosita"}), ({"Aurora","Adina"}),
+   ({"Ulrika","Ulla"}), ({"Melker","Agaton"}), ({"Ronald","Ronny"}),
+   ({"Klas","Kaj"}), ({"Kjell","Tjelvar"}), ({"Jörgen","Örjan"}),
+   ({"Anund","Gunda"}), ({"Eleonora","Ellinor"}), ({"Herman","Hermine"}),
+   ({"Joel","Judit"}), ({"Folke","Odd"}), ({"Ragnhild","Ragnvald"}),
+   ({"Reinhold","Reine"}), ({"Alexis","Alice"}), ({"Fredrik","Fred"}),
+   ({"Sara","Sally"}), ({"Margareta","Greta"}), ({"Johanna","Jane"}),
+   ({"Magdalena","Madeleine"}), ({"Emma","Emmy"}),
+   ({"Kristina","Stina"}), ({"Jakob","James"}), ({"Jesper","Jessika"}),
+   ({"Marta","Moa"}), ({"Botvid","Seved"}), ({"Olof","Olle"}),
+   ({"Algot","Margot"}), ({"Elin","Elna"}), ({"Per","Pernilla"}),
+   ({"Karin","Kajsa"}), ({"Tage","Tanja"}), ({"Arne","Arnold"}),
+   ({"Ulrik","Alrik"}), ({"Sixten","Sölve"}), ({"Dennis","Donald"}),
+   ({"Silvia","Sylvia"}), ({"Roland","Roine"}), ({"Lars","Lorentz"}),
+   ({"Susanna","Sanna"}), ({"Klara","Clary"}), ({"Hillevi","Gullvi"}),
+   ({"William","Bill"}), ({"Stella","Stellan"}), ({"Brynolf","Sigyn"}),
+   ({"Verner","Veronika"}), ({"Helena","Lena"}), ({"Magnus","Måns"}),
+   ({"Bernhard","Bernt"}), ({"Jon","Jonna"}), ({"Henrietta","Henny"}),
+   ({"Signe","Signhild"}), ({"Bartolomeus","Bert"}),
+   ({"Lovisa","Louise"}), ({"Östen","Ejvind"}), ({"Rolf","Rudolf"}),
+   ({"Gurli","Gull"}), ({"Hans","Hampus"}), ({"Albert","Albertina"}),
+   ({"Arvid","Vidar"}), ({"Samuel","Sam"}), ({"Justus","Justina"}),
+   ({"Alfhild","Alfons"}), ({"Gisela","Glenn"}), ({"Harry","Harriet"}),
+   ({"Sakarias","Esaias"}), ({"Regina","Roy"}), ({"Alma","Ally"}),
+   ({"Anita","Anja"}), ({"Tord","Tove"}), ({"Dagny","Daniela"}),
+   ({"Tyra","Åsa"}), ({"Sture","Styrbjörn"}), ({"Ida","Ellida"}),
+   ({"Sigrid","Siri"}), ({"Dag","Daga"}), ({"Hildegard","Magnhild"}),
+   ({"Alvar","Orvar"}), ({"Fredrika","Carita"}), ({"Agda","Agata"}),
+   ({"Ellen","Elly"}), ({"Maurits","Morgan"}), ({"Tekla","Tea"}),
+   ({"Gerhard","Gert"}), ({"Kåre","Tryggve"}), ({"Einar","Enar"}),
+   ({"Dagmar","Rigmor"}), ({"Lennart","Leonard"}),
+   ({"Mikael","Mikaela"}), ({"Helge","Helny"}), ({"Ragnar","Ragna"}),
+   ({"Ludvig","Louis"}), ({"Evald","Osvald"}), ({"Frans","Frank"}),
+   ({"Bror","Bruno"}), ({"Jenny","Jennifer"}), ({"Birgitta","Britta"}),
+   ({"Nils","Nelly"}), ({"Ingrid","Inger"}), ({"Helmer","Hadar"}),
+   ({"Erling","Jarl"}), ({"Valfrid","Ernfrid"}), ({"Birgit","Britt"}),
+   ({"Manfred","Helfrid"}), ({"Hedvig","Hedda"}), ({"Fingal","Finn"}),
+   ({"Antonia","Annette"}), ({"Lukas","Matteus"}), ({"Tore","Torleif"}),
+   ({"Sibylla","Camilla"}), ({"Birger","Börje"}), ({"Marika","Marita"}),
+   ({"Sören","Severin"}), ({"Evert","Eilert"}), ({"Inga","Ingvald"}),
+   ({"Amanda","My"}), ({"Sabina","Ina"}), ({"Simon","Simone"}),
+   ({"Viola","Vivi"}), ({"Elsa","Elsie"}), ({"Edit","Edgar"}),
+   ({"Andre","Andrea"}), ({"Tobias","Toini"}), ({"Hubert","Diana"}),
+   ({"Uno","Unn"}), ({"Eugen","Eugenia"}), ({"Gustav Adolf"}),
+   ({"Ingegerd","Ingela"}), ({"Vendela","Vanda"}), ({"Teodor","Ted"}),
+   ({"Martin","Martina"}), ({"Mårten"}), ({"Konrad","Kurt"}),
+   ({"Kristian","Krister"}), ({"Emil","Mildred"}), ({"Katja","Nadja"}),
+   ({"Edmund","Gudmund"}), ({"Naemi","Nancy"}), ({"Pierre","Percy"}),
+   ({"Elisabet","Lisbeth"}), ({"Pontus","Pia"}), ({"Helga","Olga"}),
+   ({"Cecilia","Cornelia"}), ({"Klemens","Clarence"}),
+   ({"Gudrun","Runar"}), ({"Katarina","Carina"}), ({"Linus","Love"}),
+   ({"Astrid","Asta"}), ({"Malte","Malkolm"}), ({"Sune","Synnöve"}),
+   ({"Anders","Andreas"}), ({"Oskar","Ossian"}), ({"Beata","Beatrice"}),
+   ({"Lydia","Carola"}), ({"Barbro","Barbara"}), ({"Sven","Svante"}),
+   ({"Nikolaus","Niklas"}), ({"Angelika","Angela"}),
+   ({"Virginia","Vera"}), ({"Anna","Annie"}), ({"Malin","Malena"}),
+   ({"Daniel","Dan"}), ({"Alexander","Alex"}), ({"Lucia"}),
+   ({"Sten","Stig"}), ({"Gottfrid","Gotthard"}), ({"Assar","Astor"}),
+   ({"Inge","Ingemund"}), ({"Abraham","Efraim"}), ({"Isak","Rebecka"}),
+   ({"Israel","Moses"}), ({"Tomas","Tom"}), ({"Natanael","Natalia"}),
+   ({"Adam"}), ({"Eva"}), ({}), ({"Stefan","Staffan"}),
+   ({"Johannes","Hannes"}), ({"Abel","Set"}), ({"Gunlög","Åslög"}),
+   ({"Sylvester"}), });
diff --git a/lib/modules/Calendar_I.pmod/module.pmod b/lib/modules/Calendar_I.pmod/module.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..302ac793ecb0d90c75c69a52141294345dfc2cc0
--- /dev/null
+++ b/lib/modules/Calendar_I.pmod/module.pmod
@@ -0,0 +1,167 @@
+
+//! 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>.
+//!
+//!	
+//!	Ie:<pre>
+//!	array(string) lesser()    - gives back a list of possible xxx's.
+//!	object xxxs()     	  - gives back a list of possible n's.
+//!	object xxx(mixed n)       - gives back xxx n
+//!	object xxx(object(Xxx) o) - gives back the corresponing xxx 
+//!	</pre>
+//!
+//!	The list of n's (as returned from xxxs) are always in order.
+//!
+//!	There are two n's with special meaning, 0 and -1.
+//!	0 always gives the first xxx, equal to 
+//!	my_obj->xxx(my_obj->xxxs()[0]), and -1 gives the last,
+//!	equal to my_obj->xxx(my_obj->xxxs()[-1]).
+//!
+//!	To get all xxxs in the object, do something like
+//!	<tt>Array.map(my_obj->xxxs(),my_obj->xxx)</tt>.
+//!
+//!	xxx(object) may return zero, if there was no correspondning xxx.
+//!
+//! 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.
+
+#define error(X) throw(({(X),backtrace()}))
+
+class _TimeUnit
+{
+   object this=this_object();
+
+   array(string) greater() { return ({}); }
+   array(string) lesser() { return ({}); }
+
+   int `<(object x) { error("'< undefined\n"); }
+   int `>(object x) { error("'> undefined\n"); }
+   int `==(object x) { error("'== undefined\n"); }
+
+   object `+(int n) { error("`+ undefined\n"); }
+   object|int `-(int n) { error("`- undefined\n"); }
+
+   object next() { return this+1; }
+   object prev() { return this+(-1); }
+}
+
+
+
+
+
+string print_month(void|object month,void|mapping options)
+{
+   object w;
+   object today;
+   string res="";
+
+   if (!month)  // resolv thing here is to avoid compile-time resolve
+      month=master()->resolv("Calendar")["Gregorian"]["Month"]();
+
+   options=(["mark_today":1,
+	     "week_space":3,
+	     "weeks":1,
+	     "days":1,
+	     "title":1,
+	     "notes":([])]) | (options || ([]));
+   options=(["date_space":(options->mark_today?3:2)])|options;
+
+
+   today=function_object(object_program(month))->Day();
+
+   w=month->day(1)->week();
+
+   res="";
+   if (options->weeks) res+=" "+" "*options->week_space;
+   if (options->title)
+      res+=sprintf("%|*s\n",
+		   (1+options->date_space)*sizeof(w->days())-1,
+		   intp(options->title)
+		   ?(String.capitalize(month->name()+" ")
+		     +month->year()->name())
+		   :options->title);
+
+   if (options->days)
+   {
+      if (options->weeks) res+=" "+" "*options->week_space;
+      foreach (Array.map(w->days(),w->day)->week_day_name(),string n)
+	 res+=sprintf("%*s ",options->date_space,n[0..options->date_space-1]);
+      res+="\n";
+   }
+
+   string daynotes="";
+
+   if (sizeof(Array.filter(
+      Array.map(month->days(),month->day),
+      lambda(object d) { return !!options->notes[d]; })))
+      daynotes="\n%-|"+options->date_space+"s";
+
+   do
+   {
+      array a;
+      array b;
+      object d;
+      string format="";
+
+      a=Array.map(Array.map(w->days(),w->day),
+		  lambda(object d) 
+		  { if (d->month()!=month) return 0; else return d; });
+
+      if (options->weeks)
+	 res+=sprintf("%*s ",options->week_space,w->name());
+      foreach (a,d)
+	 if (d)
+	    if (!options->mark_today || d!=today) 
+	       res+=sprintf("%* |d ",
+			    options->date_space,
+			    d->month_day());
+	    else 
+	       res+=sprintf(">%* |d<",
+			    options->date_space-1,
+			    d->month_day());
+	 else res+=" "+" "*options->date_space;
+
+      if (options->notes[w])
+	 res+=sprintf("%-=*s",
+		      options->week_note_column_width,
+		      options->notes[w]);
+
+      res+="\n";
+
+      if (daynotes)
+      {
+	 
+      }
+
+      w++;
+   }
+   while (w->day(0)->month()==month);
+
+   return res;
+}