模組:Date Convert/sandbox

本页使用了标题或全文手工转换
维基百科,自由的百科全书
文档图示 模块文档[查看] [编辑] [历史] [清除缓存]

本模块用于将各类日期转换为ISO 8601格式或中文日期,以方便{{#time:params}}函数和其他模板调用。

用法

输出ISO日期

使用{{#invoke:Date_Convert|ISODate}}函数。

输入完整日期,只输入年月、只输入年份皆可:

当月和日是个位数时,十位加“0”或不加“0”皆可,模块会自动补“0”,

可以转换英文和非规范的ISO 8601日期:

如果字符串以正确的日期开头,则会转换并忽视后缀文字:

  • {{#invoke:Date_Convert|ISODate|1994年10月26日,武汉}} → 1994-10-26
  • {{#invoke:Date_Convert|ISODate|1994年10月26日,武汉|suffix=yes}} → 1994-10-26,武汉(将suffix字段设为yes展示后缀)

以不合法日期开头则报错:

  • {{#invoke:Date_Convert|ISODate|一九九四年十月二十六日}}错误:时间格式不正确
  • {{#invoke:Date_Convert|ISODate|1994年13月32日}}错误:时间格式不正确
  • {{#invoke:Date_Convert|ISODate|一九九四年十月二十六日|error=ignore}} → 一九九四年十月二十六日(将error字段设为ignore返回输入值)

ISO 8601标准只规定了1583年之后的日期标准,请勿用本模块表示这之前的日期,否则可能会得到不期待的结果:

  • {{#invoke:Date_Convert|ISODate|25年8月5日(东汉建立)|suffix=yes}} → 0023-08-05(东汉建立)

{{#invoke:ISODate|dates|xxx}}等效於此{{#invoke:Date_Convert|ISODate|xxx}}

输出中文日期

使用{{#invoke:Date_Convert|ChineseDate}}函数。

输入完整日期,只输入年月、只输入年份皆可:

当月和日是个位数时,十位加“0”或不加“0”皆可,模块会自动补“0”,

可以转换英文和非规范的ISO 8601日期:

如果字符串以正确的日期开头,则会转换并忽视后缀文字:

以不合法日期开头则报错:

  • {{#invoke:Date_Convert|ChineseDate|一九九四年十月二十六日}}错误:时间格式不正确
  • {{#invoke:Date_Convert|ChineseDate|1994年13月32日}}错误:时间格式不正确
  • {{#invoke:Date_Convert|ChineseDate|一九九四年十月二十六日|error=ignore}} → 一九九四年十月二十六日(将error字段设为ignore返回输入值)

ISO 8601标准只规定了1583年之后的日期标准,请勿用本模块表示这之前的日期,否则可能会得到不期待的结果:

{{#invoke:Date_Convert|ChineseDate|xxx}}等效於此{{#invoke:Chinese_date|main|xxx}}

参见

require('Module:No globals')

local getArgs = require('Module:Arguments').getArgs
local yesno = require('Module:Yesno')
local mError
local p = {}

local timeErrorMessage
local function getTimeErrorMessage()
	if not timeErrorMessage then
		timeErrorMessage = mw.getCurrentFrame():callParserFunction('#time', '', 'error')
	end
	return timeErrorMessage
end

local function makeError(message)
	if not mError then
		mError = require('Module:Error')
	end
	return mError.error({'[[Module:Date Convert]]錯誤:' .. message})
end

local langObj = mw.language.getContentLanguage()

local function formatTime(format, input)
	if input then
		local success, value = pcall(function ()
			return langObj:formatDate(format, input)
		end)
		if success then
			return value
		end
	end
	return nil
end

-- @args input (string)
-- @returns
-- - format ('Y-m-d'/'Y-m'/'Y'/'m-d'/nil)
-- - val (string/nil)
-- - suf (string/nil)
local function convert(input)
	input = input
		:gsub(" "," ")
		:gsub("%s+"," ")
		
		:gsub('(%a+)[ ,]*(%d+)', '%1 %2');
		
	local y, m, d, suf
	local datePatternList = {
		-- English date format
		{'%d%d? ?%a+[ ,]*%d+', 'Y-m-d'},	-- 26 Oct 1994
		{'%a+ ?%d%d?[ ,]+%d+', 'Y-m-d'},	-- Oct 26, 1994
		{'%a+[ ,]*%d%d%d%d+', 'Y-m'},		-- Oct 1994
		{'%a+ ?%d%d?', 'Y-m-d'},		    -- Oct 26
		{'%d%d? *%a+', 'Y-m-d'},		    -- 26 Oct
		-- Slash or hyphen date format
		{'%d+/%d%d?/%d+', 'Y-m-d'},	    	-- 1994/10/26 or 10/26/1994
		{'%d+%.%d%d?%.%d+', 'Y-m-d'},	   	-- 1994.10.26 or 26.10.1994
		{'%d%d?/%d%d?', 'Y-m-d'},		    -- 10/26
		{'%d+%-%d%d?%-%d+', 'Y-m-d'},		-- 1994-10-26 or 26-10-94
		{'%d%d%d%d+%-%d%d?', 'Y-m'},		-- 1994-10
		{'%d%d%d%d', 'Y'},		        	-- 1994
	}

	y, m, d, suf = string.match(input, '^(%d+)年(%d%d?)月(%d%d?)日(.*)$');
	if y then
		if #y < 4 then
			y = string.rep(0, 4 - #y) .. y
		end
		return 'Y-m-d', y .. '-' .. m .. '-' .. d, suf
	end

	y, m, suf = string.match(input, '^(%d+)年(%d%d?)月(.*)$');
	if y then
		if #y < 4 then
			y = string.rep(0, 4 - #y) .. y
		end
		return 'Y-m', y .. '-' .. m, suf
	end

	y, suf = string.match(input, '^(%d+)年(.*)$');
	if y then
		if #y < 4 then
			y = string.rep(0, 4 - #y) .. y
		end
		return 'Y', y, suf
	end
	
	m, d, suf = string.match(input, '^(%d%d?)月(%d%d?)日(.*)$');
	if m and tonumber(m) then
		return 'm-d', m .. '-' .. d, suf
	end

	for _, value in ipairs(datePatternList) do
		local str, suf = string.match(input, '^(' .. value[1] .. ')(.*)$');
		if str then
			return value[2], str, suf
		end
	end

	return nil, nil, nil
end

function p._converttime(input, showsuf)
	local format, date, suf = convert(input)
	local result = formatTime(format, date) or getTimeErrorMessage()
	if yesno(showsuf) then
		return result .. suf
	else
		return result
	end
end

local function addSuffix(args, suffix)
	if suffix and (yesno(args.suf) or yesno(args.suffix)) then
		return suffix
	end
	return ''
end

local function dateFunctionWrap(template, formatFunction, postFormatFunction)
	if not formatFunction then
		formatFunction = formatTime
	end

	return function (args)
		local input = args[1]
		if not input or input == '' then
			return makeError('輸入為空。')
		end

		local format, date, suffix = convert(input)

		local result = date and formatFunction(format, date) or nil

		if result then
			if postFormatFunction then
				return postFormatFunction(result) .. addSuffix(args, suffix)
			end
			return result .. addSuffix(args, suffix)
		elseif args.error == 'ignore' then
			return input
		else
			return getTimeErrorMessage() .. '[[Category:Template:' .. template .. '使用錯誤]]'
		end
	end
end

function p.ChineseDate(frame)
	local args = getArgs(frame)
	return p._ChineseDate(args)
end

p._ChineseDate = dateFunctionWrap('Chinese date', --[=[ formatFunction ]=] function(format, date)
	if format == 'Y-m-d' then
		return formatTime('Y年n月j日', date)
	elseif format == 'Y-m' then
		return formatTime('Y年n月', date)
	elseif format == 'Y' then
		return formatTime('Y年', date)
	elseif format == 'm-d' then
		return formatTime('n月j日', date)
	end
	error('Internal error: invalid format "' .. format .. '".')
end, --[=[ postFormatFunction ]=] function(value)
	value = value:gsub("^0+","")
	return value
end)
p._ISODate = dateFunctionWrap('ISODate')

local function invokeWarp(func)
	return function (frame)
		local args = getArgs(frame)
		return p[func](args)
	end
end

p.ChineseDate = invokeWarp('_ChineseDate')
p.ISODate = invokeWarp('_ISODate')

return p