Vim Tips Wiki
(Uploaded by JohnBot from a locally edited file)
(40 intermediate revisions by 20 users not shown)
Line 1: Line 1:
{{Duplicate|890}}
 
{{review}}
 
 
{{TipImported
 
{{TipImported
 
|id=97
 
|id=97
 
|previous=96
 
|previous=96
 
|next=99
 
|next=99
|created=August 9, 2001
+
|created=2001
 
|complexity=basic
 
|complexity=basic
 
|author=newbie
 
|author=newbie
 
|version=6.0
 
|version=6.0
 
|rating=185/81
 
|rating=185/81
 
|category1=Automated Text Insertion
  +
|category2=
 
}}
 
}}
There are a variety of ways to automatically add a date/time stamp to your editing buffer, similar to <F5> in Windows Notepad.
+
There are a variety of ways to insert a date/time stamp. You can even have Vim automatically update an existing 'last modified' date/time when writing the file.
   
 
==Using strftime()==
 
==Using strftime()==
 
Vim's internal strftime() function ({{help|strftime()}}) returns a date/time string formatted in a way you specify with a format string. Most systems support <code>strftime()</code>, but some don't. To store the return value of the function, the <code>"=</code> register ({{help|id="=}}) is used. Here's a bunch of examples:
   
 
Press F5 in normal mode or in insert mode to insert the current datestamp: {{help|i_CTRL-R}}
Vim's internal strftime() function ({{help|strftime()}}) returns a date/time string, given a format string, but this might not work on all systems. To store return value of this Vim function for pasting, the <tt>"=</tt> register ({{help|id="=}}) is used. Here's a bunch of examples:
 
  +
<pre>
 
:nnoremap <F5> "=strftime("%c")<CR>P
 
:inoremap <F5> <C-R>=strftime("%c")<CR>
  +
</pre>
   
 
In the example above, the uppercase <code>P</code> at the end inserts ''before the current character'', which allows datestamps inserted at the beginning of an existing line. Other 'put' commands may be more useful for you: {{help|p}} {{help|P}} {{help|gp}} {{help|gP}}
This makes '''&lt;F5&gt; in insert mode''' paste a datestamp for an effect like that in Notepad. ({{help|i_CTRL-R}}):
 
   
 
Type <code>dts</code> in insert mode to expand to a datestamp: {{help|abbreviations}} using an expression {{help|:map-expression}}
:inoremap &lt;F5&gt; &lt;C-R&gt;=strftime("%c")&lt;CR&gt;
 
  +
<pre>
 
:iab <expr> dts strftime("%c")
  +
</pre>
   
 
To replace text with the current date '''in a substitute''' command:
This makes <tt>dts</tt> '''typed in insert mode''' expand to a datestamp ({{help|abbreviations}}):
 
  +
<pre>
 
:s/text to replace/\=strftime("%c")/
  +
</pre>
   
 
Vary the format string (the <code>"%c"</code> argument), to change how the time and/or date are displayed. For some formats, the result may depend on your locale. {{help|:language}}
:iab dts &lt;C-R&gt;=strftime("%c")&lt;CR&gt;
 
   
 
The specification for the format string itself depends on the implementation of <code>strftime()</code> on your platform. For details, Unix users may refer to the <code>strftime(3)</code> man page, by running '<code>man 3 strftime</code>'.
This will cause '''<F5> in normal mode''' to paste the current datestamp.
 
 
:nnoremap &lt;F5&gt; "=strftime("%c")&lt;CR&gt;P
 
 
In the example above, the capital P at the end inserts ''before the current character,'' which allows datestamps inserted at the beginning of an existing line. Other 'put' commands may be more useful for you: {{help|p}} {{help|P}} {{help|gp}} {{help|gP}}
 
 
To embed the current date '''in a substitution''':
 
 
:s/text to replace with date/\=strftime("%c")/
 
 
Vary the format string, i.e. the "%c" argument to strftime(), to get the time and/or date in a different format. Depending on the format string used, the result may depend on your locale ({{help|:language}}).
 
 
The specification for the format string itself depends on the implementation of strftime() on your platform. For details, Unix users may refer to the strftime(3) man page, by running 'man 3 strftime' at the prompt.
 
   
 
