Automatic timestamp update for Vim
I edit Markdown documents quite often. I use special email-style headers for things like article title, date created, and last modified date. A document could look like this:
Title: Automatic timestamp update for Vim
Date: 2008-10-16T17:55:58+03:00
Modified: 2008-10-17T13:26:48+03:00
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nunc
pellentesque. Phasellus adipiscing ligula eu dui. Donec placerat. Sed
aliquet rutrum mauris. Vestibulum ante orci, venenatis ac, imperdiet in,
sagittis nec, mi.
Note that I use ISO 8601 (or more specifically RFC 3339) formatting for my timestamps so that I can easily parse them with almost any software. I use the dates for sorting the documents, so every document must contain at least the date.
It would be silly to type the date manually in every file, so a quick remap for the F5 key in Vim would do the trick nicely. However, it turns out strftime() can’t return the timezone with the colon separating hours from minutes. The closest I can get is %z, which gives me +0300 (as opposed to +03:00, which is what I want). It’s fixed easily enough with a little function:
" Get RFC 3339 compatible timezone (+03:00 instead of +0300)
function GetTimezone()
let tz = strftime("%z")
if strlen(tz) == 5
let tz = strpart(tz,0,3) . ":" . strpart(tz,3,2)
endif
return tz
endfun
Now I can remap F5 to print the timestamp:
" Insert timestamp at current position
inoremap <F5> <C-R>=strftime("%FT%T").GetTimezone()<CR>
Now all I need to do is type the title, then “Date:”, then press F5, and I get the current date.
I also wanted a date that shows when the file was last modified. I could do this by checking when date that the filesystem gives me for a given file, but that would make it more complicated. I want all the variables I need to be in the file header.
I decided to use use a similar header variable called Modified. Then I used the following function (originally from Vim tips):
" Update or insert timestamp.
function! UpdateModified()
if &modified
let timestamp = strftime("%FT%T") . GetTimezone()
let n = min([10, line("$")])
exe "1," . n . "s#^\(.\{,10}Modified:\).*#\1 " . timestamp . "#e"
endif
endfun
The function checks if a line contains the string “Modified:”. If it does, it appends the current date at that position (or replaces the previous date, if it exists). Since all the variables are in the header, it only checks for the first 10 lines instead of the whole document.
To make this function automatic, I made Vim run it when a “.text” (the extension I use for Markdown-formatted text files) file is saved.
" Call UpdateModified everytime you save a file.
autocmd BufWritePre *.text call UpdateModified()
Now all I need to do, is type “Modified:” somewhere at the beginning of the document, then command :w, and the last modified date automatically updates.
