# Module:Date/example

-- Examples showing how to use Module:Date. See the talk page for output.  
local Date = require('Module:Date')._Date  

local show -- function defined below to display results  

-- A date can be constructed using various input formats.  
local function make_a_date  
show('Make a date')  
local same_dates = {  
Date(2016, 3, 9),  
Date('2016-03-09'),  
Date('2016-3-9'),  
Date('9&nbsp;March 2016'),  
Date('09 mar 2016'),  
Date('MAR 09 2016'),  
Date('March 9, 2016'),  
Date('March 9, 2016 CE'),  
Date('March 9, 2016 A.D.'),  
Date('3:45 pm 9 March 2016'),  
Date('3:45 p.m. 9 March 2016'),  
Date(2016, 3, 9, 15, 45),  
Date('9 March 2016 15:45'),  
}  
for _, date in ipairs(same_dates) do  
show(nil, date:text .. ' or ' .. date:text('mdy'))  
end  
local more_dates = {  
Date('4 October 1582', 'Julian'),  
Date('juliandate', 2299160),  
Date('15 October 1582'),  
}  
for _, date in ipairs(more_dates) do  
show(nil, date.dayname .. ' ' .. date:text .. ' in the ' ..  
date.calendar .. ' calendar is Julian day ' .. date.jd)  
end  
end  

-- A date can be displayed using various output formats.  
local function show_a_date  
show('Show a date')  
local dates = {  
Date(2016, 3, 9),  
Date('9 March 2016 BC'),  
}  
local format_option = {  
{ 'ymd' },  
{ 'mdy' },  
{ 'dmy' },  
{ 'dmy', 'era=B.C.E.' },  
{ '%A %B %-d, %Y %{era}' },  
{ '%A %B %-d, %Y %{era}', 'era=A.D.' },  
{ 'a %{dayname} in %{monthname} %Y %{era}' },  
}  
for _, t in ipairs(format_option) do  
local format = t[1]  
local option = t[2]  
for _, date in ipairs(dates) do  
show(nil, date:text(format, option))  
end  
end  
end  

-- When an input date is parsed, its format is stored.  
local function keep_format  
show('Keep format of input date')  
local somedate = Date('March 9, 2016')  
local dates = {  
Date(2016, 3, 9),  
Date('2016-3-9'),  
Date('9&nbsp;Mar 2016'),  
Date('March 9, 2016'),  
Date(somedate, {day = 1}), -- somedate with day changed  
somedate + 23, -- 23 days after somedate  
somedate - '3 months', -- 3 months before somedate  
Date('3:45&nbsp;p.m. March&nbsp;9, 2016'),  
}  
show(nil, 'Format of somedate was ' .. somedate.format)  
for _, date in ipairs(dates) do  
show(nil, date:text .. ' or ' .. date:text(date.format))  
end  
end  