===Some strftime() format string examples===
 
===Some strftime() format string examples===
 
 
<pre>
 
<pre>
Format String Example output
+
Format String Example output
------------- --------------
+
------------- --------------
%c Thu 27 Sep 2007 07:37:42 AM EDT (depends on locale)
+
%c Thu 27 Sep 2007 07:37:42 AM EDT (depends on locale)
%a %d %b %Y Thu 27 Sep 2007
+
%a %d %b %Y Thu 27 Sep 2007
%b %d, %Y Sep 27, 2007
+
%b %d, %Y Sep 27, 2007
%d/%m/%y %H:%M:%S 27/09/07 07:36:32
+
%d/%m/%y %H:%M:%S 27/09/07 07:36:32
%H:%M:%S 07:36:44
+
%H:%M:%S 07:36:44
%T 07:38:09
+
%T 07:38:09
%m/%d/%y 09/27/07
+
%m/%d/%y 09/27/07
%y%m%d 070927
+
%y%m%d 070927
%x %X (%Z) 09/27/2007 08:00:59 AM (EDT)
+
%x %X (%Z) 09/27/2007 08:00:59 AM (EDT)
   
RFC822 format:
+
RFC822 format:
%a, %d %b %Y %H:%M:%S %z Wed, 29 Aug 2007 02:37:15 -0400
+
%a, %d %b %Y %H:%M:%S %z Wed, 29 Aug 2007 02:37:15 -0400
   
