Home
Random
Recent changes
Special pages
Community portal
Preferences
About Stockhub
Disclaimers
Search
User menu
Talk
Contributions
Create account
Log in
Editing
Module:Next Occurrence of Hebrew Date
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
-- Based on public domain code from: http://emr.cs.iit.edu/~reingold/calendar.C local p = {} -- Absolute dates -- "Absolute date" means the number of days elapsed since the Gregorian date -- Sunday, December 31, 1 BC. (Since there was no year 0, the year following -- 1 BC is 1 AD.) Thus the Gregorian date January 1, 1 AD is absolute date -- number 1. -- Gregorian dates function LastDayOfGregorianMonth(month, year) -- Compute the last date of the month for the Gregorian calendar. if month == 2 then if ((((year % 4) == 0) and ((year % 100) ~= 0)) or ((year % 400) == 0)) then return 29; else return 28; end elseif month == 4 or month == 6 or month == 9 or month == 11 then return 30; else return 31; end end GregorianDate = {} GregorianDate.__index = GregorianDate function GregorianDate.create(month, day, year) local gregoriandate = {} -- our new object setmetatable(gregoriandate,GregorianDate) -- make GregorianDate handle lookup -- initialize our object gregoriandate.month = month -- 1 == January, ..., 12 == December gregoriandate.day = day -- 1..LastDayOfGregorianMonth(month, year) gregoriandate.year = year -- return gregoriandate end function GregorianDateFromAbsolute(d) -- Computes the Gregorian date from the absolute date. -- Search forward year by year from approximate year local year = math.floor(d/366); while (d >= AbsoluteFromGregorianDate(GregorianDate.create(1,1,year+1))) do year = year + 1; end -- Search forward month by month from January local month = 1; while (d > AbsoluteFromGregorianDate(GregorianDate.create(month, LastDayOfGregorianMonth(month,year), year))) do month = month + 1; end local day = d - AbsoluteFromGregorianDate(GregorianDate.create(month,1,year)) + 1; return GregorianDate.create(month, day, year) end function AbsoluteFromGregorianDate(gregoriandate) -- Computes the absolute date from the Gregorian date. local N = gregoriandate.day; -- days this month -- days in prior months this year local m = gregoriandate.month - 1; while (m > 0) do N = N + LastDayOfGregorianMonth(m, gregoriandate.year); m = m - 1; end return (N -- days this year + 365 * (gregoriandate.year - 1) -- days in previous years ignoring leap days + math.floor((gregoriandate.year - 1)/4) -- Julian leap days before this year... - math.floor((gregoriandate.year - 1)/100) -- ...minus prior century years... + math.floor((gregoriandate.year - 1)/400)); -- ...plus prior years divisible by 400 end -- Hebrew dates HebrewEpoch = -1373429 -- Absolute date of start of Hebrew calendar function HebrewLeapYear(year) -- True if year is an Hebrew leap year if ((((7 * year) + 1) % 19) < 7) then return 1; else return 0; end end --Last month of Hebrew year. function LastMonthOfHebrewYear(year) if (HebrewLeapYear(year) == 1) then return 13; else return 12; end end function HebrewCalendarElapsedDays(year) -- Number of days elapsed from the Sunday prior to the start of the -- Hebrew calendar to the mean conjunction of Tishri of Hebrew year. local MonthsElapsed = (235 * math.floor((year - 1) / 19)) -- Months in complete cycles so far. + (12 * ((year - 1) % 19)) -- Regular months in this cycle. + math.floor((7 * ((year - 1) % 19) + 1) / 19); -- Leap months this cycle local PartsElapsed = 204 + 793 * (MonthsElapsed % 1080); local HoursElapsed = 5 + 12 * MonthsElapsed + 793 * math.floor(MonthsElapsed / 1080) + math.floor(PartsElapsed / 1080); local ConjunctionDay = 1 + 29 * MonthsElapsed + math.floor(HoursElapsed / 24); local ConjunctionParts = 1080 * (HoursElapsed % 24) + PartsElapsed % 1080; local AlternativeDay = 0; if ((ConjunctionParts >= 19440) -- If new moon is at or after midday, or (((ConjunctionDay % 7) == 2) -- ...or is on a Tuesday... and (ConjunctionParts >= 9924) -- at 9 hours, 204 parts or later... and (HebrewLeapYear(year)) == 0) -- ...of a common year, or (((ConjunctionDay % 7) == 1) -- ...or is on a Monday at... and (ConjunctionParts >= 16789) -- 15 hours, 589 parts or later... and (HebrewLeapYear(year - 1) == 1))) then -- at the end of a leap year -- Then postpone Rosh HaShanah one day AlternativeDay = ConjunctionDay + 1; else AlternativeDay = ConjunctionDay; end if (((AlternativeDay % 7) == 0)-- If Rosh HaShanah would occur on Sunday, or ((AlternativeDay % 7) == 3) -- or Wednesday, or ((AlternativeDay % 7) == 5)) -- or Friday -- Then postpone it one (more) day then return (1+ AlternativeDay); else return AlternativeDay; end end function DaysInHebrewYear(year) -- Number of days in Hebrew year. return ((HebrewCalendarElapsedDays(year + 1)) - (HebrewCalendarElapsedDays(year))); end function LongHeshvan(year) -- True if Heshvan is long in Hebrew year. if ((DaysInHebrewYear(year) % 10) == 5) then return 1; else return 0; end end function ShortKislev(year) -- True if Kislev is short in Hebrew year. if ((DaysInHebrewYear(year) % 10) == 3) then return 1; else return 0; end end function LastDayOfHebrewMonth(month, year) -- Last day of month in Hebrew year. if ((month == 2) or (month == 4) or (month == 6) or ((month == 8) and LongHeshvan(year) == 0) or ((month == 9) and ShortKislev(year) == 1) or (month == 10) or ((month == 12) and (HebrewLeapYear(year) == 0)) or (month == 13)) then return 29; else return 30; end end HebrewDate = {} HebrewDate.__index = HebrewDate function HebrewDate.create(month, day, year) local hebrewdate = {} -- our new object setmetatable(hebrewdate,HebrewDate) -- make HebrewDate handle lookup -- initialize our object hebrewdate.month = month -- 1... hebrewdate.day = day -- 1..LastMonthOfHebrewYear(year) hebrewdate.year = year -- 1..LastDayOfHebrewMonth(month, year) return hebrewdate end function HebrewDateFromAbsolute(d) -- Computes the Hebrew date from the absolute date. local year = math.floor((d + HebrewEpoch) / 366); -- Approximation from below. -- Search forward for year from the approximation. while (d >= AbsoluteFromHebrewDate(HebrewDate.create(7,1,year + 1))) do year = year + 1; end -- Search forward for month from either Tishri or Nisan. local month = 0 if (d < AbsoluteFromHebrewDate(HebrewDate.create(1, 1, year))) then month = 7; -- Start at Tishri else month = 1; -- Start at Nisan end while (d > AbsoluteFromHebrewDate(HebrewDate.create(month, (LastDayOfHebrewMonth(month,year)), year))) do month = month + 1; end -- Calculate the day by subtraction. local day = d - AbsoluteFromHebrewDate(HebrewDate.create(month, 1, year)) + 1; return HebrewDate.create(month, day, year) end function AbsoluteFromHebrewDate(hebrewdate) -- Computes the absolute date of Hebrew date. local DayInYear = hebrewdate.day; -- Days so far this month. if (hebrewdate.month < 7) then -- Before Tishri, so add days in prior months -- this year before and after Nisan. local m = 7; while (m <= (LastMonthOfHebrewYear(hebrewdate.year))) do DayInYear = DayInYear + LastDayOfHebrewMonth(m, hebrewdate.year); m = m + 1; end m = 1; while (m < hebrewdate.month) do DayInYear = DayInYear + LastDayOfHebrewMonth(m, hebrewdate.year); m = m + 1; end else -- Add days in prior months this year local m = 7; while (m < hebrewdate.month) do DayInYear = DayInYear + LastDayOfHebrewMonth(m, hebrewdate.year); m = m + 1; end end return (DayInYear + (HebrewCalendarElapsedDays(hebrewdate.year)-- Days in prior years. + HebrewEpoch)); -- Days elapsed before absolute date 1. end function find_gregorian_for_next_hebrew_date_occurrence(greg_year, greg_month, greg_day, heb_month, heb_day) local greg_absolute = AbsoluteFromGregorianDate(GregorianDate.create(greg_month, greg_day, greg_year)) local hebrew_date = HebrewDateFromAbsolute(greg_absolute) local heb_year = hebrew_date.year -- Check if we already passed that date this year. If we have, increase the year by 1 local this_years_hebrew_absolute = AbsoluteFromHebrewDate(HebrewDate.create(heb_month, heb_day, heb_year)) if (greg_absolute > this_years_hebrew_absolute) then heb_year = heb_year + 1 end -- Certain months only have 29 days. Advance years until we find a year with 30 days that month. if heb_day == 30 then while ((heb_month == 8) and not(LongHeshvan(heb_year))) or ((heb_month == 9) and ShortKislev(heb_year)) or ((heb_month == 12) and (HebrewLeapYear(heb_year) == 0)) do heb_year = heb_year + 1 end end -- The year we're in has the date. Get the absolute and convert it back to a Gregorian date local absolute = AbsoluteFromHebrewDate(HebrewDate.create(heb_month, heb_day, heb_year)) local gregorian = GregorianDateFromAbsolute(absolute) return gregorian end function GregorianMonthToName(monthNumber) if monthNumber == 1 then return "January" elseif monthNumber == 2 then return "February" elseif monthNumber == 3 then return "March" elseif monthNumber == 4 then return "April" elseif monthNumber == 5 then return "May" elseif monthNumber == 6 then return "June" elseif monthNumber == 7 then return "July" elseif monthNumber == 8 then return "August" elseif monthNumber == 9 then return "September" elseif monthNumber == 10 then return "October" elseif monthNumber == 11 then return "November" elseif monthNumber == 12 then return "December" end end function HebrewMonthNameToNumber(month) month = string.lower(month) if month == "nisan" then return 1 elseif month == "iyar" then return 2 elseif month == "sivan" then return 3 elseif month == "tammuz" then return 4 elseif month == "av" then return 5 elseif month == "elul" then return 6 elseif month == "tishrei" then return 7 elseif month == "cheshvan" then return 8 elseif month == "kislev" then return 9 elseif month == "tevet" then return 10 elseif month == "shevat" then return 11 elseif month == "adar" then return 12 else return nil end end function p.next_occurrence_of_hebrew_date_from_date(frame) local greg_year = tonumber(frame.args[1]) local greg_month = tonumber(frame.args[2]) local greg_day = tonumber(frame.args[3]) local heb_month = frame.args[4] local heb_day = tonumber(frame.args[5]) -- Validate some of the parameters: -- heb_month can either be a month name or number heb_month_number = HebrewMonthNameToNumber(heb_month) if heb_month_number then heb_month = heb_month_number else heb_month = tonumber(heb_month) end gregorian = find_gregorian_for_next_hebrew_date_occurrence(greg_year, greg_month, greg_day, heb_month, heb_day) month_name = GregorianMonthToName(gregorian.month) return month_name.." ".. gregorian.day..", "..gregorian.year end function p.next_occurrence_of_hebrew_date(frame) local greg_year = tonumber(os.date("%Y")) local greg_month = tonumber(os.date("%m")) local greg_day = tonumber(os.date("%d")) local heb_month = frame.args[1] local heb_day = tonumber(frame.args[2]) -- Validate some of the parameters: -- heb_month can either be a month name or number heb_month_number = HebrewMonthNameToNumber(heb_month) if heb_month_number then heb_month = heb_month_number else heb_month = tonumber(heb_month) end gregorian = find_gregorian_for_next_hebrew_date_occurrence(greg_year, greg_month, greg_day, heb_month, heb_day) month_name = GregorianMonthToName(gregorian.month) return month_name.." ".. gregorian.day..", "..gregorian.year end return p
Summary:
Please note that all contributions to Stockhub may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
Stockhub:Copyrights
for details).
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Templates used on this page:
Module:Next Occurrence of Hebrew Date
(
edit
)
Module:Next Occurrence of Hebrew Date/doc
(
edit
)