Vim で現在の日時を挿入する方法


Vim で現在の日時を挿入したいと思ったことはないでしょうか? Vim の式を使って現在の Asia/Tokyo と UTC の日時を挿入する方法を紹介します.

Vim の式を試しに使ってみる

まず Vim の式とはなんなのかということですが, なんらかの値を返す関数や変数を指します.

Vim で式を評価して実行する方法はいくつかあるのですが, 今回はインサートモードで <C-R>= と入力して, 左下のコマンドラインに = が表示し, 式を入力して評価, 実行するという方法で行いたいと思います.

試しにその方法で式を実行してみようという事で, まず ia でインサートモードに入り, <C-R>= と入力して, 左下のコマンドラインに = を表示させます.

そして続けて sqrt(4) と入力し, 4 のルートを計算してみます.

ここまで入力すると次のようになります:

=sqrt(4)

そして Enter を押して, その入力した式を実行します.

すると次のような結果がインサートモードのカーソル位置に挿入されます:

2.0

こんな感じで式を使って, 今回の内容である現在の日時を挿入してみたいと思います.

Vim の式で現在の日時を取得する

Vim で式を使って現在の日時を取得しようと思いますが, 式で strftime() という関数を使いたいと思います.

例えば, 2018-08-02 21:09:35 のような日時を取得する場合, strftime("%Y-%m-%d %H:%M:%S") もしくは strftime("%F %T") というフォーマットになります.

他にもどんなフォーマットが使えるのかというのは, ターミナルのプロンプトで man strftime と入力すると使用できるフォーマットに関する情報を得られます.

日時を取得する式さえわかったらあとは簡単です.

同じようにインサートモードに入り, <C-R>= と入力し, strftime("%Y-%m-%d %H:%M:%S") と入力し, Enter を押せば, 現在の日時がカーソル位置に挿入されます.

ただ毎回このように入力するのは, すごく面倒ですよね.

なので :nnoremap でノーマルモードの非再帰的なマッピングを設定してみたいと思います.

一例として次のような <F3> のマッピングを設定すると, ノーマルモードで <F3> を押した時, 先ほどのように現在の日時が挿入されます:

:nnoremap <F3> a<C-R>=strftime("%Y-%m-%d %H:%M:%S")<CR><Esc>

どうして :nmap ではなく :nnoremap なのかというのは, こちらの記事 “Vim の :nmap と :nnoremap の違い” に書かせていただきましたので, よろしければ見ていただければと思います.

もしくは :iabbrev コマンドで, インサートモード時の略語として, インサートモード時に一例として dt と入力すると, 同じ書式の日時を挿入する事ができます:

:iabbrev dt <C-R>=strftime("%Y-%m-%d %H:%M:%S")<CR>

UTC のタイムゾーンの日時を取得する

ちなみに strftime() で挿入される日時のタイムゾーンは, 現在使っているパソコンに設定されているローカルのタイムゾーンになりますので, 環境変数 TZ を設定されていない限り, 日本の方は Asia/Tokyo というタイムゾーンになるかと思います.

なのでもし Asia/Tokyo ではなく UTC のタイムゾーンを使いたいという場合は, .bashrc.zshrc に次のように TZ を設定していただければと思います:

export TZ="UTC"

ただこの方法ですと, Vim の strftime()UTC のタイムゾーンを取得できても, Asia/Tokyo のタイムゾーンが今度は取得できなくなってしまいます.

なので Asia/Tokyo に加えて UTC のタイムゾーンも取得したいという場合は, 環境変数 TZ を設定しないか, Asia/Tokyo と設定し, ローカルのタイムゾーンを Asia/Tokyo にします.

そして今度は system() という Vim の関数を使って UTC のタイムゾーンを取得してみたいと思います.

system() は外部コマンドを実行するための関数で, つまりはシェルコマンドを実行する事ができます.

で使用するシェルコマンドは date を使いたいと思います.

date コマンドに -u というオプションを渡すと UTC のタイムゾーンの日時を取得できるためです.

なので system()date -u を使って UTC タイムゾーンの日時を取得する式を作る場合, 次のようなものになります:

=system("date -u '+%Y-%m-%d %H:%M:%S'")

ただ date コマンドは末尾に改行文字を付け加えるので, その改行文字を削除したいという場合は tr コマンドを次のように使うとできます:

=system("date -u '+%Y-%m-%d %H:%M:%S' \| tr -d '\n'")

先ほどと同じように, これを毎回入力するのは面倒なので, マッピングとして登録する場合, 一例として次のようなものになります:

:nnoremap <F4> a<C-R>=system("date -u '+%Y-%m-%d %H:%M:%S' \| tr -d '\n'")<CR><Esc>

同じく先ほどと同様, :iabbrev を使うと, インサートモード時に一例として dtu と入力すると, UTC の日時を挿入できます:

:iabbrev dtu <C-R>=system("date -u '+%Y-%m-%d %H:%M:%S' \| tr -d '\n'")<CR>

まとめ

今までの設定で <F3> を押したら Asia/Tokyo の日時を, <F4> を押したら UTC の日時を挿入できるようになります:

:nnoremap <F3> a<C-R>=strftime("%Y-%m-%d %H:%M:%S")<CR><Esc>
:nnoremap <F4> a<C-R>=system("date -u '+%Y-%m-%d %H:%M:%S' \| tr -d '\n'")<CR><Esc>

もしくは :iabbrev でインサートモード時の略語をそれぞれ設定して, それぞれの日時を挿入することもできます:

:iabbrev dt <C-R>=strftime("%Y-%m-%d %H:%M:%S")<CR>
:iabbrev dtu <C-R>=system("date -u '+%Y-%m-%d %H:%M:%S' \| tr -d '\n'")<CR>

ただこのようなマッピングはあくまで一例ですので, :nnoremap の代わりに :innoremap を使ったり, <F3><F4> の代わりに <Leader> など他のキーシーケンスを使ったり, dtdtu の代わりに ddatetimeddatetimeutc などを設定したり, 日時のフォーマットも %Y-%m-%d %H:%M:%S の他に %z, %Z, %+ などを使っていただいて, ご自身の好みに設定していただければと思います.

それが Vim の魅力でもあると思いますので.

ちなみに僕は現在次のようなマッピングを Vim の設定ファイルに設定しています:

nn <f3> a<c-r>=strftime("%F %T %Z")<cr><esc>
nn <f4> a<c-r>=system("date -u '+%F %T %Z' \| tr -d '\n'")<cr><esc>

(nnnnoremap の省略形です)

それぞれ挿入される日時は次のような書式になります:

2018-08-03 05:55:45 JST
2018-08-02 20:55:46 UTC

Vim で現在の日時を挿入したいという時は, ぜひ今回の内容を参考にされていただければと思います.