לדלג לתוכן

יחידה:תאריך

מתוך צפונות ויקי
גרסה מ־17:34, 20 במרץ 2016 מאת wikipedia:he>ערן (רצח סמנים)

יחידה זו מיועדת לביצוע פעולות נפוצות על תאריכים.

  • #חשב - מקבלת תאריך טקסטואלי ופורמט ומחלצת את מהתאריך את הפורמט הרצוי
  • #חשב טווח - מקבלת טווח תאריכים ומחשבת את ההפרש ביניהם

חשב

פורמט דוגמה תוצאה
יום {{#invoke:תאריך|חשב|[[3 בפברואר]] [[2013]]|יום}} 3
יום {{#invoke:תאריך|חשב|[[3 בפברואר]] [[2013]]{{הערה|א}}|יום}} 3
חודש {{#invoke:תאריך|חשב|[[3 בפברואר]] [[2013]]|חודש}} 2
שנה {{#invoke:תאריך|חשב|[[3 בפברואר]] [[2013]]|שנה}} 2013
שנה {{#invoke:תאריך|חשב|[[פברואר]] [[2013]]|שנה}} 2013
TS {{#invoke:תאריך|חשב|[[3 בפברואר]] [[2013]]|TS}} 2013-2-3

הערות:

  • פורמט TS ניתן להעביר לפונקציות זמן של הוראות תנאי.
  • ההמרה מתעלמת מסוגריים מרובעות של קישורים
  • ניתן להוסיף פרמטר error והתוכן שלו יוצג במקרה של שגיאה בתאריך. (רצוי להכניס במקרה כזה את הדף לקטגוריה כלשהי שתאפשר מעקב אחרי דפים לא תקינים. ברירת המחדל היא קטגוריה:דפים עם שגיאות בתאריך)

חשב טווח

דוגמה תוצאה
פורמט ברירת מחדל: אוטומטי {{#invoke:תאריך|חשב טווח|[[3 בפברואר]] [[1947]] - [[15 בספטמבר]] [[2013]]}} 66 שנים
פורמט ברירת מחדל: אוטומטי (דוגמה עם שנים וסימן מינוס) {{#invoke:תאריך|חשב טווח|1947 - 2013}} כ־66 שנים
פורמט ברירת מחדל: אוטומטי (דוגמה עם שנים וסימן קו מפריד) {{#invoke:תאריך|חשב טווח|1947–2013}} שגיאת תאריך: יחידה:תאריך:66: attempt to compare nil with number
שנים {{#invoke:תאריך|חשב טווח|[[3 בפברואר]] [[1947]] - [[15 בספטמבר]] [[2013]]|שנים}} 66 שנים
גיל {{#invoke:תאריך|חשב טווח|1 במרץ 1922 - 4 בנובמבר 1995|גיל}} 73
גיל {{#invoke:תאריך|חשב טווח|1 במרץ 1922{{הערה|ב}} - 4 בנובמבר 1995|גיל}} 73
גיל {{#invoke:תאריך|חשב טווח|1 במרץ 1994{{הערה|ב}} - 4 בנובמבר 1995|גיל}} שנה
גיל {{#invoke:תאריך|חשב טווח|1 במרץ 1993{{הערה|ב}} - 4 בנובמבר 1995|גיל}} שנתיים
מספר {{#invoke:תאריך|חשב טווח|1 במרץ 1922 - 4 בנובמבר 1995|מספר}} 73
מספר {{#invoke:תאריך|חשב טווח|1 במרץ 1922{{הערה|ב}} - 4 בנובמבר 1995|מספר}} 73
מספר {{#invoke:תאריך|חשב טווח|1 במרץ 1994{{הערה|ב}} - 4 בנובמבר 1995|מספר}} 1
מספר {{#invoke:תאריך|חשב טווח|1 במרץ 1993{{הערה|ב}} - 4 בנובמבר 1995|מספר}} 2
שנים לפנה"ס {{#invoke:תאריך|חשב טווח|[[3 בפברואר]] 1900 לפנה"ס - [[15 בספטמבר]] [[2013]]|שנים}} 3,913 שנים
ימים {{#invoke:תאריך|חשב טווח|[[3 בפברואר]] [[1947]] - [[15 בספטמבר]] [[2013]]|ימים}} 24,331 ימים
הפרש {{#invoke:תאריך|חשב טווח|[[3 בפברואר]] [[1947]] - [[15 בספטמבר]] [[2013]]|הפרש}} 2102198400
ללא תאריך יעד {{#invoke:תאריך|חשב טווח|[[3 בפברואר]] [[1947]]|שנים}} 79 שנים
לא כולל היום האחרון {{#invoke:תאריך|חשב טווח|5 ביוני 1967 - 10 ביוני 1967}} 5 ימים
כולל היום האחרון {{#invoke:תאריך|חשב טווח|5 ביוני 1967 - 10 ביוני 1967|כולל=כן}} 6 ימים
כולל היום האחרון {{#invoke:תאריך|חשב טווח|14 ספטמבר 2014 - 14 ספטמבר 2014|כולל=כן}} יום
שנה ויום {{#invoke:תאריך|חשב טווח|14 ספטמבר 2014 - 15 ספטמבר 2015|כולל=כן}} שנה

הערות:

  • כאשר לא ניתן תאריך יעד תאריך היעד נקבע כזמן הנוכחי
  • הפרש - מציין את הפרש הזמנים בשניות וללא מילים. ניתן להשתמש בערך המוחזר בחלוקה מתאימה לקבלת יחידות זמן אחרות.
  • ניתן להוסיף פרמטר כולל=כן, ואז נלקח בחשבון גם היום האחרון. כשמדובר על טווח זמן ארוך והפורמט נבחר אוטומטי או שמכיל שנים, מתקבלת תוצאה מקורבת.
  • ניתן להוסיף פרמטר error והתוכן שלו יוצג במקרה של שגיאה בטווח התאריכים. (רצוי להכניס במקרה כזה את הדף לקטגוריה כלשהי שתאפשר מעקב אחרי דפים לא תקינים. ברירת המחדל היא קטגוריה:דפים עם שגיאות בתאריך)
  • אם לא מצוין פורמט, הוא נבחר אוטומטית:
    • עד ל-3 שבועות הוא מוצג בימים
    • עד שנה הוא מוצג בימים ושבועות
    • עד ל-10 שנים בשנים ושבועות
    • מעבר לזה רק בשנים

בדיקות

דוגמאות לשימוש ביחידה ופלט לדוגמה מודגמים ביחידה:תאריך/בדיקות.


  1. ^ א
  2. ^ ב
  3. ^ ב
  4. ^ ב
  5. ^ ב
  6. ^ ב
  7. ^ ב
function parseStrDate(dateStr, dateType)
	local dates = {
		['ינואר']= 1,
		['פברואר']= 2,
		['מרץ']= 3,
		['אפריל']= 4,
		['מאי']= 5,
		['יוני']= 6,
		['יולי']= 7,
		['אוגוסט']= 8,
		['ספטמבר']= 9,
		['אוקטובר']= 10,
		['נובמבר']= 11,
		['דצמבר']= 12
	}
	-- Remove instances of [ and ]
	dateStr = mw.ustring.gsub( dateStr, "[%[%]]", "" )
	-- Remove footnotes & directionality markers
	dateStr = mw.text.killMarkers( dateStr )
	dateStr = mw.ustring.gsub(dateStr, "‏","")
	dateStr = mw.ustring.gsub(dateStr, "‎","")
	mw.log('תאריך' .. ":" .. dateStr)
	-- BC to minus
	dateStr = mw.ustring.gsub( dateStr, "([0-9]+) לפנה\"ס" , "-%1")
	-- replace month names to numbers. The month number will be 10000001..10000012, 
	-- in order to facilitate testing later on.
	for a in pairs(dates) do
		dateStr = mw.ustring.gsub(dateStr, 'ב?'..a, dates[a]+1e7) 
	end
	-- if there are alphabet chars return nil (unexpected character)
	assert(not mw.ustring.find(dateStr, '%a'), "Unexpected format")
 	
	local parts = mw.text.split(dateStr,' ')
	local res

	if #parts==3 then -- DMY date
		local ye=tonumber(parts[3])
		local mo=tonumber(parts[2])-1e7
		local da=tonumber(parts[1])
		assert(ye<1e7, "Could not recognize year")
		assert(mo<13 and mo>0, "Could not recognize month number")
		assert(da<32 and da>0, "Wrong date format")
		if dateType=='Y' then
			res = ye
		elseif dateType=='M' then
			res = mo 
		elseif dateType=='D' then
			res = da
		elseif dateType == 'TS' then
			res = ye.."-"..mo.."-"..da
		end
	elseif  #parts==2 then -- MY date
		local ye=tonumber(parts[2])
		local mo=tonumber(parts[1]) - 1e7 
		assert(ye<1e7, "Could not recognize year")
		assert(mo<13 and mo>0, "Could not recognize month number")
		if dateType=='Y' then
			res = ye
		elseif dateType=='M' then
			res = mo
		elseif dateType == 'TS' then
			res = ye.."-"..mo
		end
	elseif #parts==1 then --Y date
		local ye=tonumber(parts[1])
		assert(ye<1e7, "Could not recognize year")
		if dateType=='Y' then
			res = ye
		elseif dateType == 'TS' then
			res = ye
		end
	else
		error("Unexpected date format")
	end

	return res
end

function parseDateRange(dateRangeStr, diffFormat, inclusive )
	-- remove footnotes
	dateRangeStr = mw.ustring.gsub(dateRangeStr, "(\127UNIQ[^\127]+QINU\127)", "")
	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 res1 = parseStrDate(parts[1], 'TS' )
	local year1, month1, day1

	if mw.ustring.sub( res1, 0, 1 ) == '-' then
		year1, month1, day1 = unpack(mw.text.split(mw.ustring.sub( res1, 2 ), '-'))
		year1 = -(tonumber(year1))
	else
		year1, month1, day1 = unpack(mw.text.split( res1, '-'))
	end
	local origDay=day1
	local origMonth=month1	
	
	local t2
	local year2, month2, day2
	if #parts==2 then
		local res2 = parseStrDate( parts[2], 'TS' )
		if mw.ustring.sub( res2, 0, 1 ) == '-' then
			year2, month2, day2 = unpack(mw.text.split(mw.ustring.sub( res2, 2 ), '-'))
			year2 = -(tonumber(year2))
		else
			year2, month2, day2 = unpack(mw.text.split( res2, '-'))
		end		
	else
		t2 = os.time()
	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 ((month1 and not month2 and not t2) or (not month1 and month2)) then
		return '' -- Ambiguous date range
	end
	local NO_GUESS, MONTH_GUESS, DAY_GUESS = 0, 1, 2
	local guessLevel = NO_GUESS
	if not month1 or (not t2 and not month2) then 
		guessLevel = MONTH_GUESS
		inclusive=true
	elseif not day1 or  (not t2 and not day2) then
		guessLevel = DAY_GUESS
	end

	--assign default value
	month1 = month1 or 6
	month2 = month2 or 6

	day1 = day1 or 16
	day2 = day2 or 16
	local t1 = os.time({
		year = year1,
		month = month1,
		day = day1
		})
	t2=t2 or os.time({
			year = year2,
			month = month2,
			day = day2
			})

	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 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
			dif = dif-((readableInterval['days']<30 and 1) or -1)*readableInterval['days']*(60*60*24)
			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

return {
	['חשב'] = parseStrDateSafe,
	['חשב טווח'] =  parseDateRangeSafe,
	['parseDateRange'] =  parseDateRange,
}