DEV Community

Sérgio Araújo
Sérgio Araújo

Posted on • Edited on

Formating Dates With Vim Substitutuions

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Of course, in the above example we could have done:

:g/./exec "normal \<c-a>"
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

and run:

:@0
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

But on my neovim when I try to use this solution it says: Unknown function "strptime"

Top comments (2)

Collapse
 
filbranden profile image
Filipe Brandenburger

Great article, as usual!

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\d{4}-\d{2}-\d{2}/\=strftime("%B %d, %Y", strptime("%Y-%m-%d", submatch(0)))/g
Collapse
 
voyeg3r profile image
Sérgio Araújo

Filipe, it seems that my neovim does not have the function "strptime"