Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Module:Add to Calendar

From Mechsploit.me Wiki

Documentation for this module may be created at Module:Add to Calendar/doc

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);														-- force these to be numbers just in case
	month = tonumber (month);

	if (2 == month) then														-- if February
		if (0 == (year%4) and (0 ~= (year%100) or 0 == (year%400))) then		-- is year a leap year?
			return 29;															-- if leap year then 29 days in February
		end
	end
	return days_in_month [month];
end

local function get_date (date)
	local year, month, day, hour, minute, second;

	year, month, day, hour, minute, second = date:match ('(%d%d%d%d)%-(%d%d?)%-(%d%d?)T(%d%d?):(%d%d?):(%d%d?)');
	if not year then
		year, month, day, hour, minute, second = date:match ('^(%d%d%d%d)(%d%d)(%d%d)(%d%d)(%d%d)(%d%d)$');
		if not year then
			return nil;															-- test time did not match the specified patterns
		end
	end
	local t = {['year'] = tonumber(year), ['month'] = tonumber(month), ['day'] = tonumber(day), ['hour'] = tonumber(hour), ['min'] = tonumber(minute), ['sec'] = tonumber(second) or 0};
    
    if t.hour < 0 or t.hour > 23 or t.min < 0 or t.min > 59 or t.sec < 0 or t.sec > 59 then
        return nil; -- Invalid time values
    end
    
    if t.month < 1 or t.month > 12 then
        return nil; -- Invalid month
    end

    if t.day < 1 or t.day > get_days_in_month(t.year, t.month) then
        return nil; -- Invalid day for the month
    end
    return t; -- Return the table with valid date and time
end

local function get_utc_offset (utc_offset)

	local h, m, sep, sign;
	

	local patterns = {
		'^([%+%-±−]?)(%d%d?%.%d%d?)$',										-- one or two fractional hour digits
		'^([%+%-±−]?)(%d%d?):(%d%d)$',										-- two minute digits
		'^([%+%-±−]?)(%d%d?)[%.:]?$',											-- hours only; ignore trailing separator
		}
	
	for _, pattern in ipairs(patterns) do										-- loop through the patterns
		sign, h, m = mw.ustring.match (utc_offset, pattern);
		if h then
			break;																-- if h is set then pattern matched
		end
	end

	if not h then
		return nil;														-- did not match a pattern
	end

    if '-' == sign then sign = -1; else sign = 1; end
	h = tonumber(h)
	m = tonumber(m) or 0;
	return sign * ((h * 3600) + (m * 60));
end

local function main(frame)
	local getArgs = require('Module:Arguments with aliases').getArgs
	local arg_aliases = {
        text = { 'text', 'title' },
        date = { 'date', 'start' },
        end_date = { 'end_date', 'end' },
        details = { 'details', 'description' },
        location = { 'location', 'venue' },
        url_title = { 'url_title' },
        timezone = { 'timezone', 'tz' }
    }
    
    local args = getArgs(frame, {
        aliases = arg_aliases,
    })
    
    local date_txt = ''
	local tz_offest = (args.timezone and get_utc_offset(args.timezone)) or 0
	
    local date_t = args.date and get_date(args.date) or nil
    local end_date_t = args.end_date and get_date(args.end_date) or nil
    
    
    if not date_t then
        return error('Invalid date format. Please use YYYY-MM-DDThh:mm:ss or YYYYMMDDhhmmss.');
    end
    
    local date_u = os.time(date_t) + tz_offest
    local end_date_u = date_u

    if end_date_t then
        end_date_u = os.time(end_date_t) + tz_offest
        if end_date_u < date_u then
            return error('End date cannot be before start date.');
        end
    end
    date_txt = os.date('%Y%m%dT%H%M%SZ', date_u) .. '/' .. os.date('%Y%m%dT%H%M%SZ', end_date_u);


    return '<span class="add-to-calendar">' ..
        '[https://calendar.google.com/calendar/render?action=TEMPLATE' .. 
        '&text=' .. mw.uri.encode(args.text or '') ..
        '&dates=' .. date_txt ..
        '&details=' .. mw.uri.encode(args.details or '') ..
        '&location=' .. mw.uri.encode(args.location or '') ..
        -- '&ctz=' .. mw.uri.encode(args.timezone or 'UTC') ..
        ' ' .. (args.url_title or 'Add to calendar') .. ']' ..
        '</span>';
end

return {
	main = main
}