-- Using Date to get the current date, or current date and time.  
local function current_date  
local now_date = Date('currentdate')  
local now_datetime = Date('currentdatetime')  
show('Current date showing when this page was last purged',  
now_date:text, -- 7 March 2016 (for example)  
now_date:text('mdy'), -- March 7, 2016  
now_date:text('ymd'), -- 2016-03-07  
now_date:text('%A %-d %B %-Y'), -- Monday 7 March 2016  
now_datetime:text, -- 21:32:45 7 March 2016  
now_datetime:text('hms'), -- 21:32:45  
now_datetime:text('%c') -- 9:32 pm 7 March 2016  
end  

-- Using current to provide default values.  
local function current_as_default(year, month, day, hour, minute, second)  
local current = require('Module:Date')._current  
year = year or current.year  
month = month or current.month  
day = day or current.day  
hour = hour or current.hour  
minute = minute or current.minute  
second = second or current.second  
show('Using the current date as a default',  
year, month, day, hour, minute, second)  
-- Alternatively, a date can be constructed with specified items overridden.  
show(nil, Date('currentdatetime', {  
year = year,  
month = month,  
day = day,  
hour = hour,  
minute = minute,  
second = second }):text('%c'))  
end  

-- Make a date from the day number in a year.  
local function date_from_day_of_year  
-- Example: day 123 in 2015 and in 2016.  
show('Make a date from the day number in a year')  
local offset = 123 - 1 -- 1 January has day-of-year = 1  
for _, year in ipairs({ 2015, 2016 }) do  
local date = Date(year, 1, 1) + offset  
show(nil, 'Day ' .. date.dayofyear .. ' in ' .. year .. ' is ' .. date:text)  
end  
end  

-- Number of days in a month for Gregorian (default) and Julian calendars.  
local function days_in_month(year, month, calendar_name)  
local title = 'Days in month'  
if calendar_name then  
title = title .. ' (' .. calendar_name .. ' calendar)'  
end  
local monthdays = require('Module:Date')._days_in_month  
show(title, monthdays(year, month, calendar_name))  
-- Alternative method, using Date.  
local date = Date(year, month, 1, calendar_name)  
show(nil, date.monthname .. ' ' .. date.year .. ' had ' .. date.monthdays .. ' days')  
show(nil, date:text('%{monthname} %{year} had %{monthdays} days')) -- same  
end  

-- Julian day number and date arithmetic.  
local function julian_date(year, month, count, calendar_name)  
if calendar_name then  
show('Julian date (' .. calendar_name .. ')')  
else  
show('Julian date (Gregorian)') -- Gregorian calendar by default  
local date = Date('24 November 4714 BCE')  
show(nil, 'Julian day number was ' .. date.jd .. ' on ' .. date:text('mdy'))  
end  
local first_of_month = Date(year, month, 1, calendar_name)  
for _ = 1, count do  
first_of_month = first_of_month + '1m' -- next month  
local date = first_of_month - '1d' -- last day of month  
show(nil,  
'Last day in month (' .. date:text .. ' ' .. date.calendar ..  
' calendar) had Julian day number ' .. date.jd  
end  
end  

-- Number of days a date was in the past, or will be in the future.  
local function how_long(date_text)  
local now_date = Date('currentdate')  
local then_date = Date(date_text)  
if not then_date then  
show('How long', 'Invalid date: ' .. (date_text or ''))  
return  
end  
local fmt = '%A %B %-d, %-Y %{era} (day of year = %{dayofyear}, serial day = %{gsd}) '  
local info = then_date:text(fmt)  
if then_date == now_date then  
fmt = 'is now (%d day%s)'  
elseif then_date > now_date then  
fmt = 'will be in %d day%s'  
else  
fmt = 'was %d day%s ago'  
end  
local diff = then_date - now_date  
local days = diff.age_days  
local s = days == 1 and '' or 's'  
show('How long', info .. string.format(fmt, days, s))  
local y, m, d = diff:age('ymd') -- age in years, months, days  
show(nil, string.format('(%d years + %d months + %d days)', y, m, d))  
end  

-- First and third Fridays in each month of the given year.  
local function fridays(year)  
show('First and third Fridays in each month of ' .. year)  
for month = 1, 12 do  
local dates = Date(year, month, 1):list('Friday >=')  
show(nil, dates[1] .. ', ' .. dates[3])  
end  
end  

-- Next Friday after or before a particular date.  
local function next_friday  
show('Next Friday and last Friday for certain dates')  
local dates = {  
Date('1 Jan 2016'),  
Date('2 Jan 2016'),  
Date('3 Mar 1980'),  
}  
for _, date in ipairs(dates) do  
-- 1 = number of Fridays that are wanted in the list  
local after = date:list('1 Friday')[1]  
local before = date:list('1 Friday <')[1]  
local format = '%A %-d %B %-Y'  
show(nil,  
'For ' .. date:text(format) ..  
', the next is ' .. after:text(format) ..  
', and the last is ' .. before:text(format)  
end  
end  

-- Results are held in the lines table.  
local lines  
function show(title, ...) -- for forward declaration above  
if title then  
if lines[1] then  
table.insert(lines, '')  
end  
table.insert(lines, "**" .. title .. "**")  
end  
for _, text in ipairs({...}) do  
table.insert(lines, ':' .. tostring(text))  
end  
end  

local function main  
lines = {}  
make_a_date  
show_a_date  
keep_format  
current_date  
current_as_default(nil, nil, nil, 14, 30, 0) -- 2:30 pm today  
date_from_day_of_year  
days_in_month(1900, 2)  
days_in_month(1900, 2, 'Julian')  
julian_date(1899, 11, 4)  
julian_date(-120, 11, 4, 'Julian')  
how_long('29 Feb 2100') -- an invalid date  
how_long('currentdate')  
how_long('29 Feb 2400')  
how_long('29 Feb 2401 BCE')  
fridays(2016)  
next_friday  
return table.concat(lines, '\n')  
end  

return { main = main }