Module:Sandbox/AlphaZeta/test3

--[[ Calculates years between two dates, for example birth date and death date. Input dates can be in any of these formats:	"1999-12-31"	"1999-12"	"1999"	"31 december 1999" 	"31 dec 1999" 	"december 1999" 	"dec 1999" 	also dates with links are accepted, ie "[31 december] [1999]" 	case doesnt matter, "31 DECEMBER 1999"	"f.Kr." (BC) and "e.Kr." (AD) allowed, ie "300 f.Kr." Usage:

age
================================ Years between now and a date

Years between two dates

Result will be in these forms: "87 år" "87 eller 88 år" (range if years without month or day give) "" (if error)

date conversion
==================== Date to iso-date

returns: "1975-12-31"

Date to short date

returns: "31 dec 1975"

Date to long date

returns: "31 december 1975"

date conversion with links
=========

returns: "[31 december|31 dec] [1975]"

returns: "[31 december] [1975]"

returns: "[31 december|31 dec] [Konstår 1975|1975]"

returns: "[31 december] [Konstår 1975|1975]" ]]

local main = {}; local months_long={'januari','februari','mars','april','maj','juni','juli','augusti','september','oktober','november','december'} local months_short={'jan','feb','mar','apr','maj','jun','jul','aug','sep','okt','nov','dec'}

local useEkrFkr -- flag that "e.Kr." or "f.Kr." (ED/BC) was used on input string and so should also be used in output local nbsp=' '

-- split string s into an array function split(s, delimiter) result = {}; for match in (s..delimiter):gmatch("(.-)"..delimiter) do       table.insert(result, match); end return result; end

-- remove links from text local function removeLinks(text) text=string.gsub(text,"%[%^%[%-|([^%[%]|]-)%]%]","%1") -- link, text separated by "|". Handles case of File: when no alt= is specified, -assuming- last field is the legend text=string.gsub(text,"%[%[([^%[%]|]-)%]%]","%1") -- link with no funny |s at all return text end

-- remove trailing and leading whitespace from string. -- http://en.wikipedia.org/wiki/Trim_(8programming) local function trim(s) return (s:gsub("^%s*(.-)%s*$", "%1")) end

-- convert month from string to number local function convertmonth( month ) month = string.lower(month) for i, m in ipairs(months_long) do		if m==month then return i end end for i, m in ipairs(months_short) do		if m==month then return i end end return -1 end

-- get max number of days in a month local function daysInMonth(month) if month==2 then return 29 elseif month==4 or month==6 or month==9 or month==11 then return 30 else return 31 end end

-- takes 3 strings and returns a date object -- input:year="1999", month="12", day="31" -- output: {year=1999,month=12,day=31} or nil if date not valid local function createDateObject(year,month,day,bc) local year=tonumber(year) if bc then year=-year end local month=tonumber(month) local day=tonumber(day) if year==nil or month ==nil or day == nil then return nil end if month 12 then return nil end if day daysInMonth(month) then return nil end return {year=year,month=month,day=day} end

-- convert date string to date format -- input: a date string, example "1930 e.Kr." "1956-12-20" "12 dec 1940" "januari 2001" -- output: {year=1999,month=12,day=31} or nil if not valid local function convertdate( date ) local bc=false --negativ years date=removeLinks(date) date=trim(date) date=date:lower local pos pos=date:find('e%p?kr') if (pos~=nil) then useEkrFkr=true date=date:sub(1,pos-1) else pos=date:find('f%p?kr') if (pos~=nil) then useEkrFkr=true bc=true date=date:sub(1,pos-1) end end -- Check if date in numeric format (1999 or 1999-12 or 1999-12-31) if not string.match ( date ,"%a" ) then date=date:gsub(' ','') -- remove all spaces local datesplit=split(date, "-") local count=table.getn(datesplit) if count==1 then return createDateObject(datesplit[1],0,0,bc) end if count==2 then return createDateObject(datesplit[1],datesplit[2],0,bc) end if count==3 then return createDateObject(datesplit[1],datesplit[2],datesplit[3],bc) end return nil end

