모듈 : ISOdate

이 페이지는 지속적인 문서 훼손 또는 정책 위반 등으로 인하여 영구적으로 준보호되어 있습니다.
위키百科, 우리 모두의 百科事典.

--[[  

 
This module is intended for processing of date strings.

 
Please do not modify this code without applying the changes first at Module:ISOdate/sandbox and testing 

at Module:ISOdate/sandbox/testcases and Module talk:ISOdate/sandbox/testcases.

 
Authors and maintainers:

* User:Parent5446 - original version of the function mimicking template:ISOdate

* User:Jarekt - original version of the functions mimicking template:Date and template:ISOyear

 
]]

 
 
local
 p
 =
 {}

 
-- =======================================

-- === Dependencies ======================

-- =======================================

local
 D
 =
 require
(
'Module:Date2'
)

 
--[[

ISOyear

 
This function returns year part of date string.

 
Usage:

{{#invoke:ISOdate|ISOyear|target_string}}

 
Parameters

    1: The date string 

 
Error Handling:

   If the string does not look like it contain the year than the function will not return anything.

   That is the preferred treatment for the template:Creator which is the main (only?) template calling it.

]]

function
 p
.
ISOyear
(
 frame
 )

	local
 input
 =
 frame
.
args
[
1
]

	if
 not
 input
 then

		input
 =
 frame
.
args
[
"s"
]

	end

	input
 =
 mw
.
text
.
trim
(
 input
 )

 
	-- if empty string then return it

	if
 input
 ==
 ""
 then

		return
 input

	end

 
	-- if number then return it

	if
 tonumber
(
 input
 )
 then

		return
 mw
.
ustring
.
format
(
 '%04i'
,
 input
 )

	end

 
	-- otherwise use regular expression match

	input
 =
 mw
.
ustring
.
match
(
 input
,
 '^(-?%d%d?%d?%d?)-'
 )

	if
 input
 then

		return
 mw
.
ustring
.
format
(
 '%04i'
,
 input
 )

	else

		return
 ''

	end

end

 
--[[

ISOdate

 
This function is the core part of the ISOdate template. 

 
Usage:

{{#invoke:ISOdate|ISOdate|target_string|lang=}}

 
Parameters:

     1: The date string 

  lang: The language to display it in

  form: Language format (genitive, etc.) for some languages

 class: CSS class for the <time> node

 
 Error Handling:

   If the string does not look like it contain the proper ISO date than the function will return the original string.

 
   That is the preferred treatment for the template:Information (and similar templates) which calling it.

]]

function
 p
.
ISOdate
(
frame
)

	local
 datestr
,
 succeded

	datestr
,
 succeded
 =
 p
.
_ISOdate
(

		mw
.
text
.
trim
(
frame
.
args
[
1
]),

		frame
.
args
[
"lang"
],
                  -- language

		frame
.
args
[
"trim_year"
]
 or
 '100-999'
 -- by default pad one and 2 digit years to be 4 digit long, while keeping 3 digit years as is	

	)

	return
 datestr

end

 
function
 p
.
_ISOdate
(
datestr
,
 lang
,
 trim_year
)

 
	-- pattern: regexp - regular expresion to test; dlen - number of date elements; tail = which element is a "tail" if any

	-- regexp hints:

	--  1) Strings starting with "^" and ending with "$" indicate whole string match

	--  2) optional tail part copied as-is and following the main parsed part of the date have to be separated from the date by a whitespace, so "(\s.+)?"

	local
 patterns
 =
 {

		-- strings starting with YYYY-MM-DD. Year 1-4 digits, the rest 1-2

		{
dlen
=
3
,
 tail
=
4
,
 regexp
=
"^(%d%d?%d?%d?)-(%d%d?)-(%d%d?)(%s.+)"
},

		{
dlen
=
3
,
 tail
=
0
,
 regexp
=
"^(%d%d?%d?%d?)-(%d%d?)-(%d%d?)$"
},

		-- strings starting with YYYY-MM. Year 3-4 digits, month 2 digits

		-- (want to avoit converting to dates strings like 10-5 = 5

		{
dlen
=
2
,
 tail
=
3
,
 regexp
=
"^(%d%d%d%d?)-(%d%d)(%s.+)"
},
 
		-- if whole string is in YYYY-MM form: If Year 1-4 digits, month 1-2 digits

		{
dlen
=
2
,
 tail
=
0
,
 regexp
=
"^(%d%d?%d?%d?)-(%d%d?)$"
},
 
		-- string starts with a number -> it has to be 3 or 4 digit long to be a year

		{
dlen
=
1
,
 tail
=
2
,
 regexp
=
"^(%d%d%d%d?)(%s.+)"
},
	
		 -- if whole string is a number (1-4 digit long) than it will be interpreted as a year

		{
dlen
=
1
,
 tail
=
0
,
 regexp
=
"^(%d%d?%d?%d?)$"
},

	}

 
	-- create datevec based on which variables are provided

	local
 datevec
,
 tail
,
 formatNum

	datevec
,
 tail
,
 formatNum
 =
 p
.
test_date_formats
(
datestr
,
 patterns
)

	if
 datevec
[
1
]
==
''
 or
 datevec
[
1
]
==
nil
 then

		-- quickly return if datestr does not look like date (it could be a template)

		return
 datestr
,
 false

	end

 
	-- call p._Date function to format date string

	local
 succeded
,
 datestr2

	succeded
,
 datestr2
 =
 pcall
(
 D
.
_Date
,
 datevec
,
 lang
,
 trim_year
)

	if
 succeded
 and
 datestr2
~=
''
 then

		return
 mw
.
text
.
trim
(
 datestr2
 ..
 tail
),
 true

	else
 -- in case of errors return the original string

		return
 datestr
,
 false

	end
	
end

 
function
 p
.
ISOdate_extended
(
frame
)

	-- pattern: regexp - regular expresion to test; dlen - number of date elements; tail = which element is a "tail" if any

	-- regexp hints:

	--  1) Strings starting with "^" and ending with "$" indicate whole string match

	--  2) optional tail part copied as-is and following the main parsed part of the date have to be separated from the date by a whitespace, so "(\s.+)?"

 
	local
 datestr
,
 succeded

	datestr
,
 succeded
 =
 p
.
_ISOdate
(

		mw
.
text
.
trim
(
frame
.
args
[
1
]),

		frame
.
args
[
"lang"
],
                  -- language

		frame
.
args
[
"trim_year"
]
 or
 '100-999'
 -- by default pad one and 2 digit years to be 4 digit long, while keeping 3 digit years as is	

	)

	if
 succeded
 then

		return
 datestr

	end

 
	local
 datevec
,
 tail
,
 formatNum
,
 category
 =
 ''

	datevec
,
 tail
,
 formatNum
 =
 p
.
test_date_formats
(
frame
.
args
[
1
],
 patterns
)

	if
 formatNum
==
1
 or
 formatNum
==
2
 then

		vec
 =
 datevec
;

		if
 tonumber
(
datevec
[
1
])
>
12
 then

			frame
.
args
[
1
]
 =
 string.format
(
'%04i-%02i-%02i'
,
 datevec
[
3
],
 datevec
[
2
],
 datevec
[
1
]
 )

			category
 =
 '[[Category:Date in DD/MM/YYYY format]]'

			return
 mw
.
text
.
trim
(
 p
.
ISOdate
(
frame
)
 ..
 tail
);

		elseif
 tonumber
(
datevec
[
2
])
>
12
 then

			frame
.
args
[
1
]
 =
 string.format
(
'%04i-%02i-%02i'
,
 datevec
[
3
],
 datevec
[
1
],
 datevec
[
2
]
 )

			category
 =
 '[[Category:Date in MM/DD/YYYY format]]'

			return
 mw
.
text
.
trim
(
 p
.
ISOdate
(
frame
)
 ..
 tail
);

		end

	elseif
 (
formatNum
==
3
 or
 formatNum
==
4
)
 and
 (
datevec
[
3
]
==
''
 or
 datevec
[
3
]
~=
nil
)
 then

		local
 str
 =
 mw
.
getCurrentFrame
():
callParserFunction
(
 "#time"
,
 {
 'Y-m-d'
,
 datestr
}
 )

		local
 vec
 =
 {
str
:
match
(
 "^(%d%d?%d?%d?)-(%d%d?)-(%d%d?)$"
 )}

		if
 vec
 and
 vec
[
1
]
~=
nil
 then

			frame
.
args
[
1
]
 =
 string.format
(
'%04i-%02i-%02i'
,
 vec
[
1
],
 vec
[
2
],
 vec
[
3
]
 )

			category
 =
 '[[Category:Date in word format]]'

			return
 p
.
ISOdate
(
frame
);

		end

	end
	
	return
 datestr

end

 
function
 p
.
test_date_formats
(
datestr
,
 patterns
)

	-- pattern: regexp - regular expresion to test; dlen - number of date elements; tail = which element is a "tail" if any

 
	local
 datevec
 =
 {
''
,
''
,
''
,
''
,
''
,
''
}

	local
 tail
 =
 ''

	local
 vec
,
 pat

	local
 formatNum
 =
 0

	for
 i
,
 pat
 in
 ipairs
(
 patterns
 )
 do

		vec
 =
 {
datestr
:
match
(
 pat
.
regexp
 )}

		if
 vec
 and
 vec
[
1
]
~=
nil
 then

			for
 j
=
1
,
pat
.
dlen
 do

				datevec
[
j
]
 =
 vec
[
j
]

			end

			if
 pat
.
tail
>
0
 and
 vec
[
pat
.
tail
]
~=
nil
 then

				tail
 =
 mw
.
ustring
.
gsub
(
' '
 ..
 vec
[
pat
.
tail
],
 ' +'
,
 ' '
)

			end

			formatNum
 =
 i

			break

		end

	end

	return
 datevec
,
 tail
,
 formatNum

end

 
return
 p