Module:Sandbox/RexxS/CalcDate

.mw-parser-output .documentation,.mw-parser-output .documentation-metadata{border:1px solid var(--border-color-base,#a2a9b1);background-color:#ecfcf4;color:inhe

Module:Sandbox/RexxS/CalcDate
--[[ CalcDate
Modified from chunks of Module:Time
Main function: getYearMonthDay
takes a date string like "second Friday in June" as parameter |date=
and a year as parameter |year= (uses current year if omitted)
and returns the date in YYYY-MM-DD format, e.g. 2018-06-08
Other formats are possible.
]]

require ('strict')


--[[ is_set(var)
Whether variable is set or not.  A variable is set when it is not nil and not empty.
]]
local function is_set(var)
	return var and var ~= ''
end

--[[ current_year()
returns the current year
]]
local function current_year()
	return os.date('%Y', os.time())
end


--[[ decode_date_event(date_event_string)
extract ordinal, day-name, and month from daylight saving start/end definition string as digits:
	Second Sunday in March
returns
	2 0 3
Case doesn't matter but the form of the string does:
	<ordinal> <day> <any single word> <month> – all are separated by spaces
]]
local function decode_date_event(date_event_string)
	local ordinals = {
		['1st'] = 1, ['first'] = 1, ['2nd'] = 2, ['second'] = 2, ['3rd'] = 3, ['third'] = 3,
		['4th'] = 4, ['fourth'] = 4, ['5th'] = 5, ['fifth'] = 5, ['last'] = -1
	}
	local days = {
		['sunday'] = 0, ['monday'] = 1, ['tuesday'] = 2, ['wednesday'] = 3, ['thursday'] = 4, ['friday'] = 5, ['saturday'] = 6
	}
	local months = {
		['january'] = 1, ['february'] = 2, ['march'] = 3, ['april'] = 4, ['may'] = 5,
		['june'] = 6, ['july'] = 7, ['august'] = 8, ['september'] = 9, ['october'] = 10,
		['november'] = 11, ['december'] = 12
	}

	date_event_string = date_event_string:lower()
	local ord, day, month = date_event_string:match ('([%a%d]+)%s+(%a+)%s+%a+%s+(%a+)')

	if is_set(ord) and is_set(day) and is_set(month) then
		return ordinals[ord], days[day], months[month]
	else
		-- if one or more of these not set, then pattern didn't match
		return nil
	end
end


--[[ get_days_in_month(year, month)
Returns the number of days in the month where month is a number 1–12
and year is four-digit Gregorian calendar.
Accounts for leap year. Throws an error if month and year are not numbers.
]]
local function get_days_in_month(year, month)
	local days_in_month = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
	year = tonumber (year)
	month = tonumber (month)
	if month == 2 and year%4 == 0 and (year%100 ~= 0 or year%400 == 0) then
		return 29
	end
	return days_in_month [month]
end


--[[ get_date_month_day(date_event_string, year)
Return the date for the day that is the ordinal (nth) day-name in month of the given year
e.g. "second Friday in June", 2018 -> 2018-06-08
]]
local function get_date_month_day(date_event_string, year)
	local ord, weekday_num, month = decode_date_event(date_event_string)
	if not (is_set (ord) and is_set (weekday_num) and is_set (month)) then
		return nil
	end
	if ord == -1 then
		-- event occurs on the last day-name of the month
		-- j = t + 7×(n + 1) - (wt - w) mod 7
		local days_in_month = get_days_in_month (year, month)
		local ostime = os.time ({['year']=year, ['month']=month, ['day']=days_in_month})
		local last_day_of_month = os.date('%w', ostime)
		return month, days_in_month + 7 * (ord + 1) - ((last_day_of_month - weekday_num) % 7)
	else
		-- j = 7×n - 6 + (w - w1) mod 7
		local ostime = os.time({['year']=year, ['month']=month, ['day']=1})
		local first_day_of_month = os.date('%w', ostime)
		return month, 7 * ord - 6 + (weekday_num - first_day_of_month) % 7
	end
end


-- set up public functions for debugging
local p = {}
p.currentYear = current_year
p.getDateMonth = function(frame)
	local m, d = get_date_month_day(frame.args.date, frame.args.year)
	return m .. "-" .. d
end
--[[ getYearMonthDay
Takes a date string like "second Friday in June" as parameter |date=
and a year as parameter |year=
and returns the date in YYYY-MM-DD format, e.g. 2018-06-08
Other formats are easy to implement.
]]
p.getYearMonthDay = function(frame)
	local args = frame.args or frame:getParent().args
	local date_event = args.date or mw.text.trim(args[1])
	local year = args.year or args[2] or current_year()
	local month, day = get_date_month_day(date_event, year)
	month = (month<10 and "0" or "") .. month
	day = (day<10 and "0" or "") .. day
	return year .. "-" .. month .. "-" .. day
end
return p

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.