Documentation for this module may be created at Module:TimeAgo/doc

  1. -- Replacement for [[Template:Time ago]]
  2. local numberSpell = require('Module:NumberSpell')._main
  3. local yesno = require('Module:Yesno')
  4.  
  5. local p = {}
  6.  
  7. -- Table to convert entered text values to numeric values.
  8. timeText = {
  9. ['seconds'] = 1,
  10. ['minutes'] = 60,
  11. ['hours'] = 3600,
  12. ['days'] = 86400,
  13. ['weeks'] = 604800,
  14. ['months'] = 2678400,
  15. ['years'] = 31557600
  16. }
  17.  
  18. -- Table containing tables of possible units to use in output.
  19. timeUnits = {
  20. [1] = { 'second', 'seconds', "second's", "seconds'" },
  21. [60] = { 'minute', 'minutes', "minutes'", "minutes'" },
  22. [3600] = { 'hour', 'hours', "hour's", "hours'" },
  23. [86400] = { 'day', 'days', "day's", "days'" },
  24. [604800] = { 'week', 'weeks', "week's", "weeks'" },
  25. [2678400] = { 'month', 'months', "month's", "months'" },
  26. [31557600] = { 'year', 'years', "year's", "years'" }
  27. }
  28.  
  29. function p._main( args )
  30. -- Initialize variables
  31. local lang = mw.language.getContentLanguage()
  32. local auto_magnitude_num
  33. local min_magnitude_num
  34. local result
  35. local result_unit
  36. local magnitude = args.magnitude
  37. local min_magnitude = args.min_magnitude
  38. local purge = args.purge
  39. local spell_out = args.spellout
  40. local spell_out_max = args.spelloutmax
  41. -- Add a purge link if something (usually "yes") is entered into the purge parameter
  42. if purge then
  43. purge = ' <span class="plainlinks">([' .. mw.title.getCurrentTitle():fullUrl('action=purge') .. ' purge])</span>'
  44. else
  45. purge = ''
  46. end
  47.  
  48. -- Check that the entered timestamp is valid. If it isn't, then give an error message.
  49. local noError, inputTime = pcall( lang.formatDate, lang, 'U', args[1], true )
  50. if not noError then
  51. return '<strong class="error">Error: first parameter cannot be parsed as a date or time.</strong>'
  52. end
  53.  
  54. -- Store the difference between the current time and the inputted time, as well as its absolute value.
  55. local timeDiff = lang:formatDate( 'U', nil, true ) - inputTime
  56. local absTimeDiff = math.abs( timeDiff )
  57.  
  58. if magnitude then
  59. auto_magnitude_num = 0
  60. min_magnitude_num = timeText[magnitude]
  61. else
  62. -- Calculate the appropriate unit of time if it was not specified as an argument.
  63. local autoMagnitudeData = {
  64. { denom = 63115200, amn = 31557600 },
  65. { denom = 5356800, amn = 2678400 },
  66. { denom = 172800, amn = 86400 },
  67. { denom = 7200, amn = 3600 },
  68. { denom = 120, amn = 60 }
  69. }
  70. for i, t in ipairs( autoMagnitudeData ) do
  71. if absTimeDiff / t.denom >= 1 then
  72. auto_magnitude_num = t.amn
  73. break
  74. end
  75. end
  76. auto_magnitude_num = auto_magnitude_num or 1
  77. if min_magnitude then
  78. min_magnitude_num = timeText[min_magnitude]
  79. else
  80. min_magnitude_num = -1
  81. end
  82. end
  83.  
  84. if not min_magnitude_num then
  85. -- Default to seconds if an invalid magnitude is entered.
  86. min_magnitude_num = 1
  87. end
  88.  
  89. local magnitude_num = math.max( min_magnitude_num, auto_magnitude_num )
  90. local result_num = math.floor ( absTimeDiff / magnitude_num )
  91.  
  92. local punctuation_key, suffix
  93. if timeDiff >= 0 then -- Past
  94. if result_num == 1 then
  95. punctuation_key = 1
  96. else
  97. punctuation_key = 2
  98. end
  99. if args.ago == '' then
  100. suffix = ''
  101. else
  102. suffix = ' ' .. (args.ago or 'ago')
  103. end
  104. else -- Future
  105. if args.ago == '' then
  106. suffix = ''
  107. if result_num == 1 then
  108. punctuation_key = 1
  109. else
  110. punctuation_key = 2
  111. end
  112. else
  113. suffix = ' time'
  114. if result_num == 1 then
  115. punctuation_key = 3
  116. else
  117. punctuation_key = 4
  118. end
  119. end
  120. end
  121. result_unit = timeUnits[ magnitude_num ][ punctuation_key ]
  122.  
  123. -- Convert numerals to words if appropriate.
  124. spell_out_max = tonumber( spell_out_max ) -- Would cause script errors if not a number.
  125. local result_num_text
  126. if ( spell_out == 'auto' and 1 <= result_num and result_num <= 9 and result_num <= ( spell_out_max or 9 ) )
  127. or ( yesno( spell_out ) and 1 <= result_num and result_num <= 100 and result_num <= ( spell_out_max or 100 ) )
  128. then
  129. result_num_text = numberSpell( result_num )
  130. else
  131. result_num_text = tostring( result_num )
  132. end
  133.  
  134. result = result_num_text .. ' ' .. result_unit .. suffix -- Spaces for suffix have been added in earlier.
  135. return result .. purge
  136. end
  137.  
  138. function p.main( frame )
  139. local args = require( 'Module:Arguments' ).getArgs( frame, {
  140. valueFunc = function( k, v )
  141. if v then
  142. v = v:match( '^%s*(.-)%s*$' ) -- Trim whitespace.
  143. if k == 'ago' or v ~= '' then
  144. return v
  145. end
  146. end
  147. return nil
  148. end,
  149. wrappers = 'Template:Time ago'
  150. })
  151. return p._main( args )
  152. end
  153.  
  154. return p