ISO8601/W3C format (http://www.w3.org/TR/NOTE-datetime):
+
ISO8601/W3C format (http://www.w3.org/TR/NOTE-datetime):
%FT%T%z 2007-08-29T02:37:13-0400
+
%FT%T%z 2007-08-29T02:37:13-0400
 
</pre>
 
</pre>
   
 
==Using external tools==
 
==Using external tools==
Unix users have access to the <tt>date</tt> utility. You may ask Vim to run 'date' and insert the output in the buffer:
+
On Unix-based systems, enter the following in Vim to read the output from running the <code>date</code> utility, inserting the result after the current line:
  +
<pre>
 
:r !date
  +
</pre>
   
 
Under Windows, use:
:r!date
 
  +
<pre>
 
:r !date /t
  +
</pre>
   
  +
The above commands insert the output of the <code>date</code> program after the current line. If wanted, the <code>!!</code> command can be used to filter the current line, replacing it with the output of <code>date</code>.
Under Windows,
 
  +
<pre>
:r!date /t
 
  +
!!date
 
  +
# Under Windows, use:
Alternatively, Windows users may install cygwin from http://sources.redhat.com/cygwin for access to Unix 'date' and a host of other utilities, but that might be overkill if you're just looking for datestamps.
 
  +
!!date /t
  +
</pre>
   
 
==Automatically update timestamps==
 
==Automatically update timestamps==
 
 
You might want to automatically update existing time stamps when writing a file.
 
You might want to automatically update existing time stamps when writing a file.
   
 
This is a solution for html implemented as an autocmd which fires when the file is written:
 
This is a solution for html implemented as an autocmd which fires when the file is written:
  +
<pre>
 
:au BufWritePre *.html exe "norm mz"|exe '%s/\(<!-- DATE -->\).\{-\}\d\d:\d\d:\d\d/\1'.strftime("%b %d, %Y %X")."/e"|norm `z
  +
</pre>
   
 
That way a string of the form <code><!-- DATE -->Aug 13, 2001 14:19:50</code> is embedded in the text, and it will be updated to the current date and time automatically, every time the file is saved (the ...DATE... stuff is an HTML comment and won't appear in an HTML document).
:au BufWritePre *.html exe "norm mz"|exe '%s/\(&lt;!-- DATE --&gt;\).\{-}\d\d:\d\d:\d\d/\1'.strftime("%b %d, %Y %X")."/e"|norm `z
 
 
That way a string of the form <tt>&lt;!-- DATE --&gt;Aug 13, 2001 14:19:50</tt> is embedded in the text, and it will be updated to the current date (using Vim's built-in strftime() function) and time automatically &ndash; every time I save the file (the ...DATE... stuff is an HTML comment which won't appear in an HTML document).
 
   
 
This is a general solution:
 
This is a general solution:
 
 
<pre>
 
<pre>
" Add a function that returns a time stamp in the desired format.
+
" If buffer modified, update any 'Last modified: ' in the first 20 lines.
  +
" 'Last modified: ' can have up to 10 characters before (they are retained).
if !exists("*TimeStamp")
 
  +
" Restores cursor and window position using save_cursor variable.
fun TimeStamp()
 
  +
function! LastModified()
return "Time-stamp: &lt;" . strftime("%d %b %Y %X") . " My Name&gt;"
 
  +
if &modified
endfun
 
  +
let save_cursor = getpos(".")
endif
 
  +
let n = min([20, line("$")])
  +
keepjumps exe '1,' . n . 's#^\(.\{,10}Last modified: \).*#\1' .
  +
\ strftime('%a %b %d, %Y %I:%M%p') . '#e'
  +
call histdel('search', -1)
  +
call setpos('.', save_cursor)
 
endif
 
endfun
 
autocmd BufWritePre * call LastModified()
  +
</pre>
   
  +
<code>keepjumps</code> excludes timestamp position from jump list, which is a false positive in this context. Calling <code>histdel</code> removes timestamp search pattern from search history.
" Search for an existing time stamp and update it.
 
if !exists("*UpdateTimeStamp")
 
fun UpdateTimeStamp()
 
if (match(getline(1),"Time-stamp: &lt;.*&gt;")) &gt; 1
 
exe "1,1 s/Time-stamp: &lt;.*&gt;/" . TimeStamp()
 
endif
 
endfun
 
endif
 
   
  +
==Updating timestamps in XML files==
" Abbreviation to manually enter a timestamp (type YTS in insert mode).
 
  +
An XML file may contain a line like the following (the value is a date/time given as the number of milliseconds past the [[wikipedia:Unix time|epoch]]):
iab YTS &lt;C-R&gt;=TimeStamp()&lt;CR&gt;
 
  +
<pre>
  +
<property name='p2.timestamp' value='1333222444000'/>
  +
</pre>
   
  +
With the code below in your [[vimrc]], enter <code>:UpdateTimestamps</code> to update the value to the current time in each instance of a tag with the format shown above. The code uses Vim's <code>strftime()</code> which requires support by the operating system, so this will only work on systems which handle <code>%s</code> (the number of seconds since the start of 1970-01-01; should be available on Unix systems but not Windows).
" Add an autocommand to update an existing time stamp when writing the file.
 
  +
<pre>
" It uses the functions above to replace the time stamp and restores cursor
 
  +
function! s:UpdateTimestamps()
" position afterwards.
 
  +
let tstamp = strftime('%s000')
autocmd BufWritePre,FileWritePre * ks|call UpdateTimeStamp()|'s
 
  +
%s#<property name='p2.timestamp' value='\zs\d\+\ze'/>#\=tstamp#g
  +
echo 'New time: ' . tstamp
  +
endfunction
  +
command! UpdateTimestamps call s:UpdateTimestamps()
 
</pre>
 
</pre>
   
  +
It is not necessary to type the full command: just type <code>:Up</code> then press Tab for command completion. Using a command allows updating to be easily applied to [[Run a command in multiple buffers|multiple buffers]], for example, entering <code>:bufdo UpdateTimestamps</code> would update all tags in all buffers.
The date is searched for in the first line of the file only (you can change that) in columns &gt; 1. I did that mainly for security reasons (in source code, there will be almost always a comment start, e.g. /* in c, preceding the time stamp).
 
   
  +
==Updating a DNS SOA serial number==
==Comments==
 
  +
When manually editing a zone file for a DNS name server, the serial number in the SOA record needs to be updated. Often a ten-digit number is used, consisting of a timestamp of the form "YYYYMMDD" and a two-digit version number. For example, "2009042101" might represent update number 01 on 21 April 2009.
You could also use the following :execute commands:
 
   
  +
The following mapping finds the next 10-digit number, and replaces it with a timestamp + "00", and shows the original number in the message line (so you can see what change occurred):
 
<pre>
 
<pre>
  +
:nnoremap <F8> /\<\d\{10}\><CR>ce<C-r>=strftime("%Y%m%d00")<CR><Esc>:echo @"<CR>
nmap &lt;leader&gt;tt :execute "normal i" . strftime("%x %X (%Z) ")&lt;Esc&gt;
 
imap &lt;leader&gt;tt &lt;Esc&gt;:execute "normal i" . strftime("%x %X (%Z) ")&lt;Esc&gt;i
 
 
</pre>
 
</pre>
   
  +
For example, if the date today is 21 April 2009 and the next ten-digit number after the cursor is "2008123002", pressing the F8 key would change the number to "2009042100", and would display "2008123002" in the message line at the bottom of the window.
By default, &lt;leader&gt; is "\". ({{help|mapleader}}.) In my case I hit "\tt" in normal or insert mode and hello time and date.
 
   
  +
The command searches for <code>\<</code> (beginning word), followed by 10 digits, followed by <code>\></code> (end word). The <code>ce</code> changes to the end of the word (deleting the number to the unnamed register), then inserts (Ctrl-r) the value of register <code>=</code> (which evaluates the following expression).
----
 
  +
[[Category:Automated Text Insertion]]
 
  +
==See also==
  +
*[[VimTip1521|Automatically Update Copyright Notice in Files]]
  +
 
==Comments==

Revision as of 09:56, 28 July 2013

Tip 97 Printable Monobook Previous Next

created 2001 · complexity basic · author newbie · version 6.0


There are a variety of ways to insert a date/time stamp. You can even have Vim automatically update an existing 'last modified' date/time when writing the file.

Using strftime()

Vim's internal strftime() function (:help strftime()) returns a date/time string formatted in a way you specify with a format string. Most systems support strftime(), but some don't. To store the return value of the function, the "= register (:help "=) is used. Here's a bunch of examples:

Press F5 in normal mode or in insert mode to insert the current datestamp: :help i_CTRL-R

:nnoremap <F5> "=strftime("%c")<CR>P
:inoremap <F5> <C-R>=strftime("%c")<CR>

In the example above, the uppercase P at the end inserts before the current character, which allows datestamps inserted at the beginning of an existing line. Other 'put' commands may be more useful for you: :help p :help P :help gp :help gP

Type dts in insert mode to expand to a datestamp: :help abbreviations using an expression :help :map-expression

:iab <expr> dts strftime("%c")

To replace text with the current date in a substitute command:

:s/text to replace/\=strftime("%c")/

Vary the format string (the "%c" argument), to change how the time and/or date are displayed. For some formats, the result may depend on your locale. :help :language

The specification for the format string itself depends on the implementation of strftime() on your platform. For details, Unix users may refer to the strftime(3) man page, by running 'man 3 strftime'.

Some strftime() format string examples

Format String              Example output
-------------              --------------
%c                         Thu 27 Sep 2007 07:37:42 AM EDT (depends on locale)
%a %d %b %Y                Thu 27 Sep 2007
%b %d, %Y                  Sep 27, 2007
%d/%m/%y %H:%M:%S          27/09/07 07:36:32
%H:%M:%S                   07:36:44
%T                         07:38:09
%m/%d/%y                   09/27/07
%y%m%d                     070927
%x %X (%Z)                 09/27/2007 08:00:59 AM (EDT)

RFC822 format:
%a, %d %b %Y %H:%M:%S %z   Wed, 29 Aug 2007 02:37:15 -0400

ISO8601/W3C format (http://www.w3.org/TR/NOTE-datetime):
%FT%T%z                    2007-08-29T02:37:13-0400

Using external tools

On Unix-based systems, enter the following in Vim to read the output from running the date utility, inserting the result after the current line:

:r !date

Under Windows, use:

:r !date /t

The above commands insert the output of the date program after the current line. If wanted, the !! command can be used to filter the current line, replacing it with the output of date.

!!date
# Under Windows, use:
!!date /t

Automatically update timestamps

You might want to automatically update existing time stamps when writing a file.

This is a solution for html implemented as an autocmd which fires when the file is written:

:au BufWritePre *.html exe "norm mz"|exe '%s/\(<!-- DATE -->\).\{-\}\d\d:\d\d:\d\d/\1'.strftime("%b %d, %Y %X")."/e"|norm `z

That way a string of the form Aug 13, 2001 14:19:50 is embedded in the text, and it will be updated to the current date and time automatically, every time the file is saved (the ...DATE... stuff is an HTML comment and won't appear in an HTML document).

This is a general solution:

" If buffer modified, update any 'Last modified: ' in the first 20 lines.
" 'Last modified: ' can have up to 10 characters before (they are retained).
" Restores cursor and window position using save_cursor variable.
function! LastModified()
  if &modified
    let save_cursor = getpos(".")
    let n = min([20, line("$")])
    keepjumps exe '1,' . n . 's#^\(.\{,10}Last modified: \).*#\1' .
          \ strftime('%a %b %d, %Y  %I:%M%p') . '#e'
    call histdel('search', -1)
    call setpos('.', save_cursor)
  endif
endfun
autocmd BufWritePre * call LastModified()

keepjumps excludes timestamp position from jump list, which is a false positive in this context. Calling histdel removes timestamp search pattern from search history.

Updating timestamps in XML files

An XML file may contain a line like the following (the value is a date/time given as the number of milliseconds past the epoch):

<property name='p2.timestamp' value='1333222444000'/>

With the code below in your vimrc, enter :UpdateTimestamps to update the value to the current time in each instance of a tag with the format shown above. The code uses Vim's strftime() which requires support by the operating system, so this will only work on systems which handle %s (the number of seconds since the start of 1970-01-01; should be available on Unix systems but not Windows).

function! s:UpdateTimestamps()
  let tstamp = strftime('%s000')
  %s#<property name='p2.timestamp' value='\zs\d\+\ze'/>#\=tstamp#g
  echo 'New time: ' . tstamp
endfunction
command! UpdateTimestamps call s:UpdateTimestamps()

It is not necessary to type the full command: just type :Up then press Tab for command completion. Using a command allows updating to be easily applied to multiple buffers, for example, entering :bufdo UpdateTimestamps would update all tags in all buffers.

Updating a DNS SOA serial number

When manually editing a zone file for a DNS name server, the serial number in the SOA record needs to be updated. Often a ten-digit number is used, consisting of a timestamp of the form "YYYYMMDD" and a two-digit version number. For example, "2009042101" might represent update number 01 on 21 April 2009.

The following mapping finds the next 10-digit number, and replaces it with a timestamp + "00", and shows the original number in the message line (so you can see what change occurred):

:nnoremap <F8> /\<\d\{10}\><CR>ce<C-r>=strftime("%Y%m%d00")<CR><Esc>:echo @"<CR>

For example, if the date today is 21 April 2009 and the next ten-digit number after the cursor is "2008123002", pressing the F8 key would change the number to "2009042100", and would display "2008123002" in the message line at the bottom of the window.

The command searches for \< (beginning word), followed by 10 digits, followed by \> (end word). The ce changes to the end of the word (deleting the number to the unnamed register), then inserts (Ctrl-r) the value of register = (which evaluates the following expression).

See also

Comments