The problem
I have stumbled upon an article on how to format dates using vim sub-expression and sub-match tricks in order to format dates, but what happens is that the original article shows examples that work on MacOS and does not have comments section. So I decided to adapt what I have learned reading the article and some personal research.
Let's say you have a HTML file with a large number of lines like this:
<time datetime="2017-10-17">2017-10-17</time>
Our mission is to change the view of the result to the public, keeping our internal html as it is, so the change will be:
<time datetime="2017-10-17">october 17, 2017</time>
The regex to match our date
/>\zs\v\d{4}-\d{2}-\d{2}
> .................. literal >
\zs ................. start of our match
\v .................. very magic search (avoid backslashes)
\d .................. digits [0-9]
\{4} ................ four times
Using an expression in our substitution
If you have a series of numbers in your file and want to increase them on the substitution you can go:
0 first line
1 second line
2 third line
:%s/\v\d+/\=submatch(0)+1
\v .......... very magic
\d+ ......... a digit or more
\=submatch(0) the whole search match
Of course, in the above example we could have done:
:g/./exec "normal \<c-a>"
Whic means:
. ................ every lines that has at least one char '.'
exec .............. execute
normal ............ a normal command
\<c-a> ............ as we used double quotes: the Ctrl-a to increase
But the problem is that in some situations things are a little more complex
You can even use functions as expressions in substitutions. Copy the function bellow to the clipboard:
function! Hello()
return "Hello World"
endfunction
and run:
:@0
The above command loads de function with no need to save on your vimrc.
Now let's substitute "amazing" with the return of our function:
This is amazing
This is amazing
This is amazing
This is amazing
This is amazing
This is amazing
:%s/amazing/\=Hello()
So for the dates we can do:
%s/>\v\zs\d{4}-\d{2}-\d{2}/\=system('date -d "'.submatch(0).'" +"%B %d, %Y"')/g
\=system() ................ calls any system command
date -d ................... use a parameter as date input
. ...................... used for concatenation
+"%B %d, %Y" .............. date format we want
Update
I have just read a comment from Filipe Brandenburger giving us a useful update, he says:
For the replacement, also possible to use Vim functions strftime()
and strptime()
, so you don't need to shell out to an external date binary..
:%s/>\v\zs\d{4}-\d{2}-\d{2}/\=strftime("%B %d, %Y", strptime("%Y-%m-%d", submatch(0)))/g
But on my neovim when I try to use this solution it says: Unknown function "strptime"
Top comments (2)
Great article, as usual!
For the replacement, also possible to use Vim functions
strftime()
andstrptime()
, so you don't need to shell out to an externaldate
binary..Filipe, it seems that my neovim does not have the function "strptime"