-- Date with written month, "31 dec(ember) 1999" or "dec(ember) 1999" date=string.gsub(date, "%s+", " ") local datesplit=split(date, " ") local count=table.getn(datesplit) if count==2 then return createDateObject(datesplit[2],convertmonth(datesplit[1]),0,bc) end if count==3 then return createDateObject(datesplit[3],convertmonth(datesplit[2]),datesplit[1],bc) end return nil end -- takes two date objects and returns number of years between them -- both dates must have year, month and day local function yearsBetweenDates(date1,date2) if date1.year>date2.year or 	(date1.year==date2.year and date1.month>date2.month ) or 	(date1.year==date2.year and date1.month==date2.month and date1.day>date2.day ) then local tmp=date1 date1=date2 date2=tmp end local years=date2.year-date1.year if date1.month>date2.month or ((date1.month==date2.month) and date1.day>date2.day) then years=years-1 end return years end

-- takes two date objects and returns number of years between them -- both dates must have year. Month and day are optional. local function yearsBetweenUnfixedDates(date1,date2) local date1_hi,date1_low local date2_hi,date2_low if date1.month>0 and date1.day>0 then date1_low=date1 date1_hi=date1 elseif date1.month>0 then date1_low={year=date1.year,month=date1.month,day=1} date1_hi={year=date1.year,month=date1.month,day=daysInMonth(date1.month)} else date1_low={year=date1.year,month=1,day=1} date1_hi={year=date1.year,month=12,day=31} end if date2.month>0 and date2.day>0 then date2_low=date2 date2_hi=date2 elseif date2.month>0 then date2_low={year=date2.year,month=date2.month,day=1} date2_hi={year=date2.year,month=date2.month,day=daysInMonth(date2.month)} else date2_low={year=date2.year,month=1,day=1} date2_hi={year=date2.year,month=12,day=31} end local years1=yearsBetweenDates(date1_low,date2_hi) local years2=yearsBetweenDates(date1_hi,date2_low) if years1==years2 then return years1 elseif years1>years2 then return years2..' eller '..years1 else return years1..' eller '..years2 end end

local function checkLinkArg(larg) if (larg==nil) then linkArg='' elseif (larg:lower=='link') then linkArg='link' else local cpos=larg:find(':') if cpos~=nil then linkArg=larg:sub(cpos+1) end end end

local function createLinkText(link,text) if text==nil or text=='' then return '' elseif link==nil or link=='' then return text elseif link==text then return ..text.. else return ..text.. end

end

--- function main.format(date,link,longFormat) local makeLinks=false local linkPrefix='' -- Process link argument -- can be: nil, "", "link", "link:" or "link:Prefix" if (link==nil or link=="") then makeLinks=false elseif (link:lower=='link' or link:lower=='link:') then makeLinks=true linkPrefix='' else local cpos=link:find(':') if cpos~=nil then makeLinks=true linkPrefix=link:sub(cpos+1)..' ' end end

-- Process date arguement, if any error just return it	local dateObj=convertdate(date) if dateObj==nil then return date end

-- Build the date string -- date and month local result='' if dateObj.month>0 then if (longFormat) then result=months_long[dateObj.month] else result=months_short[dateObj.month] end if dateObj.day>0 then result=dateObj.day..' '..result if makeLinks then result=createLinkText(dateObj.day..' '..months_long[dateObj.month],result) end end result=result..' ' end -- year local yearString,yearLink if dateObj.year<0 then yearString=(-dateObj.year)..' f.Kr.' yearLink=linkPrefix..yearString elseif useEkrFkr and dateObj.year>0 then yearString=dateObj.year..' e.Kr.' yearLink=linkPrefix..dateObj.year else yearString=dateObj.year yearLink=linkPrefix..yearString end if (not makeLinks) then result=result..yearString else result=result..createLinkText(yearLink,yearString) end

return result end

function main.yearsBetween(date1,date2) if (date1==nil or date1=='') then return '' end if (date2==nil or date2=='') then date2=os.date("%Y-%m-%d") end local dateObj1=convertdate(date1) local dateObj2=convertdate(date2) if dateObj1==nil or dateObj2==nil then return "" end return yearsBetweenUnfixedDates(dateObj1,dateObj2) ..nbsp..'år' end

function main.to_iso(input) local input_date=input.args[1] local date1=convertdate(input_date) if date1==nil then return input_date end local result=date1.year..'-' if (date1.month)<10 then result=result..'0' end result=result.. date1.month..'-' if (date1.day)<10 then result=result..'0' end result=result.. date1.day return result end

function main.to_long(input) return main.format(input.args[1],input.args[2],true) end

function main.to_short(input) return main.format(input.args[1],input.args[2],false) end

function main.age(input) return main.yearsBetween(input.args[1],input.args[2]) end return main