Module:Birthday

local p = {}

D = {} J = {} T = {}

function BirthdayInsert(Date, Japanese, Transliterated) table.insert(D, Date) table.insert(J, Japanese) table.insert(T, Transliterated) end

--When adding, do so in the right place. It's first ordered by day, then within days by years oldest to newest. --This way it's already in an order best for most of the birthday functions, and no sorting needs to be programmed in.

BirthdayInsert('1992-01-04', '谷口奈々', 'Taniguchi Nana') BirthdayInsert('1993-01-06', '若葉理安', 'Wakaba Ria') BirthdayInsert('1995-01-07', '倉本美香', 'Kuramoto Mika') BirthdayInsert('1995-01-13', '朝長穂乃果', 'Tomonaga Honoka') BirthdayInsert('1994-01-14', '宮本秋', 'Miyamoto Aki') BirthdayInsert('1998-01-15', '山下道子', 'Yamashita Michiko') BirthdayInsert('2002-01-15', '山田芙美', 'Yamada Fumi') BirthdayInsert('1998-01-19', '山本愛子', 'Yamamoto Aiko')

BirthdayInsert('1999-02-01', '二宮理利', 'Ninomiya Riri') BirthdayInsert('1992-02-27', '秋元あゆみ', 'Akimoto Ayumi') BirthdayInsert('1993-02-27', '柏木レナ', 'Kashiwagi Rena')

BirthdayInsert('1998-03-07', '穴見比奈', 'Anami Hina') BirthdayInsert('1995-03-15', '日笠愛', 'Hikasa Ai') BirthdayInsert('1998-03-17', '水谷理沙', 'Mizutani Risa')

BirthdayInsert('2002-04-03', '水原満里奈', 'Mizuhara Marina') BirthdayInsert('1995-04-08', '吉川美春', 'Kikkawa Miharu') BirthdayInsert('1996-04-15', '森川ここみ', 'Morikawa Kokomi') BirthdayInsert('1997-04-24', '山本麻未', 'Yamamoto Ami') BirthdayInsert('1991-04-26', '夜神亜里紗', 'Yagami Arisa') BirthdayInsert('1994-04-28', '立花蝶子', 'Tachibana Chouko')

BirthdayInsert('1989-05-01', '川瀬美春', 'Kawase Miharu') BirthdayInsert('2000-05-03', '三浦莉子', 'Miura Riko') BirthdayInsert('1992-05-07', '宮崎遊狩', 'Miyazaki Yuukari') BirthdayInsert('1997-05-10', '前原あゆな', 'Maehara Ayuna') BirthdayInsert('1986-05-12', '山下歩美', 'Yamashita Ayumi') BirthdayInsert('1999-05-19', '奥山コノリ', 'Okuyama Konori') BirthdayInsert('1992-05-23', '喜佐美愛生', 'Kisami Mei') BirthdayInsert('1988-05-25', '渡辺秀', 'Watanabe Shu') BirthdayInsert('1991-05-29', '河野さくら', 'Kawano Sakura')

BirthdayInsert('1995-06-05', '春神涼香', 'Harukami Suzuka') BirthdayInsert('1992-06-08', '猿渡道代', 'Saruwatari Michiyo') BirthdayInsert('2001-06-11', '亜沙見菖蒲', 'Asami Ayame') BirthdayInsert('1987-06-16', '前田友依', 'Maeda Yui') BirthdayInsert('1995-06-16', '宮藤玲', 'Miyafuji Rei') BirthdayInsert('1995-06-16', '芦川彬子', 'Ashikawa Akiko') BirthdayInsert('1999-06-20', '川本千代', 'Kawamoto Chiyo') BirthdayInsert('1993-06-24', '星野愛美', 'Hoshino Manami')

BirthdayInsert('1987-07-03', '最上花', 'Mogami Hana') BirthdayInsert('1990-07-17', '小原泉美', 'Kohara Izumi') BirthdayInsert('1997-07-18', '清水若菜', 'Shimizu Wakana') BirthdayInsert('1991-07-23', '松井美幸', 'Matsui Miyuki')

BirthdayInsert('1995-08-08', '川崎まゆら', 'Kawasaki Mayura') BirthdayInsert('1992-08-16', '鈴木愛子', 'Suzuki Aiko') BirthdayInsert('1993-08-28', '小泉雨夜', 'Koizumi Amaya') BirthdayInsert('1997-08-31', '御碕樹理', 'Misaki Juri')

