i got tired of all calendars being based on this system, which i find too restricted. You cannot encode many types of holiday, Easter or many religious festivals. You can't track the moon either.<p>So, i wrote my own calendar and the events work as a start datetime, end datetime and optional recurrence. the recurrence is encoded as a small script "generator" statement (LUA actually). The script uses a rich set of built in "function kit" such as "fullmoon", "newmoon" etc. Things like Easter need the moon, and so do many religious festivals.<p>The generator returns the NEXT datetime, so that the calendar can chain these events so that scrolling works nicely and you only calculate what you need.<p># Example Generators<p>## Annual date (eg birthdays)
return nextMonthDay(d, september, 23)<p>## monthly date, `v' of month
return nextMonth(d)+v-1<p>## first monday of next month
return nthkDay(nextMonth(d),1,monday)<p>## last sunday in a month next year
eg last sunday next march. finds next april 1 and works back to last sunday
return nthkDay(nextMonthDay(d+7,april,1),-1,sunday)<p>next monday on or after next May 1st
eg may day
return nthkDay(nextMonthDay(d,may,1),1,monday)<p>eg last monday in may, spring bank holiday
return nthkDay(nextMonthDay(d+7,june,1),-1,monday)<p>## third tuesday of the month
return nthkDay(nextMonth(d),3,tuesday)<p>## fourth thursday in November (Thanksgiving USA)
return nthkDay(nextMonthDay(d, november, 1), 4, thursday)<p>## second monday of october (Thanksgiving Canada)
return nthkDay(nextMonthDay(d, october, 1), 2, monday)<p>## mothers day UK
4th sunday of Lent = 3 weeks before easter sunday
return cal.nextEasterSunday(d+22)-21<p>## first and third thursday of the month
function cvrs(da)
local d1 = nthkDay(thisMonth(da),3,thursday)
local d2 = nthkDay(nextMonth(da),1,thursday)
if d1 > da then return d1 end
return d2
end
return cvrs(d)<p>## first weekday of month
function weekday(d)
local da = cal.dayOfWeek(d)
if da == sunday then d = d + 1
elseif da == saturday then d = d + 2 end
return d
end
return weekday(nextMonth(d))<p>## first weekday on or before given date of of month
function weekdayb4(d)
local da = cal.dayOfWeek(d)
if da == sunday then d = d - 2
elseif da == saturday then d = d - 1 end
return d
end
return weekdayb4(nextMonth(d)+25) -- example<p>## easter
return cal.nextEasterSunday(d)<p>eg good friday
return cal.nextEasterSunday(d+3)-2<p>eg. Easter monday
return cal.nextEasterSunday(d)+1<p>eg shrove tuesday
return cal.nextEasterSunday(d+48)-47<p>##* moon phases
return cal.nextNewMoon(d+1)
return cal.nextFullMoon(d+1)<p>## ramadan<p>this generates the logical 1/9 islamic. Howeever the fast of Ramadan
is often started the day earlier if based on the observational moon
note that it <i>always</i> begins the sunset beforehand.<p>y,m = cal.islamicFromFixed(d)
if m >= 9 then y=y+1 end
return cal.fixedFromIslamic(y,9,1)<p>-- end of ramadan is the end of month 9
-- Eid-al-Fitr (Ramadan ends)
y,m = cal.islamicFromFixed(d+1)
if m >= 10 then y=y+1 end
return cal.fixedFromIslamic(y,9,30)<p>-- Al-Hijra (Islamic New Year)
return cal.fixedFromIslamic(cal.islamicFromFixed(d)+1,1,1)<p>## Hebrew<p>-- Rosh Hashanah (Jewish New Year)
-- 1st of Tishri
return cal.fixedFromHebrew(cal.hebrewFromFixed(d)+1,7,1)<p>-- Yom Yippur
-- tishri 10
return cal.fixedFromHebrew(cal.hebrewFromFixed(d)+1,7,10)