Formating Dates With Vim Substitutuions
Tags: vim, neovim, regex
Published: 2020-03-23 13:01:11

---
title: Formating Dates With Vim Substitutuions
published: true
description: Useful tricks when formating dates with vim
tags: vim, neovim, regex
---

## The problem

I have stumbled upon [an article](https://jeffkreeftmeijer.com/vim-reformat-dates/) 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](https://dev.to/filbranden) 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"