BirthdayInsert('1996-09-04', '太光姫々紀', 'Tako Hibiki') BirthdayInsert('1986-09-10', '楠田希', 'Kusuda Nozomi') BirthdayInsert('1996-09-12', '田井中利奈', 'Tainaka Rina') BirthdayInsert('1995-09-14', '明石千代', 'Akashi Chiyo') BirthdayInsert('1997-09-17', '月村由美', 'Tsukimura Yumi') BirthdayInsert('1999-09-19', '筒井美月', 'Tsutsui Mizuki') BirthdayInsert('1998-09-19', '井上菜奈', 'Inoue Nana') BirthdayInsert('1989-09-21', '田中真子', 'Tanaka Mako') BirthdayInsert('2001-09-21', '新井優奈', 'Arai Yuna') BirthdayInsert('1999-09-23', '早水奏愛', 'Hayami Kaname')

BirthdayInsert('1993-10-03', '加藤冬美', 'Kato Fuyumi') BirthdayInsert('1997-10-12', '安藤ひかり', 'Ando Hikari') BirthdayInsert('1999-10-16', '加持明日陽', 'Kaji Asuhi') BirthdayInsert('1986-10-18', '石田樹里', 'Ishida Juri') BirthdayInsert('1991-10-19', '藤香花美', 'Fujika Hanami') BirthdayInsert('1994-10-20', '山崎春香', 'Yamazaki Haruka') BirthdayInsert('1996-10-29', '加嶋理香', 'Kashima Rika')

BirthdayInsert('1995-11-03', '渡辺佑美', 'Watanabe Yumi') BirthdayInsert('1993-11-10', '若久絵美', 'Wakahisa Emi') BirthdayInsert('1999-11-18', '井上雅美', 'Inoue Masami') BirthdayInsert('1994-11-26', '藤原みちよ', 'Fujiwara Michiyo') BirthdayInsert('1993-11-28', '山根侑姫', 'Yamane Yuki') BirthdayInsert('1998-11-29', '宮本月子', 'Miyamoto Tsukiko')

BirthdayInsert('1992-12-10', '大塚真希', 'Otsuka Maki') BirthdayInsert('1995-12-11', '火音美波', 'Hine Minami') BirthdayInsert('1999-12-15', '市川愛生', 'Ichikawa Miu') BirthdayInsert('1995-12-22', '松田菜々美', 'Matsuda Nanami')

function Ordinal(anumber) if anumber % 10 == 1 then return anumber .. "st" elseif anumber % 10 == 2 then if anumber%100==12 then return anumber .. "th" else return anumber .. "nd" end elseif anumber % 10 == 3 then if anumber%100==13 then return anumber .. "th" else return anumber .. "rd" end else return anumber .. "th" end end

function WhichBirthday(yyyymmdd) --Just rounds to which age is nearest. For standard uses of looking forward a week, it does the trick. _, _, y, m, d = string.find(yyyymmdd, "(%d%d%d%d)-(%d%d)-(%d%d)") difference = os.time - os.time{year=y, month=m, day=d} difference = difference / 31555008 difference = math.floor(difference+0.5) --Rounding return Ordinal(difference) end

function WhereDayXStarts(mmdd) i = 0 repeat i=i+1 until string.sub( D[i], 6, 10 ) >= mmdd or i == table.getn(D) if string.sub(D[i], 6, 10) < mmdd then i = 1 end --If we've gone all the way and found squat, stick to the beginning. return i --.. " " .. string.sub( D[i], 6, 10 ) .. " >= " .. mmdd .. " or i == " .. table.getn(D) end

function WhereDayXEnds(mmdd) _, _, m, d = string.find(mmdd, "(%d%d)-(%d%d)") if d+1 < 10 then nextday = m .. "-0" .. d+1 --Needs zero padded else nextday = m .. "-" .. d+1 --Even if this date isnt' real, it should work as a point of comparison end if nextday=="12-32" then return table.getn(D) -- As long as things are properly ordered, the table ends with the end of the year. else thisdaybegins = WhereDayXStarts(mmdd) itbegins = WhereDayXStarts(nextday) if(thisdaybegins==itbegins) then --Next day starts no later than today, so no need to subtract 1. ThenWhereDayXEnds = itbegins else ThenWhereDayXEnds = itbegins - 1 --Just before where the next day starts, see. if ThenWhereDayXEnds == 0 then ThenWhereDayXEnds = table.getn(D) end --Again if the very beginning is "after", the end is... the end. end return ThenWhereDayXEnds end end

