ניתן ליצור תיעוד על היחידה הזאת בדף יחידה:תאריך/תיעוד

local Date = {} local maxDaysInMonth = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}  --[[     Supported calendar models ]]-- Date.CALENDAR = { 	GREGORIAN = 'Gregorian', 	JULIAN    = 'Julian' }  --Internal functions --[[     Check if a value is a number in the given range     @param mixed value     @param number min     @param number max     @return boolean ]]-- local function validateNumberInRange( value, min, max )     return type( value ) == 'number' and value >= min and value <= max end  --[[     Validate a time defintion     @param table definition data     @return boolean ]]-- local function validate(definition) 	--Validate constants 	if not Date.knowsPrecision(definition.precision) or  		(definition.calendar ~= Date.CALENDAR.GREGORIAN and definition.calendar ~= Date.CALENDAR.JULIAN) then 		return false 	end      --Validate year     if not (type( definition.year ) == 'number' or (definition.year == nil and precision == Date.PRECISION.DAY)) then         return false     end     if definition.precision <= Date.PRECISION.YEAR then         return true     end      --Validate month     if not validateNumberInRange( definition.month, 1, 12 ) then         return false     end     if definition.precision <= Date.PRECISION.MONTH then         return true     end      --Validate day     if not validateNumberInRange( definition.day, 1, 31 ) then         return false     end     if definition.precision <= Date.PRECISION.DAY then         return true     end      --Validate hour     if not validateNumberInRange( definition.hour, 0, 23 ) then         return false     end     if definition.precision <= Date.PRECISION.HOUR then         return true     end      --Validate minute     if not validateNumberInRange( definition.minute, 0, 59 ) then         return false     end     if definition.precision <= Date.PRECISION.MINUTE then         return true     end      --Validate second     if not validateNumberInRange( definition.second, 0, 60 ) then         return false     end      return true end  --[[     Try to find the relevant precision for a time definition     @param table time definition     @return number the precision ]]-- local function guessPrecision(definition)     if definition.month == nil or (definition.month == 0 and definition.day == 0) then         return Date.PRECISION.YEAR     elseif definition.day == nil or definition.day == 0 then         return Date.PRECISION.MONTH     elseif definition.hour == nil then         return Date.PRECISION.DAY     elseif definition.minute == nil then         return Date.PRECISION.HOUR     elseif definition.second == nil then         return Date.PRECISION.MINUTE     else         return Date.PRECISION.SECOND     end end  --[[     Try to find the relevant calendar for a time definition     @param table time definition     @return string the calendar name ]]-- local function guessCalendar( definition )     if definition.year ~= nil and definition.year < 1583 and definition.precision > Date.PRECISION.MONTH then         return Date.CALENDAR.JULIAN     else         return Date.CALENDAR.GREGORIAN     end end  --[[     Parse an ISO 2061 string and return it as a time definition     @param string iso the iso datetime     @param boolean withoutRecurrence concider date in the format XX-XX as year-month and not month-day     @return table ]]-- local function parseIso8601( iso, withoutRecurrence )     local definition = {}      --Split date and time     iso = mw.text.trim( iso:upper() )     local beginMatch, endMatch, date, time, offset = iso:find( '([%+%-]?[%d%-]+)[T ]?([%d%.:]*)([Z%+%-]?[%d:]*)' )      if beginMatch ~= 1 or endMatch ~= iso:len() then --iso is not a valid ISO string         return {}     end      --date     if date ~= nil then         local isBC = false         if date:sub( 1, 1 ) == '-' then             isBC = true             date = date:sub( 2, date:len() )         end         local parts = mw.text.split( date, '-' )         if not withoutRecurrence and table.maxn( parts ) == 2 and parts[1]:len() == 2 then             --MM-DD case             definition.month = tonumber( parts[1] )             definition.day = tonumber( parts[2] )         else             if isBC then                 definition.year = -1 * tonumber( parts[1] )  --FIXME - 1 --Years BC are counted since 0 and not -1             else                 definition.year = tonumber( parts[1] )             end             definition.month = tonumber( parts[2] )             definition.day = tonumber( parts[3] )         end     end      --time     if time ~= nil then         local parts = mw.text.split( time, ':' )         definition.hour = tonumber( parts[1] )         definition.minute = tonumber( parts[2] )         definition.second = tonumber( parts[3] )     end      --ofset     if offset ~= nil then         if offset == 'Z' then             definition.utcoffset = '+00:00'         else             definition.utcoffset = offset         end     end      return definition end  --[[     Format UTC offset for ISO output     @param string offset UTC offset     @return string UTC offset for ISO ]]-- local function formatUtcOffsetForIso( offset )     if offset == '+00:00' then         return 'Z'     else         return offset     end end  --[[     Prepend as mutch as needed the character c to the string str in order to to have a string of length length     @param mixed str     @param string c     @param number length     @return string ]]-- local function prepend(str, c, length)     str = tostring( str )     while str:len() < length do         str = c .. str     end     return str end  --  LEAP_GREGORIAN  --  Is a given year in the Gregorian calendar a leap year ? local function leapGregorian(year)     return ((year % 4) == 0) and             (not (((year % 100) == 0) and ((year % 400) ~= 0))) end  local isDateInLeapYear = function(indate) 	if indate.calendar == Date.CALENDAR.JULIAN then 		return 0 == indate.year % 4 	end 	return leapGregorian(indate.year) end  --  GREGORIAN_TO_JD  --  Determine Julian day number from Gregorian calendar date local GREGORIAN_EPOCH = 1721425.5  local function gregorianToJd(year, month, day)     return (GREGORIAN_EPOCH - 1) +            (365 * (year - 1)) +            math.floor((year - 1) / 4) +            (-math.floor((year - 1) / 100)) +            math.floor((year - 1) / 400) +            math.floor((((367 * month) - 362) / 12) +            ((month <= 2) and 0 or                                (leapGregorian(year) and -1 or -2)            ) +            day) end  --  JD_TO_JULIAN  --  Calculate Julian calendar date from Julian day local function jdToJulian(td)     local z, a, alpha, b, c, d, e, year, month, day          td = td + 0.5     z = math.floor(td)          a = z     b = a + 1524     c = math.floor((b - 122.1) / 365.25)     d = math.floor(365.25 * c)     e = math.floor((b - d) / 30.6001)          month = math.floor((e < 14) and (e - 1) or (e - 13))     year = math.floor((month > 2) and (c - 4716) or (c - 4715))     day = b - d - math.floor(30.6001 * e)          --[[         If year is less than 1, subtract one to convert from         a zero based date system to the common era system in         which the year -1 (1 B.C.E) is followed by year 1 (1 C.E.).     --]]          if year < 1 then         year = year - 1     end          return year, month, day end  -- adapted from ro:Modul:GregorianDate local initialOffset = -3 local limitDates = { 	{year = 4, month = 3, day = 3, calendar = Date.CALENDAR.JULIAN }, 	{year = 100, month = 3, day = 2, calendar = Date.CALENDAR.JULIAN }, 	{year = 200, month = 3, day = 1, calendar = Date.CALENDAR.JULIAN }, 	{year = 300, month = 2, day = 29, calendar = Date.CALENDAR.JULIAN }, 	{year = 500, month = 2, day = 28, calendar = Date.CALENDAR.JULIAN }, 	{year = 600, month = 2, day = 27, calendar = Date.CALENDAR.JULIAN }, 	{year = 700, month = 2, day = 26, calendar = Date.CALENDAR.JULIAN }, 	{year = 900, month = 2, day = 25, calendar = Date.CALENDAR.JULIAN }, 	{year = 1000, month = 2, day = 24, calendar = Date.CALENDAR.JULIAN }, 	{year = 1100, month = 2, day = 23, calendar = Date.CALENDAR.JULIAN }, 	{year = 1300, month = 2, day = 22, calendar = Date.CALENDAR.JULIAN }, 	{year = 1400, month = 2, day = 21, calendar = Date.CALENDAR.JULIAN }, 	{year = 1500, month = 2, day = 20, calendar = Date.CALENDAR.JULIAN }, 	{year = 1700, month = 2, day = 19, calendar = Date.CALENDAR.JULIAN }, 	{year = 1800, month = 2, day = 18, calendar = Date.CALENDAR.JULIAN }, 	{year = 1900, month = 2, day = 17, calendar = Date.CALENDAR.JULIAN }, 	{year = 2100, month = 2, day = 16, calendar = Date.CALENDAR.JULIAN }, 	{year = 2200, month = 2, day = 15, calendar = Date.CALENDAR.JULIAN }, 	{year = 2300, month = 2, day = 14, calendar = Date.CALENDAR.JULIAN } }  function Date.julianToGregorian(indate) 	if indate.calendar ~= Date.CALENDAR.JULIAN then 			return indate 	end 	 	local outputDate 	if indate.precision > Date.PRECISION.MONTH then 		local offset = initialOffset 		local limitDateIdx = 1 		 		while limitDateIdx < #limitDates and Date.le(limitDates[limitDateIdx], indate) do 			limitDateIdx = limitDateIdx + 1 			offset = offset + 1 		end 	 		outputDate = Date.addDaysToDate(indate, offset) 	else 		outputDate = mw.clone(indate) 	end 	outputDate.calendar = Date.CALENDAR.GREGORIAN 	outputDate.calendarmodel = 'http://www.wikidata.org/entity/Q1985727' 	 	return Date.new(outputDate) end  function Date.addDaysToDate(indate, days) 	local outdate = mw.clone(indate) 	 	outdate.day = outdate.day + days 	local lastDayOfMonth = maxDaysInMonth[outdate.month] 	while outdate.day > lastDayOfMonth do 		lastDayOfMonth = maxDaysInMonth[outdate.month] 		if outdate.month == 2 and isDateInLeapYear(outdate) then lastDayOfMonth = 29 end 		outdate.month = outdate.month + 1 		outdate.day = outdate.day - lastDayOfMonth 	end 	while outdate.month > 12 do 		outdate.year = outdate.year + 1 		outdate.month = outdate.month - 12 	end  	return outdate end  function Date.le(t1, t2, correct_calender) 	if t1.calendar ~= t2.calendar then 		if correct_calender then 			t1 = Date.julianToGregorian(t1) 			t2 = Date.julianToGregorian(t2) 		else 			 error("Calanders dont match", 2) 		end 	end 	if t1.year < t2.year then 		return true 	end 	if t1.year == t2.year then 		if t1.month < t2.month then 			return true 		end 		if t1.month == t2.month and t1.day <= t2.day then 			return true 		end 	end 	return false end  --Public interface --[[     Build a new Date     @param table definition definition of the time     @return Date|nil ]]-- function Date.new( definition )     --Default values     if definition.precision == nil then         definition.precision = guessPrecision( definition )     end     if definition.calendar == nil then         definition.calendar = guessCalendar( definition )     end      if not validate( definition ) then         return nil     end      local time = {         year = definition.year or nil,         month = definition.month or 1,         day = definition.day or 1,         hour = definition.hour or 0,         minute = definition.minute or 0,         second = definition.second or 0,         utcoffset = definition.utcoffset or '+00:00',         calendar = definition.calendar or Date.CALENDAR.GREGORIAN,         precision = definition.precision or 0     }      setmetatable( time, {         __index = Date,         __le = le,         __tostring = function( self ) return self:toString() end     } )              return time end  --[[     Build a new Date from an ISO 8601 datetime     @param string iso the time as ISO string     @param boolean withoutRecurrence concider date in the format XX-XX as year-month and not month-day     @return Date|nil ]]-- function Date.newFromIso8601( iso, withoutRecurrence )     return Date.new( parseIso8601( iso, withoutRecurrence ) ) end  --[[     Build a new Date from a Wikidata time value     @param table wikidataValue the time as represented by Wikidata     @return Date|nil ]]-- function Date.newFromWikidataValue( wikidataValue )     local definition = parseIso8601( wikidataValue.time )     definition.precision = wikidataValue.precision      if  wikidataValue.calendarmodel == 'http://www.wikidata.org/entity/Q1985727' then         definition.calendar = Date.CALENDAR.GREGORIAN     elseif  wikidataValue.calendarmodel == 'http://www.wikidata.org/entity/Q1985786' then         definition.calendar = Date.CALENDAR.JULIAN     else         return nil     end      return Date.new( definition ) end  --[[     Build a new Date from a wiki string     @param string wikitext string     @return Date|nil	 ]] function Date.newFromWikitext( wikitext ) 	local months = { 		['ינואר']= 1, 		['פברואר']= 2, 		['מרץ']= 3, 		['אפריל']= 4, 		['מאי']= 5, 		['יוני']= 6, 		['יולי']= 7, 		['אוגוסט']= 8, 		['ספטמבר']= 9, 		['אוקטובר']= 10, 		['נובמבר']= 11, 		['דצמבר']= 12 	} 	local calendar = nil 	if mw.ustring.find( wikitext, '<small>%(%[%[הלוח היוליאני%|יוליאני%]%]%)</small>' ) then 		calendar = Date.CALENDAR.JULIAN 		wikitext = mw.ustring.gsub( wikitext, "<small>%(%[%[הלוח היוליאני%|יוליאני%]%]%)</small>", "" ) 	end 	 	-- Remove instances of [ and ] 	wikitext = mw.ustring.gsub( wikitext, "[%[%]]", "" ) 	-- Remove footnotes & directionality markers 	wikitext = mw.text.killMarkers( wikitext ) 	wikitext = mw.ustring.gsub(wikitext, "&rlm;","") 	wikitext = mw.ustring.gsub(wikitext, "&lrm;","") 	mw.log('תאריך' .. ":" .. wikitext) 	-- BC to minus 	wikitext = mw.ustring.gsub( wikitext, "([0-9]+) לפנה[\"״]ס" , "-%1") 	 	for a in pairs(months) do 		wikitext = mw.ustring.gsub(wikitext, ' ?ב?'..a, ' ' .. months[a])  	end 	-- if there are alphabet chars return nil (unexpected character) 	assert(not mw.ustring.find(wikitext, '%a'), "Unexpected format") 	local parts = mw.text.split(mw.text.trim(wikitext),' ')      local definition = {} 	definition.calendar = calendar 	if #parts==3 then -- DMY date 		definition.year = tonumber(parts[3]) 		definition.month = tonumber(parts[2]) 		definition.day = tonumber(parts[1]) 		assert(definition.year, "Could not recognize year") 		assert(definition.month<13 and definition.month>0, "Could not recognize month number") 		assert(definition.day<32 and definition.day>0, "Wrong date format") 		definition.precision = Date.PRECISION.DAY 	elseif  #parts==2 then -- MY date 		definition.year = tonumber(parts[2]) 		definition.month = tonumber(parts[1])   		definition.precision = Date.PRECISION.MONTH 		assert(definition.year<1e7, "Could not recognize year") 		assert(definition.month<13 and definition.month>0, "Could not recognize month number") 	elseif #parts==1 then --Y date 		definition.precision = Date.PRECISION.YEAR 		definition.year=tonumber(parts[1]) 		assert(definition.year<1e7, "Could not recognize year") 	else 		error("Unexpected date format") 	end 	 	return Date.new( definition )  end   --[[     Return a Date as a ISO 8601 string     @return string ]]-- function Date:toIso8601()     local iso = ''     if self.year ~= nil then         if self.year < 0 then              --Years BC are counted since 0 and not -1             iso = '-' .. prepend(string.format('%.0f', -1 * self.year), '0', 4)         else             iso = prepend(string.format('%.0f', self.year), '0', 4)         end     end      --month     if self.precision < Date.PRECISION.MONTH then         return iso     end     if self.iso ~= '' then         iso = iso .. '-'     end     iso = iso .. prepend( self.month, '0', 2 )      --day     if self.precision < Date.PRECISION.DAY then         return iso     end     iso = iso .. '-' .. prepend( self.day, '0', 2 )      --hour     if self.precision < Date.PRECISION.HOUR then         return iso     end     iso = iso .. 'T' .. prepend( self.hour, '0', 2 )      --minute     if self.precision < Date.PRECISION.MINUTE then         return iso .. formatUtcOffsetForIso( self.utcoffset )     end     iso = iso .. ':' .. prepend( self.minute, '0', 2 )      --second     if self.precision < Date.PRECISION.SECOND then         return iso .. formatUtcOffsetForIso( self.utcoffset )     end     return iso .. ':' .. prepend( self.second, '0', 2 ) .. formatUtcOffsetForIso( self.utcoffset ) end   --[[     Return a hebrew representation of Date as a string     @return string ]]-- function Date:toHebrewString() 	local hebrewStr = '' 	local year = self.year 	 	if (self.precision >= Date.PRECISION.MY100) and (self.precision <= Date.PRECISION.MY) then 		if self.year>0 then         	return (self.year/1000000) .. ' מיליון שנים לספירה'         else         	return (-self.year/1000000) ..' מיליון שנים לפנה״ס'         end 	elseif (self.precision >=Date.PRECISION.KY100) and (self.precision <= Date.PRECISION.KY) then 		if self.year>0 then         	return 'האלף ה־'.. (self.year/1000)         else         	return 'האלף ה־'.. (-self.year/1000) ..' לפנה״ס'         end 	elseif self.precision == Date.PRECISION.YEAR100 then 		if year>0 then 	        	return 'המאה ה־'.. math.ceil(self.year/100) 		else         		return 'המאה ה־'.. math.ceil(-self.year/100) ..' לפנה״ס'         end 	elseif self.precision == Date.PRECISION.YEAR10 then         local year = math.floor((self.year < 0 and -1 * self.year or self.year)  / 10) * 10         if self.year>0 then         	if year%100==0 then         		return  'העשור הראשון של המאה ה־'.. tostring((year/100)+1)         	else         		return 'שנות ה־' .. tostring(year%100) .. ' של המאה ה־'.. tostring(math.ceil(year/100))         	end         else         	if year%100==0 then         		return  'העשור הראשון של המאה ה־'.. tostring((year/100))..' לפנה״ס'         	else         		return 'שנות ה־' .. tostring(year%100) .. ' של המאה ה־'.. tostring(math.ceil(year/100))..' לפנה״ס'         	end         end 	end     if self.year ~= nil then         if self.year < 0 then             hebrewStr = mw.ustring.format('%d לפנה״ס',  (-1*self.year))         else 			if self.calendar == Date.CALENDAR.JULIAN and self.year > 1583 then 				hebrewStr = mw.ustring.format('%d <small>([[הלוח היוליאני|יוליאני]])</small>',  (self.year)) 			else 				hebrewStr = mw.ustring.format('%d',  self.year) 			end         end     end      --month     if self.precision>=Date.PRECISION.YEAR and self.precision < Date.PRECISION.MONTH then         return hebrewStr     end     local months = { 'ינואר','פברואר', 'מרץ', 'אפריל', 'מאי', 'יוני', 'יולי', 'אוגוסט', 'ספטמבר', 'אוקטובר', 'נובמבר','דצמבר' }     hebrewStr = months[self.month] .. ' ' .. hebrewStr      --day     if self.precision < Date.PRECISION.DAY then         return hebrewStr     end     hebrewStr = mw.ustring.format('%d ב%s', self.day, hebrewStr)      --hour     if self.precision < Date.PRECISION.HOUR then         return hebrewStr     end     hebrewStr = mw.ustring.format('%s בשעה %d',  hebrewStr, self.hour)      --minute     if self.precision < Date.PRECISION.MINUTE then         return hebrewStr .. formatUtcOffsetForIso( self.utcoffset )     end     hebrewStr = hebrewStr .. ':' .. prepend( self.minute, '0', 2 )      --second     if self.precision < Date.PRECISION.SECOND then         return hebrewStr .. formatUtcOffsetForIso( self.utcoffset )     end     return hebrewStr .. ':' .. prepend( self.second, '0', 2 ) .. formatUtcOffsetForIso( self.utcoffset ) end  --[[     Return a Date as a string     @param mw.language|string|nil language to use. By default the content language.     @return string ]]-- function Date:toString( language )     if language == nil then         return self:toIso8601()     end     if language == 'he' then     	return self:toHebrewString()     end     --[[if type( language ) == 'string' then         language = mw.language.new( language )     end          return language:formatDate( 'r', self:toIso8601() )]]     return self:toIso8601() end  --[[     Return a Date in HTMl (with a <time> node)     @param mw.language|string|nil language to use. By default the content language.     @param table|nil attributes table of attributes to add to the <time> node.     @return string ]]-- function Date:toHtml( language, attributes )     if attributes == nil then         attributes = {}     end     attributes['datetime'] = self:toIso8601()     return mw.text.tag( 'time', attributes, self:toString( language ) ) end  --[[     All possible precisions for a Date (same ids as Wikibase) ]]-- Date.PRECISION = { 	GY      = 0, --Gigayear 	MY100   = 1, --100 Megayears 	MY10    = 2, --10 Megayears 	MY      = 3, --Megayear 	KY100   = 4, --100 Kiloyears 	KY10    = 5, --10 Kiloyears 	KY      = 6, --Kiloyear 	YEAR100 = 7, --100 years 	YEAR10  = 8, --10 years 	YEAR    = 9, 	MONTH   = 10, 	DAY     = 11, 	HOUR    = 12, 	MINUTE  = 13, 	SECOND  = 14 }  --[[     Check if the precision is known     @param number precision ID     @return boolean ]]-- function Date.knowsPrecision( precision ) 	for _,id in pairs( Date.PRECISION ) do 		if id == precision then 			return true 		end 	end     return false end  function Date.age(time1, time2)     if time2 == nil then         time2 = Date.newFromIso8601(mw.getContentLanguage():formatDate('c', nil, true), true)     end     local age = time2.year - time1.year     if time2.month < time1.month or (time2.month == time1.month and time2.day < time1.day) then         age = age - 1     end     if time1.year < 0 and time2.year > 0 then         age = age - 1     end     return age end   function Date:formatDate(options)     options = options or {}     local fd = ''     if self.precision >= Date.PRECISION.DAY then         fd = self.year < 0 and (-1 * self.year) .. ' לפנה"ס' or fd .. self.year         if options.link then fd = '[[' .. fd .. ']]' end         local d = '2000-' .. prepend(self.month, '0', 2) .. '-' .. prepend(self.day, '0', 2)         local lang = mw.getContentLanguage()         fd = fd .. '. ' .. lang:formatDate(options.link and '[[j xg]]' or 'j xg', d) 	elseif self.precision >= Date.PRECISION.MONTH then 		fd = self.year < 0 and (-1 * self.year) .. ' לפנה"ס' or fd .. self.year 		local month = mw.getContentLanguage():formatDate('F', '2000-' .. self.month) 		if options.link then fd = '[[' .. fd .. ']]' end 		fd = month .. ' ' .. fd     elseif self.precision >= Date.PRECISION.YEAR then         fd = self.year < 0 and (-1 * self.year) .. ' לפנה"ס' or fd .. self.year         if options.link ~= 'nem' then fd = '[[' .. fd .. ']]' end     elseif self.precision == Date.PRECISION.YEAR10 then         local year = math.floor((self.year < 0 and -1 * self.year or self.year)  / 10) * 10         fd = 'שנות ה-' .. tostring(year%100) .. ' של המאה ה-'.. tostring(ceil(year/100))         fd = self.year < 0 and year .. ' לפנה"ס' or tostring(year)     elseif self.precision == Date.PRECISION.YEAR100 then         if self.year < 0 then             fd = 'המאה ה-' .. math.floor(-1 * self.year / 100) .. ' לפנה"ס'         else             fd = 'המאה ה-' ..math.floor(self.year / 100)         end         if options.link then fd = '[[' .. fd .. ']]' end     else         fd = tostring(self.year)     end          return fd end   function parseStrDate(dateStr, dateType) 	local datetime = Date.newFromWikitext( dateStr ) 	if datetime.precision >= Date.PRECISION.DAY then -- DMY date 		if dateType=='Y' then 			res = datetime.year 		elseif dateType=='M' then 			res = datetime.month  		elseif dateType=='D' then 			res = datetime.day 		elseif dateType == 'TS' then 			res = datetime:toIso8601() 		end 	elseif  datetime.precision >= Date.PRECISION.MONTH then -- MY date  		if dateType=='Y' then 			res = datetime.year 		elseif dateType=='M' then 			res = datetime.month 		elseif dateType == 'TS' then 			res = datetime:toIso8601() 		end 	else --Y date 		if dateType=='Y' then 			res = datetime.year 		elseif dateType == 'TS' then 			res = datetime:toIso8601() 		end 	end 	return res end  function parseDateRange(dateRangeStr, diffFormat, inclusive ) 	-- remove footnotes 	dateRangeStr = mw.text.killMarkers(dateRangeStr) 	dateRangeStr = mw.ustring.gsub(dateRangeStr, "&rlm;","")    mw.log("טווח תאריכים:" .. dateRangeStr) 	local outputPrefix = '' 	local parts = mw.text.split(dateRangeStr,' +%- +') 	assert(#parts==2 or #parts==1, "Date range expected format is from - to or from (e.g from - now)") 	 	-- parse dates 	local t1 = Date.newFromWikitext( parts[1] ) 	local t2 	if #parts==2 then 		t2 = Date.newFromWikitext( parts[2] ) 	else 		t2 = Date.newFromIso8601(mw.getContentLanguage():formatDate('c', nil, true), true) 	end 	 	local hasYears = (diffFormat=='auto') 	local hasDays = (diffFormat=='auto') 	for i=1,#diffFormat do   		if (diffFormat[i]=='years') then  			hasYears=true 		elseif diffFormat[i]=='days' then 			hasDays =true 		end  	end 		 	if hasDays and ((t1.precision>=Date.PRECISION.MONTH and t2.precision<Date.PRECISION.MONTH) or (t1.precision<Date.PRECISION.MONTH and t2.precision>=Date.PRECISION.MONTH)) then 		return '' -- Ambiguous date range 	end 	local NO_GUESS, MONTH_GUESS, DAY_GUESS = 0, 1, 2 	local guessLevel = NO_GUESS 	if t1.precision<Date.PRECISION.MONTH or t2.precision<Date.PRECISION.MONTH then  		guessLevel = MONTH_GUESS 		inclusive=true 	elseif t1.precision<Date.PRECISION.DAY or t2.precision<Date.PRECISION.DAY then 		guessLevel = DAY_GUESS 	end 	 	local t1 = os.time({ 		year = t1.year, 		month = t1.month or 6, 		day = t1.day or 16 		}) 	t2= os.time({ 			year = t2.year, 			month = t2.month or 6, 			day = t2.day or 16 		})  	local dif = os.difftime (t2, t1) 	local lang = mw.getContentLanguage() 	local readableInterval = lang:getDurationIntervals(dif, {'years', 'days'}) 	readableInterval['days'] = readableInterval['days'] or 0 	readableInterval['years'] = readableInterval['years'] or 0 	if not (guessLevel==NO_GUESS) and not (guessLevel==DAY_GUESS and hasYears and #diffFormat==1 and readableInterval['days']>31) then  		outputPrefix='כ־' 	end 	if inclusive then 		dif = dif+60*60*24 -- include last day 	end  	if diffFormat=="auto" then 		if dif<=60*60*24 then 			return '' -- Ambiguous date range - we arent handling preceision of less than 1 day (hours, minutes, seconds) 		end 		if guessLevel==MONTH_GUESS and readableInterval['years']==0 then 			return '' -- Ambiguous date range 		end 		--for intervals of around year  		if readableInterval['years']>0 and (readableInterval['days']<30 or (365-readableInterval['days'])<30) then 			-- around 			if readableInterval['days']<30 then 				dif = dif - readableInterval['days']*(60*60*24) 			else 				dif = dif+((365-readableInterval['days'])*(60*60*24)) 			end 			diffFormat = {'years'} 		else 			local diffDays = dif/(60*60*24) 			if diffDays<7*3 then diffFormat = { 'days' } 			elseif diffDays<364 then diffFormat = {'weeks', 'days'} 			elseif diffDays<10*365 then diffFormat = {'years', 'weeks'} 			else  diffFormat = {'years'}  			end 		end 	end 	 	if diffFormat=="raw" then 		return dif 	else 		return outputPrefix..lang:formatDuration(dif, diffFormat) 	end end  function parseDateRangeSafe(frame) 	local diffFormat = 'auto' 	if frame.args[2] == 'ימים' then 		diffFormat = {'days'} 	elseif frame.args[2] == 'שנים' then 		diffFormat = {'years'} 	elseif frame.args[2] == "הפרש" then 		diffFormat = "raw" 	elseif frame.args[2] == "גיל" then 		diffFormat = {'years'} 	elseif frame.args[2] == "מספר" then 		diffFormat = {'years'} 	end  	 	 	local inclusive= (frame.args["כולל"]=="כן") 	local success, res = pcall(parseDateRange, frame.args[1], diffFormat, inclusive) 	  	if success then 		local str=res 		-- the following translations are needed because the underline function 		-- local format is wierd 		str = mw.ustring.gsub(str,  			"(כ)־([א-ת])", "%1%2") 		str= mw.ustring.gsub(str,"וגם ([0-9])","ו-%1") 		str= mw.ustring.gsub(str,"וגם ([א-ת])","ו%1");  		if frame.args[2] == "גיל" then 			str= mw.ustring.gsub(str,"כ־(.+) שנים","%1 בערך") 			str= mw.ustring.gsub(str," שנים","") 		end 		 	-- This parameter returns the difference as number of years, without any text. 		if frame.args[2] == "מספר" then 			str= mw.ustring.gsub(str,"כ(.+)","%1"); 			str= mw.ustring.gsub(str,"־(.+)","%1"); 			str= mw.ustring.gsub(str," שנים","") 			if str == "שנתיים" then 				str = 2 			end 			if str == "שנה" then 				str = 1 			end 			if tonumber(str) > 0 and 					tonumber(parseDateRange(frame.args[1], "raw", inclusive)) < 0 then 				str = -1 * str 			end 		end 		 		return str 	else 		return frame.args['error'] or '<span class="scribunto-error">שגיאת תאריך: '..res..'</span>[[קטגוריה:דפים עם שגיאות בתאריך]]' 	end end  function parseStrDateSafe(frame) 	local dateType = frame.args[2] 	if dateType =='שנה' then 		dateType = 'Y' 	elseif dateType=='חודש' then 		dateType = 'M' 	elseif dateType=='יום' then 		dateType='D' 	end  	local success, res = pcall( parseStrDate, frame.args[1], dateType ) 	if success then 		if dateType=='Y' and mw.ustring.sub( res, 0, 1)=='-' then 			res = mw.ustring.sub( res, 2).. ' לפנה"ס' 		end 		return res 	else 		return frame.args['error'] or '<span class="scribunto-error">שגיאת תאריך: '..res..'</span>[[קטגוריה:דפים עם שגיאות בתאריך]]'  	end end  Date['חשב'] = parseStrDateSafe; Date['חשב טווח'] =  parseDateRangeSafe; Date['parseDateRange'] =  parseDateRange;  return Date