diff --git a/doc/lua-filters.md b/doc/lua-filters.md
index 52d745ce8..4411e90a5 100644
--- a/doc/lua-filters.md
+++ b/doc/lua-filters.md
@@ -173,10 +173,11 @@ Some pandoc functions have been made available in lua:
   documents;
 - [`pipe`](#pipe) runs an external command with input from and
   output to strings;
-- [`sha1`](#utils-sha1) generates a SHA1 hash;
 - the [`pandoc.mediabag`](#module-pandoc.mediabag) module allows
   access to the "mediabag," which stores binary content such as
-  images that may be included in the final document.
+  images that may be included in the final document;
+- the [`pandoc.utils`](#module-pandoc.utils) module contains
+  various utility functions.
 
 # Lua interpreter initialization
 
@@ -1456,9 +1457,23 @@ functions.
     Usage:
 
         local inline = pandoc.Emph{pandoc.Str 'Moin'}
-         -- outputs "Moin"
+        -- outputs "Moin"
         print(pandoc.utils.stringify(inline))
 
+[`to_roman_numeral (integer)`]{#utils-to_roman_numeral}
+
+:   Converts an integer < 4000 to uppercase roman numeral.
+
+    Returns:
+
+    -   A roman numeral string.
+
+    Usage:
+
+        local to_roman_numeral = pandoc.utils.to_roman_numeral
+        local pandoc_birth_year = to_roman_numeral(2006)
+        -- pandoc_birth_year == 'MMVI'
+
 
 # Module pandoc.mediabag
 
diff --git a/src/Text/Pandoc/Lua/Module/Utils.hs b/src/Text/Pandoc/Lua/Module/Utils.hs
index 3a3727355..3c830a4bd 100644
--- a/src/Text/Pandoc/Lua/Module/Utils.hs
+++ b/src/Text/Pandoc/Lua/Module/Utils.hs
@@ -30,7 +30,7 @@ module Text.Pandoc.Lua.Module.Utils
   ) where
 
 import Control.Applicative ((<|>))
-import Foreign.Lua (FromLuaStack, Lua, NumResults)
+import Foreign.Lua (FromLuaStack, Lua, LuaInteger, NumResults)
 import Text.Pandoc.Definition (Pandoc, Meta, Block, Inline)
 import Text.Pandoc.Lua.StackInstances ()
 import Text.Pandoc.Lua.Util (addFunction)
@@ -44,6 +44,7 @@ import qualified Text.Pandoc.Shared as Shared
 pushModule :: Lua NumResults
 pushModule = do
   Lua.newtable
+  addFunction "to_roman_numeral" toRomanNumeral
   addFunction "sha1" sha1
   addFunction "stringify" stringify
   return 1
@@ -53,6 +54,9 @@ sha1 :: BSL.ByteString
      -> Lua String
 sha1 = return . SHA.showDigest . SHA.sha1
 
+-- | Convert pandoc structure to a string with formatting removed.
+-- Footnotes are skipped (since we don't want their contents in link
+-- labels).
 stringify :: AstElement -> Lua String
 stringify el = return $ case el of
   PandocElement pd -> Shared.stringify pd
@@ -77,3 +81,7 @@ instance FromLuaStack AstElement where
       Right x -> return x
       Left _ -> Lua.throwLuaError
         "Expected an AST element, but could not parse value as such."
+
+-- | Convert a number < 4000 to uppercase roman numeral.
+toRomanNumeral :: LuaInteger -> Lua String
+toRomanNumeral = return . Shared.toRomanNumeral . fromIntegral
diff --git a/test/Tests/Lua.hs b/test/Tests/Lua.hs
index 57e7c5f0c..956575911 100644
--- a/test/Tests/Lua.hs
+++ b/test/Tests/Lua.hs
@@ -102,6 +102,7 @@ tests = map (localOption (QuickCheckTests 20))
                      , plain (str "read: OK")
                      , plain (str "failing read: OK")
                      , plain (str "stringify: OK")
+                     , plain (str "to_roman_numeral: OK")
                      ])
   ]
 
diff --git a/test/lua/test-pandoc-utils.lua b/test/lua/test-pandoc-utils.lua
index ce3456d5d..0a7aedbfd 100644
--- a/test/lua/test-pandoc-utils.lua
+++ b/test/lua/test-pandoc-utils.lua
@@ -64,6 +64,14 @@ function test_stringify ()
   return utils.stringify(inline) == 'Cogito ergo sum.'
 end
 
+-- to_roman_numeral
+------------------------------------------------------------------------
+function test_to_roman_numeral ()
+  return utils.to_roman_numeral(1888) == 'MDCCCLXXXVIII'
+    -- calling with a string fails
+    and not pcall(utils.to_roman_numeral, 'not a number')
+end
+
 -- Return result
 ------------------------------------------------------------------------
 function run(fn)
@@ -78,5 +86,6 @@ function Para (el)
     pandoc.Plain{pandoc.Str("read: " .. run(test_read))},
     pandoc.Plain{pandoc.Str("failing read: " .. run(test_failing_read))},
     pandoc.Plain{pandoc.Str("stringify: " .. run(test_stringify))},
+    pandoc.Plain{pandoc.Str("to_roman_numeral: " .. run(test_to_roman_numeral))},
   }
 end