function p.upcoming(frame) num_days = tonumber(frame.args.days or 7) num_min = tonumber(frame.args.min or 2) starting = frame.args.starting or os.date("%m-%d",os.time+32400) ending = os.date("%m-%d", os.time{year=2001, month=string.sub(starting,1,2), day=string.sub(starting,4,5)}+86400*(num_days-1))

STARTBEGINS = WhereDayXStarts(starting) ENDENDS = WhereDayXEnds(ending) LISTEND = table.getn(D)

--output = "starting: " .. starting .. " ending: " .. ending .. " STARTBEGINS: " .. STARTBEGINS .. " ENDENDS: " .. ENDENDS .. " LISTEND: " .. LISTEND

startread2 = 0 endread2 = -1 if ENDENDS>=STARTBEGINS then if (ENDENDS-STARTBEGINS+1) >= num_min then --Is Y greater than X and Y-X>=Min? Fantastic! Read from spots X through Y.           --output = output .. " CASE 1 " startread1 = STARTBEGINS endread1 = ENDENDS startread2 = 0 elseif (LISTEND-STARTBEGINS+1) >= num_min then --Is Y greater than X, Y-X=Min? OK, find what date X+Min is, find where that date ends, call it Y. Read from spots X through Y.           --output = output .. " CASE 2 " ending = string.sub(D[STARTBEGINS+num_min-1], 6, 10 ) --mm-dd for minimum spot ENDENDS = WhereDayXEnds(ending) startread1 = STARTBEGINS endread1 = ENDENDS else --Need more to hit minimum, rest of list isn't enough. Need to check beginning of list for end of minimum and read those too. --output = output .. " CASE 3 " ending = string.sub(D[num_min-(LISTEND-STARTBEGINS+1)], 6, 10 ) --mm-dd for minimum spot ENDENDS = WhereDayXEnds(ending) startread1 = STARTBEGINS endread1 = LISTEND startread2 = 1 endread2 = ENDENDS end else if (LISTEND-STARTBEGINS+ENDENDS) >= num_min then --Is Y less than X and (End-X+Y)>=Min? Read from spots X through End, then 1 through Y.           --output = output .. " CASE 4 " startread1 = STARTBEGINS endread1 = LISTEND startread2 = 1 endread2 = ENDENDS else --Is Y less than X, (End-X+Y)<Min? OK, find what date (Min-End-X) is, find where that date ends, call it Y. Read from spots X through End, then 1 through Y.           --Very similar to an earlier case, except this time Y has already looped. Calculations should remain the same, though. --output = output .. " CASE 5 " ending = string.sub(D[num_min-(LISTEND-STARTBEGINS+1)], 6, 10 ) --mm-dd for minimum spot ENDENDS = WhereDayXEnds(ending) startread1 = STARTBEGINS endread1 = LISTEND startread2 = 1 endread2 = ENDENDS end end

--output = output .. " ending: " .. ending .. " ENDENDS: " .. ENDENDS --output = output.. " startread1: " .. startread1 .. " " .. T[startread1] .. " endread1: " .. endread1 .. " " .. T[endread1] .. " startread2: " .. startread2 .. " endread2: " .. endread2 .. "\n"

lastday = 0 output = ""

--First read group i = startread1 while i<= endread1 do       thisday = string.sub( D[i], 6, 10 ) if thisday ~= lastday then --It's a new day, something should be written. output = output .. ";" .. os.date("%B %e", os.time{year=2001, month=string.sub(D[i],6,7), day=string.sub(D[i],9,10)}) .. ", "           if thisday==starting then output = output .. "Happy Birthday!" else output = output .. "Coming Soon" end output = output .. "\n" end output = output .. ":" .. T[i] .. " (" .. WhichBirthday(D[i]) .. ")\n" lastday = thisday i=i+1 end

--Second read group i = startread2 while i<= endread2 do       thisday = string.sub( D[i], 6, 10 ) if thisday ~= lastday then --It's a new day, something should be written. output = output .. ";" .. os.date("%B %e", os.time{year=2001, month=string.sub(D[i],6,7), day=string.sub(D[i],9,10)}) .. ", "           if thisday==starting then output = output .. "Happy Birthday!" else output = output .. "Coming Soon" end output = output .. "\n" end output = output .. ":" .. T[i] .. " (" .. WhichBirthday(D[i]) .. ")\n" lastday = thisday i=i+1 end

return output -- .. " " .. os.clock end

