Home
Random
Recent changes
Special pages
Community portal
Preferences
About Stockhub
Disclaimers
Search
User menu
Talk
Contributions
Create account
Log in
Editing
Module:Sandbox/Harry noob/Dates
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
--Harry noob Google Code-in 2019, Lua Task 9 --[[ date format M= word month m= number month d/m/y y/m/d m/d/y d M y M d y y M M y y ]]-- --[[ TODO: Q. how to know it is invalid day or it just doesnt match the current pattern? A. save when it matches some pattern ]]-- local p = {} local log = mw.log function p.canonicalDate(frame) local fmt = frame.args.format local text = frame.args.text local date, defaultFmt = p.parseDate(text) if not date then return "Invalid entry" end local formattedDate = p.formatDate(date, fmt, defaultFmt) local result = addPreSuffix(text, formattedDate) return result end function p.parseDate(text) local d, m, y, a, b, c, mName local mayMatch log("try to match y/m/d or d/m/y or m/d/y") a, b, c = string.match(text, "(%d+)[/%- ](%d+)[/%- ](%d+)") -- y/m/d or d/m/y or m/d/y log(a, b, c) mayMatch = a and b and c local possibleArrangement = {{a, b, c}, {c, b, a}, {c, a, b}} mw.logObject(possibleArrangement, "possibleArrangement: ") for _, arrange in ipairs(possibleArrangement) do y, m, d = unpack(arrange) -- this is not python :(, need to add unpack, destructing assignment doesnt works with table if isValidNumDate(y, m, d) then log("isValidNumDate passed 1") return mapToNum({y, m, d}), "iso" end end if mayMatch then return nil end local monthShortNameToNum = {jan = 1, feb = 2, mar = 3, apr = 4, jun = 6, jul = 7, aug = 8, sept = 9, oct = 10, nov = 11, dec = 12} local monthLongNameToNum = {january = 1, february = 2, march = 3, april = 4, may = 5, june = 6, july = 7, august = 8, september = 9, october = 10, november = 11, december = 12} -- match long name first, and then short name local monthFound = false local start, stop for monthName, monthNum in pairs(monthLongNameToNum) do start, stop = text:lower():find(monthName) log("month for loop 1:", monthName, monthNum, start, stop) if start and stop then monthFound = true mName = text:sub(start, stop) -- ~= monthName, == orginal month name log("mName:", mName) m = monthNum break end end if not monthFound then for monthName, monthNum in pairs(monthShortNameToNum) do if monthName == "sept" then start, stop = text:lower():find("sept?") else start, stop = text:lower():find(monthName) end if start and stop then monthFound = true mName = text:sub(start, stop) -- ~= monthName, == orginal month name log("mName:", mName) m = monthNum break end end end if monthFound then log("try to match d M y or y M d") d, y = text:match("(%d+)%D-" .. mName .. "%D-(%d+)") -- d M y if isValidNumDate(y, m, d) then log("isValidNumDate passed 2") return mapToNum({y, m, d}), "dmy" end if d and y then return nil end log("try to match M d y") d, y = text:match(mName .. "%D-(%d+)%D-(%d+)") -- M d y if isValidNumDate(y, m, d) then log("isValidNumDate passed 4") return mapToNum({y, m, d}), "mdy" end if d and y then return nil end log("try to match M y") y = text:match(mName .. "%D-(%d+)") -- M y log("y =", y) if y then return mapToNum({y, m}), "my" end log("try to match y M") y = text:match("(%d+)%D-" .. mName) -- y M log("y =", y) if y then return mapToNum({y, m}), "ym" end end log("try to match y") y = text:match("(%d+)%D-$") -- y if y then return {tonumber(y)}, "year" end log("no match") return nil end -- y, m, d are string number function isValidNumDate(y, m, d) log("isValidNumDate receive:", y, m, d) y, m, d = tonumber(y), tonumber(m), tonumber(d) local NOfDays = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} local result = y and m and d and 1 <= m and m <= 12 and ( isLeap(y) and m == 2 and 1 <= d and -- if is leap year and February (d <= 29) or -- then test if it <= 29 (d <= NOfDays[m])) -- else follow general case (use assert and pcall instead of returning 2 result can type less code) log("isValidNumDate result:" .. tostring(result)) return result end function isLeap(y) return y%4 == 0 and (y%100 ~= 0 or y%400 == 0) end function mapToNum(arr) mw.logObject(arr, "mapToNum receive arr:") for i, v in pairs(arr) do arr[i] = tonumber(v) end mw.logObject(arr, "mapToNum result arr:") return arr end function p.formatDate(date, fmt, defaultFmt) local monthNames = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"} local y, m, d = unpack(date) if (fmt or defaultFmt) == "iso" then return ("%d-%02d-%02d"):format(y, m, d) elseif (fmt or defaultFmt) == "dmy" then return ("%d %s %d"):format(d, monthNames[m], y) elseif (fmt or defaultFmt) == "mdy" then return ("%s %d, %d"):format(monthNames[m], d, y) elseif (fmt or defaultFmt) == "my" then return ("%s %d"):format(monthNames[m], y) elseif (fmt or defaultFmt) == "ym" then return ("%d %s"):format(y, monthNames[m]) else return tostring(y) end end function addPreSuffix(text, dateStr) local aboutList = {"about", "around", "uncertain", "roughly", "approximate", "close to", "near "} local suffixList = {"BCE", "CE", "BC", "AD"} for i, word in ipairs(aboutList) do if text:lower():find(word) then dateStr = "circa " .. dateStr break end end for i, word in ipairs(suffixList) do if text:find(" " .. word) then dateStr = dateStr .. " " .. word break end end return dateStr end return p
Summary:
Please note that all contributions to Stockhub may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see
Stockhub:Copyrights
for details).
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)
Template used on this page:
Module:Sandbox/Harry noob/Dates/doc
(
edit
)