function p.year(frame) year = frame.args[1] or 1982 lastday = 0 output = "" for i=1, table.getn(D), 1 do       if string.sub(D[i],1,4) == year then thisday = string.sub( D[i], 6, 10 ) if thisday ~= lastday then output = output .. ";" .. os.date("%B %e", os.time{year=2001, month=string.sub(D[i],6,7), day=string.sub(D[i],9,10)}) .. "\n" end output = output .. ":" .. T[i] .. "\n" lastday = thisday end end return output end

function p.month(frame) month = frame.args[1] or 1 if month == '1' or month == '01' then starting='01-01' ending='02-01' elseif month == '2' or month == '02' then starting='02-01' ending='03-01' elseif month == '3' or month == '03' then starting='03-01' ending='04-01' elseif month == '4' or month == '04' then starting='04-01' ending='05-01' elseif month == '5' or month == '05' then starting='05-01' ending='06-01' elseif month == '6' or month == '06' then starting='06-01' ending='07-01' elseif month == '7' or month == '07' then starting='07-01' ending='08-01' elseif month == '8' or month == '08' then starting='08-01' ending='09-01' elseif month == '9' or month == '09' then starting='09-01' ending='10-01' elseif month == '10' then starting='10-01' ending='11-01' elseif month == '11' then starting='11-01' ending='12-01' elseif month == '12' then starting='12-01' ending='12-31' end STARTBEGINS = WhereDayXStarts(starting) --ENDENDS = WhereDayXEnds(ending) if month=='12' then NEXTBEGINS = table.getn(D) + 1 -- Past the end else NEXTBEGINS = WhereDayXStarts(ending) end

lastday = 0 output = "" i = STARTBEGINS while i < NEXTBEGINS do       thisday = string.sub( D[i], 6, 10 ) if thisday ~= lastday then --It's a new day, something should be written. output = output .. ";" .. os.date("%B %e", os.time{year=2001, month=string.sub(D[i],6,7), day=string.sub(D[i],9,10)}) .. "\n" end output = output .. ":" .. T[i] .. " (" .. string.sub(D[i], 1, 4) .. ")\n" lastday = thisday i=i+1 end return output end

function p.age(frame) age = frame.args[1] or 20 output = "" starting = os.date("%Y-%m-%d",os.time+32400) --Y-m-d for today in Japan _, _, y, m, d = string.find(starting, "(%d%d%d%d)-(%d%d)-(%d%d)") LOWBORDER = y-age .. "-" .. m .. "-" .. d   if d+1<10 then --needs a leading 0 HIGHBORDER = y-age-1 .. "-" .. m .. "-0" .. d+1 else HIGHBORDER = y-age-1 .. "-" .. m .. "-" .. d+1 --Might be an improper date, but for comparison purposes should work end --output = "LOWBORDER: " .. LOWBORDER .. " HIGHBORDER: " .. HIGHBORDER --return output STARTBEGINS = WhereDayXStarts(string.sub(HIGHBORDER,6,10))

--First half i = STARTBEGINS while i<= table.getn(D) do       if D[i] >= HIGHBORDER and D[i] <= LOWBORDER then output = output .. ":" .. T[i] .. " (" .. D[i] .. ")\n" end i=i+1 end

--Second half i = 1 while i<= STARTBEGINS-1 do       if D[i] >= HIGHBORDER and D[i] <= LOWBORDER then output = output .. ":" .. T[i] .. " (" .. D[i] .. ")\n" end i=i+1 end

return output end

function p.between(frame) startdate=frame.args[1] enddate=frame.args[2] if startdate > enddate then --You trying to screw things up? Well, we'll just flip 'em. temp = startdate startdate = enddate enddate = temp end output = ""

year = string.sub(startdate,1,4) while year<=string.sub(enddate,1,4) do       if year==string.sub(startdate,1,4) then lowcomparison = string.sub(startdate,6,10) --If it's the first year, only start at the given date else lowcomparison = '01-01' end if year==string.sub(enddate,1,4) then highcomparison = string.sub(enddate,6,10) --If it's the last year, stop by the given date else highcomparison = '12-31' end

i = 1 while i<= table.getn(D) do           if string.sub(D[i],1,4) == year and string.sub(D[i],6,10) >= lowcomparison and string.sub(D[i],6,10) <= highcomparison then output = output .. ":" .. T[i] .. " (" .. D[i] .. ")\n" end i=i+1 end year=tostring(year+1) end return output end

function p.random math.randomseed( os.time ) return "" .. T[math.random(" end

return p

-- --ja:モジュール:誕生日 --cs:Modul:Narozeniny