(browse-url-netscape): Encode `)' too.
[bpt/emacs.git] / lisp / time-stamp.el
CommitLineData
9565745a 1;;; time-stamp.el --- Maintain last change time stamps in files edited by Emacs
9565745a 2
fd72ddf6 3;; Copyright 1989, 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
b578f267 4
b4b33e01 5;; Maintainer's Time-stamp: <1998-03-04 14:14:19 gildea>
622b7ede 6;; Maintainer: Stephen Gildea <gildea@alum.mit.edu>
9565745a
RS
7;; Keywords: tools
8
9;; This file is free software; you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation; either version 2, or (at your option)
12;; any later version.
13
14;; This file is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
b578f267
EN
20;; along with GNU Emacs; see the file COPYING. If not, write to the
21;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22;; Boston, MA 02111-1307, USA.
9565745a
RS
23
24;;; Commentary:
25
03d7856a
KH
26;; A template in a file can be updated with a new time stamp when
27;; you save the file. For example:
28;; static char *ts = "sdmain.c Time-stamp: <1996-08-13 10:20:51 gildea>";
29;; See the top of `time-stamp.el' for another example.
30
31;; To use time-stamping, add this line to your .emacs file:
32;; (add-hook 'write-file-hooks 'time-stamp)
33;; Now any time-stamp templates in your files will be updated automatically.
34
35;; See the documentation for the functions `time-stamp'
36;; and `time-stamp-toggle-active' for details.
b578f267 37
9565745a
RS
38;;; Code:
39
cb35a83c
RS
40(defgroup time-stamp nil
41 "Maintain last change time stamps in files edited by Emacs."
42 :group 'data
43 :group 'extensions)
44
fd72ddf6 45(defcustom time-stamp-format "%:y-%02m-%02d %02H:%02M:%02S %u"
03d7856a 46 "*Format of the string inserted by \\[time-stamp].
c9c0e4bb
RS
47The value may be a string or a list. Lists are supported only for
48backward compatibility; see variable `time-stamp-old-format-warn'.
f8d35bf3 49
fd72ddf6
RS
50A string is used verbatim except for character sequences beginning with %:
51
52%:a weekday name: `Monday'. %#A gives uppercase: `MONDAY'
53%3a abbreviated weekday: `Mon'. %3A gives uppercase: `MON'
54%:b month name: `January'. %#B gives uppercase: `JANUARY'
55%3b abbreviated month: `Jan'. %3B gives uppercase: `JAN'
56%02d day of month
57%02H 24-hour clock hour
58%02I 12-hour clock hour
59%02m month number
60%02M minute
61%#p `am' or `pm'. %P gives uppercase: `AM' or `PM'
62%02S seconds
63%w day number of week, Sunday is 0
64%02y 2-digit year: `97' %:y 4-digit year: `1997'
65%z time zone name: `est'. %Z gives uppercase: `EST'
66
67Non-date items:
68%% a literal percent character: `%'
69%f file name without directory %F gives absolute pathname
70%s system name
71%u user's login name
72%h mail host name
73
74Decimal digits between the % and the type character specify the
75field width. Strings are truncated on the right; years on the left.
76A leading zero causes numbers to be zero-filled.
622b7ede
RS
77
78For example, to get the format used by the `date' command,
fd72ddf6
RS
79use \"%3a %3b %2d %02H:%02M:%02S %Z %:y\".
80
81In the future these formats will be aligned more with format-time-string.
82Because of this transition, the default padding for numeric formats will
83change in a future version. Therefore either a padding width should be
84specified, or the : modifier should be used to explicitly request the
85historical default."
cb35a83c
RS
86 :type 'string
87 :group 'time-stamp)
03d7856a 88
95772e85
RS
89(defcustom time-stamp-active t
90 "*Non-nil to enable time-stamping of buffers by \\[time-stamp].
91Can be toggled by \\[time-stamp-toggle-active].
92See also the variable `time-stamp-warn-inactive'."
93 :type 'boolean
94 :group 'time-stamp)
95
96(defcustom time-stamp-warn-inactive t
97 "Non-nil to have \\[time-stamp] warn if a buffer did not get time-stamped.
98A warning is printed if `time-stamp-active' is nil and the buffer contains
99a time stamp template that would otherwise have been updated."
100 :type 'boolean
101 :group 'time-stamp)
102
103(defcustom time-stamp-old-format-warn 'ask
104 "Action to take if `time-stamp-format' is an old-style list.
105If `error', the format is not used. If `ask', the user is queried about
106using the time-stamp-format. If `warn', a warning is displayed.
107If nil, no notification is given."
108 :type '(choice (const :tag "No notification" nil)
109 (const :tag "Don't use the format" error)
110 (const ask) (const warn))
111 :group 'time-stamp)
112
113(defcustom time-stamp-time-zone nil
114 "If non-nil, a string naming the timezone to be used by \\[time-stamp].
115Format is the same as that used by the environment variable TZ on your system."
7967f8ab 116 :type '(choice (const nil) string)
95772e85 117 :group 'time-stamp)
622b7ede
RS
118
119
b4b33e01
RS
120;;; Do not change time-stamp-line-limit, time-stamp-start,
121;;; time-stamp-end, or time-stamp-pattern in your .emacs
122;;; or you will be incompatible with other people's files!
123;;; If you must change them, do so only in the local variables
124;;; section of the file itself.
9565745a 125
03d7856a 126
e1f40b28 127(defvar time-stamp-line-limit 8 ;Do not change!
c7c4ddd4 128 "Lines of a file searched; positive counts from start, negative from end.
e1f40b28 129The patterns `time-stamp-start' and `time-stamp-end' must be found on one
c7c4ddd4
KH
130of the first (last) `time-stamp-line-limit' lines of the file for the
131file to be time-stamped by \\[time-stamp].
e1f40b28
RS
132
133Do not change `time-stamp-line-limit', `time-stamp-start', or
134`time-stamp-end' for yourself or you will be incompatible
135with other people's files! If you must change them for some application,
136do so in the local variables section of the time-stamped file itself.")
137
9565745a 138
36081614 139(defvar time-stamp-start "Time-stamp:[ \t]+\\\\?[\"<]+" ;Do not change!
9565745a 140 "Regexp after which the time stamp is written by \\[time-stamp].
e1f40b28 141See also the variables `time-stamp-end' and `time-stamp-line-limit'.
9565745a 142
e1f40b28
RS
143Do not change `time-stamp-line-limit', `time-stamp-start', or
144`time-stamp-end' for yourself or you will be incompatible
9565745a
RS
145with other people's files! If you must change them for some application,
146do so in the local variables section of the time-stamped file itself.")
147
148
e1f40b28 149(defvar time-stamp-end "\\\\?[\">]" ;Do not change!
9565745a 150 "Regexp marking the text after the time stamp.
e1f40b28
RS
151\\[time-stamp] deletes the text between the first match of `time-stamp-start'
152and the following match of `time-stamp-end' on the same line,
153then writes the time stamp specified by `time-stamp-format' between them.
154
155Do not change `time-stamp-line-limit', `time-stamp-start', or
156`time-stamp-end' for yourself or you will be incompatible
157with other people's files! If you must change them for some application,
158do so in the local variables section of the time-stamped file itself.")
159
9565745a 160
b4b33e01
RS
161(defvar time-stamp-pattern "%%" ;Do not change!
162 "Convenience variable setting all time-stamp location and format variables.
163This string has four parts, each of which is optional.
164These four parts set time-stamp-line-limit, time-stamp-start,
165time-stamp-format, and time-stamp-end. See the documentation
166for each of these variables for details.
167
168The first part is a number followed by a slash; the number sets the number
169of lines at the beginning (negative counts from end) of the file searched
170for the time-stamp. The number and the slash may be omitted to use the
171normal value.
172
173The second part is a regexp identifying the pattern preceding the time stamp.
174This part may be omitted to use the normal pattern.
175
176The third part specifies the format of the time-stamp inserted. See
177the documentation for time-stamp-format for details. Specify this
178part as \"%%\" to use the normal format.
179
180The fourth part is a regexp identifying the pattern following the time stamp.
181This part may be omitted to use the normal pattern.
182
183As an example, the default behavior can be specified something like this:
184\"8/Time-stamp: [\\\"<]%:y-%02m-%02d %02H:%02M:%02S %u[\\\">]\"
185
186Do not change `time-stamp-pattern' for yourself or you will be incompatible
187with other people's files! Set it only in the local variables section
188of the time-stamped file itself.")
189
190
03d7856a 191
59b644e8 192;;;###autoload
9565745a
RS
193(defun time-stamp ()
194 "Update the time stamp string in the buffer.
03d7856a
KH
195A template in a file can be automatically updated with a new time stamp
196every time you save the file. Add this line to your .emacs file:
197 (add-hook 'write-file-hooks 'time-stamp)
198Normally the template must appear in the first 8 lines of a file and
199look like one of the following:
200 Time-stamp: <>
201 Time-stamp: \" \"
202The time stamp is written between the brackets or quotes:
b4b33e01 203 Time-stamp: <1998-02-18 10:20:51 gildea>
622b7ede 204The time stamp is updated only if the variable `time-stamp-active' is non-nil.
03d7856a
KH
205The format of the time stamp is set by the variable `time-stamp-format'.
206The variables `time-stamp-line-limit', `time-stamp-start',
207and `time-stamp-end' control finding the template."
9565745a 208 (interactive)
fe8287c6 209 (let ((case-fold-search nil)
03d7856a
KH
210 (start nil)
211 (end nil)
622b7ede 212 search-limit
b4b33e01
RS
213 (line-limit time-stamp-line-limit)
214 (ts-start time-stamp-start)
215 (ts-format time-stamp-format)
216 (ts-end time-stamp-end))
217 (if (stringp time-stamp-pattern)
218 (progn
219 (string-match "^\\(\\(-?[0-9]+\\)/\\)?\\([^%]+\\)?\\(.*%[-.,:@+_ #^()0-9]*[A-Za-z%]\\)?\\([^%]+\\)?$" time-stamp-pattern)
220 (and (match-beginning 2)
221 (setq line-limit
222 (string-to-int (match-string 2 time-stamp-pattern))))
223 (and (match-beginning 3)
224 (setq ts-start (match-string 3 time-stamp-pattern)))
225 (and (match-beginning 4)
226 (not (string-equal (match-string 4 time-stamp-pattern) "%%"))
227 (setq ts-format (match-string 4 time-stamp-pattern)))
228 (and (match-beginning 5)
229 (setq ts-end (match-string 5 time-stamp-pattern)))))
622b7ede
RS
230 (cond ((not (integerp line-limit))
231 (setq line-limit 8)
b4b33e01 232 (message "time-stamp-line-limit is not an integer")
622b7ede
RS
233 (sit-for 1)))
234 (save-excursion
235 (save-restriction
236 (widen)
237 (cond ((> line-limit 0)
238 (goto-char (setq start (point-min)))
239 (forward-line line-limit)
240 (setq search-limit (point)))
241 (t
242 (goto-char (setq search-limit (point-max)))
243 (forward-line line-limit)
244 (setq start (point))))
245 (goto-char start)
246 (while (and (< (point) search-limit)
247 (not end)
b4b33e01 248 (re-search-forward ts-start search-limit 'move))
622b7ede
RS
249 (setq start (point))
250 (end-of-line)
251 (let ((line-end (point)))
c7c4ddd4 252 (goto-char start)
b4b33e01 253 (if (re-search-forward ts-end line-end 'move)
622b7ede 254 (setq end (match-beginning 0)))))))
b4b33e01
RS
255 (if end
256 (progn
257 ;; do all warnings outside save-excursion
258 (cond
259 ((not time-stamp-active)
260 (if time-stamp-warn-inactive
261 ;; don't signal an error in a write-file-hook
262 (progn
263 (message "Warning: time-stamp-active is off; did not time-stamp buffer.")
264 (sit-for 1))))
265 ((not (and (stringp ts-start)
266 (stringp ts-end)))
267 (message "time-stamp-start or time-stamp-end is not a string")
268 (sit-for 1))
269 (t
270 (let ((new-time-stamp (time-stamp-string ts-format)))
271 (if (stringp new-time-stamp)
272 (save-excursion
273 (save-restriction
274 (widen)
275 (delete-region start end)
276 (goto-char start)
277 (insert-and-inherit new-time-stamp)
278 (setq end (point))
279 ;; remove any tabs used to format time stamp
280 (goto-char start)
281 (if (search-forward "\t" end t)
282 (untabify start end)))))))))))
9565745a
RS
283 ;; be sure to return nil so can be used on write-file-hooks
284 nil)
285
b1defad2
RS
286;;;###autoload
287(defun time-stamp-toggle-active (&optional arg)
03d7856a 288 "Toggle `time-stamp-active', setting whether \\[time-stamp] updates a buffer.
b1defad2
RS
289With arg, turn time stamping on if and only if arg is positive."
290 (interactive "P")
291 (setq time-stamp-active
292 (if (null arg)
293 (not time-stamp-active)
294 (> (prefix-numeric-value arg) 0)))
295 (message "time-stamp is now %s." (if time-stamp-active "active" "off")))
03d7856a 296
6946129c
RS
297(defconst time-stamp-no-file "(no file)"
298 "String to use when the buffer is not associated with a file.")
299
fd72ddf6
RS
300;;; time-stamp is transitioning to using the new, expanded capabilities
301;;; of format-time-string. During the process, this function implements
302;;; intermediate, compatible formats and complains about old, soon to
303;;; be unsupported, formats. This function will get a lot (a LOT) shorter
304;;; when the transition is complete and we can just pass most things
305;;; straight through to format-time-string.
306;;; At all times, all the formats recommended in the doc string
307;;; of time-stamp-format will work not only in the current version of
308;;; Emacs, but in all versions that have been released within the past
309;;; two years.
310;;; The : modifier is a temporary conversion feature used to resolve
311;;; ambiguous formats--formats that are changing (over time) incompatibly.
312(defun time-stamp-string-preprocess (format &optional time)
313 ;; Uses a FORMAT to format date, time, file, and user information.
314 ;; Optional second argument TIME is only for testing.
315 ;; Implements non-time extensions to format-time-string
316 ;; and all time-stamp-format compatibility.
317 (let ((fmt-len (length format))
318 (ind 0)
319 cur-char
320 (prev-char nil)
321 (result "")
322 field-index
323 field-width
324 field-result
325 alt-form change-case require-padding
326 (paren-level 0))
327 (while (< ind fmt-len)
328 (setq cur-char (aref format ind))
329 (setq
330 result
331 (concat result
332 (cond
333 ((eq cur-char ?%)
334 ;; eat any additional args to allow for future expansion
335 (setq alt-form nil change-case nil require-padding nil)
336 (while (progn
337 (setq ind (1+ ind))
338 (setq cur-char (if (< ind fmt-len)
339 (aref format ind)
340 ?\0))
341 (or (eq ?. cur-char)
342 (eq ?, cur-char) (eq ?: cur-char) (eq ?@ cur-char)
343 (eq ?- cur-char) (eq ?+ cur-char) (eq ?_ cur-char)
344 (eq ?\ cur-char) (eq ?# cur-char) (eq ?^ cur-char)
345 (and (eq ?\( cur-char)
346 (not (eq prev-char ?\\))
347 (setq paren-level (1+ paren-level)))
348 (if (and (eq ?\) cur-char)
349 (not (eq prev-char ?\\))
350 (> paren-level 0))
351 (setq paren-level (1- paren-level))
352 (and (> paren-level 0)
353 (< ind fmt-len)))))
354 (setq prev-char cur-char)
355 ;; some characters we actually use
356 (cond ((eq cur-char ?:)
357 (setq alt-form t))
358 ((eq cur-char ?#)
359 (setq change-case t))))
360 ;; get format width
361 (setq field-index ind)
362 (setq ind (1- ind))
363 (while (progn
364 (setq ind (1+ ind))
365 (setq cur-char (if (< ind fmt-len)
366 (aref format ind)
367 ?\0))
368 (and (<= ?0 cur-char) (>= ?9 cur-char))))
369 (setq field-width (substring format field-index ind))
370 (setq field-result
371 (cond
372 ((eq cur-char ?%)
373 "%")
374 ((eq cur-char ?a) ;day of week
375 (if change-case
376 (format-time-string "%#A" time)
377 (or alt-form (not (string-equal field-width ""))
378 (time-stamp-conv-warn "%a" "%:a"))
379 (if (and alt-form (not (string-equal field-width "")))
380 "" ;discourage "%:3a"
381 (format-time-string "%A" time))))
382 ((eq cur-char ?A)
383 (if alt-form
384 (format-time-string "%A" time)
385 (or change-case (not (string-equal field-width ""))
386 (time-stamp-conv-warn "%A" "%#A"))
387 (format-time-string "%#A" time)))
388 ((eq cur-char ?b) ;month name
389 (if change-case
390 (format-time-string "%#B" time)
391 (or alt-form (not (string-equal field-width ""))
392 (time-stamp-conv-warn "%b" "%:b"))
393 (if (and alt-form (not (string-equal field-width "")))
394 "" ;discourage "%:3b"
395 (format-time-string "%B" time))))
396 ((eq cur-char ?B)
397 (if alt-form
398 (format-time-string "%B" time)
399 (or change-case (not (string-equal field-width ""))
400 (time-stamp-conv-warn "%B" "%#B"))
401 (format-time-string "%#B" time)))
402 ((eq cur-char ?d) ;day of month, 1-31
fdac7fba 403 (time-stamp-do-number cur-char alt-form field-width time))
fd72ddf6 404 ((eq cur-char ?H) ;hour, 0-23
fdac7fba 405 (time-stamp-do-number cur-char alt-form field-width time))
fd72ddf6 406 ((eq cur-char ?I) ;hour, 1-12
fdac7fba 407 (time-stamp-do-number cur-char alt-form field-width time))
fd72ddf6 408 ((eq cur-char ?m) ;month number, 1-12
fdac7fba 409 (time-stamp-do-number cur-char alt-form field-width time))
fd72ddf6 410 ((eq cur-char ?M) ;minute, 0-59
fdac7fba 411 (time-stamp-do-number cur-char alt-form field-width time))
fd72ddf6
RS
412 ((eq cur-char ?p) ;am or pm
413 (or change-case
414 (time-stamp-conv-warn "%p" "%#p"))
415 (format-time-string "%#p" time))
416 ((eq cur-char ?P) ;AM or PM
417 (format-time-string "%p" time))
418 ((eq cur-char ?S) ;seconds, 00-60
fdac7fba 419 (time-stamp-do-number cur-char alt-form field-width time))
fd72ddf6
RS
420 ((eq cur-char ?w) ;weekday number, Sunday is 0
421 (format-time-string "%w" time))
422 ((eq cur-char ?y) ;year
423 (or alt-form (not (string-equal field-width ""))
424 (time-stamp-conv-warn "%y" "%:y"))
425 (string-to-int (format-time-string "%Y" time)))
426 ((eq cur-char ?Y) ;4-digit year, new style
427 (string-to-int (format-time-string "%Y" time)))
428 ((eq cur-char ?z) ;time zone lower case
429 (if change-case
430 "" ;discourage %z variations
431 (format-time-string "%#Z" time)))
432 ((eq cur-char ?Z)
433 (if change-case
434 (format-time-string "%#Z" time)
435 (format-time-string "%Z" time)))
436 ((eq cur-char ?f) ;buffer-file-name, base name only
437 (if buffer-file-name
438 (file-name-nondirectory buffer-file-name)
439 time-stamp-no-file))
440 ((eq cur-char ?F) ;buffer-file-name, full path
441 (or buffer-file-name
442 time-stamp-no-file))
443 ((eq cur-char ?s) ;system name
444 (system-name))
445 ((eq cur-char ?u) ;user name
446 (user-login-name))
447 ((eq cur-char ?h) ;mail host name
448 (time-stamp-mail-host-name))
449 ))
450 (if (string-equal field-width "")
451 field-result
452 (let ((padded-result
453 (format (format "%%%s%c"
454 field-width
455 (if (numberp field-result) ?d ?s))
456 (or field-result ""))))
457 (let ((initial-length (length padded-result))
458 (desired-length (string-to-int field-width)))
459 (if (> initial-length desired-length)
460 ;; truncate strings on right, years on left
461 (if (stringp field-result)
462 (substring padded-result 0 desired-length)
463 (if (eq cur-char ?y)
464 (substring padded-result (- desired-length))
465 padded-result)) ;non-year numbers don't truncate
466 padded-result)))))
467 (t
468 (char-to-string cur-char)))))
469 (setq ind (1+ ind)))
470 result))
471
fdac7fba
RS
472(defun time-stamp-do-number (format-char alt-form field-width time)
473 ;; Handle a compatible FORMAT-CHAR where only
fd72ddf6 474 ;; the default width/padding will change.
fdac7fba
RS
475 ;; ALT-FORM is whether `#' specified. FIELD-WIDTH is the string
476 ;; width specification or "". TIME is the time to convert.
fd72ddf6
RS
477 (let ((format-string (concat "%" (char-to-string format-char))))
478 (and (not alt-form) (string-equal field-width "")
479 (time-stamp-conv-warn format-string
480 (format "%%:%c" format-char)))
481 (if (and alt-form (not (string-equal field-width "")))
482 "" ;discourage "%:2d" and the like
483 (string-to-int (format-time-string format-string time)))))
484
485(defvar time-stamp-conversion-warn t
486 "Non-nil to warn about soon-to-be-unsupported forms in time-stamp-format.
487In would be a bad idea to disable these warnings!
488You really need to update your files instead.
489
490The new formats will work with old versions of Emacs.
491New formats are being recommended now to allow time-stamp-format
492to change in the future to be compatible with format-time-string.
493The new forms being recommended now will continue to work then.")
494
495
496(defun time-stamp-conv-warn (old-form new-form)
497 ;; Display a warning about a soon-to-be-obsolete format.
498 (cond
499 (time-stamp-conversion-warn
500 (save-excursion
501 (set-buffer (get-buffer-create "*Time-stamp-compatibility*"))
502 (goto-char (point-max))
503 (if (bobp)
504 (progn
505 (insert
506 "The formats recognized in time-stamp-format will change in a future release\n"
507 "to be compatible with the new, expanded format-time-string function.\n\n"
508 "The following obsolescent time-stamp-format construct(s) were found:\n\n")))
509 (insert "\"" old-form "\" -- use " new-form "\n"))
510 (display-buffer "*Time-stamp-compatibility*"))))
95772e85 511
fd72ddf6 512
b1defad2 513
b4b33e01
RS
514(defun time-stamp-string (&optional ts-format)
515 "Generate the new string to be inserted by \\[time-stamp].
516Optionally use FORMAT."
517 (or ts-format
518 (setq ts-format time-stamp-format))
519 (if (stringp ts-format)
95772e85
RS
520 (if (stringp time-stamp-time-zone)
521 (let ((real-time-zone (getenv "TZ")))
522 (unwind-protect
523 (progn
524 (setenv "TZ" time-stamp-time-zone)
525 (format-time-string
b4b33e01 526 (time-stamp-string-preprocess ts-format)))
95772e85
RS
527 (setenv "TZ" real-time-zone)))
528 (format-time-string
b4b33e01 529 (time-stamp-string-preprocess ts-format)))
03d7856a
KH
530 ;; handle version 1 compatibility
531 (cond ((or (eq time-stamp-old-format-warn 'error)
532 (and (eq time-stamp-old-format-warn 'ask)
533 (not (y-or-n-p "Use non-string time-stamp-format? "))))
534 (message "Warning: no time-stamp: time-stamp-format not a string")
535 (sit-for 1)
536 nil)
537 (t
538 (cond ((eq time-stamp-old-format-warn 'warn)
539 (message "Obsolescent time-stamp-format type; should be string")
540 (sit-for 1)))
b4b33e01 541 (time-stamp-fconcat ts-format " ")))))
b1defad2 542
c7c4ddd4
KH
543(defconst time-stamp-no-file "(no file)"
544 "String to use when the buffer is not associated with a file.")
545
b1defad2
RS
546(defun time-stamp-mail-host-name ()
547 "Return the name of the host where the user receives mail.
548This is the value of `mail-host-address' if bound and a string,
e654f4b0 549otherwise the value of the function system-name."
b1defad2
RS
550 (or (and (boundp 'mail-host-address)
551 (stringp mail-host-address)
552 mail-host-address)
b1defad2
RS
553 (system-name)))
554
555;;; the rest of this file is for version 1 compatibility
9565745a
RS
556
557(defun time-stamp-fconcat (list sep)
e1f40b28 558 "Similar to (mapconcat 'funcall LIST SEP) but LIST allows literals.
9565745a
RS
559If an element of LIST is a symbol, it is funcalled to get the string to use;
560the separator SEP is used between two strings obtained by funcalling a
561symbol. Otherwise the element itself is inserted; no separator is used
562around literals."
563 (let ((return-string "")
564 (insert-sep-p nil))
565 (while list
566 (cond ((symbolp (car list))
567 (if insert-sep-p
568 (setq return-string (concat return-string sep)))
569 (setq return-string (concat return-string (funcall (car list))))
570 (setq insert-sep-p t))
571 (t
572 (setq return-string (concat return-string (car list)))
573 (setq insert-sep-p nil)))
574 (setq list (cdr list)))
575 return-string))
576
03d7856a 577;;; Some functions used in time-stamp-format
9565745a
RS
578
579;;; Could generate most of a message-id with
e1f40b28 580;;; '(time-stamp-yymmdd "" time-stamp-hhmm "@" time-stamp-mail-host-name)
9565745a 581
9565745a
RS
582;;; pretty form, suitable for a title page
583
584(defun time-stamp-month-dd-yyyy ()
e1f40b28 585 "Return the current date as a string in \"Month DD, YYYY\" form."
b8944601 586 (format-time-string "%B %e, %Y"))
9565745a 587
b24173f7
RS
588(defun time-stamp-dd/mm/yyyy ()
589 "Return the current date as a string in \"DD/MM/YYYY\" form."
b8944601 590 (format-time-string "%d/%m/%Y"))
b24173f7 591
9565745a
RS
592;;; same as __DATE__ in ANSI C
593
594(defun time-stamp-mon-dd-yyyy ()
e1f40b28
RS
595 "Return the current date as a string in \"Mon DD YYYY\" form.
596The first character of DD is space if the value is less than 10."
b8944601 597 (format-time-string "%b %d %Y"))
9565745a
RS
598
599;;; RFC 822 date
600
601(defun time-stamp-dd-mon-yy ()
e1f40b28 602 "Return the current date as a string in \"DD Mon YY\" form."
b8944601 603 (format-time-string "%d %b %y"))
9565745a
RS
604
605;;; RCS 3 date
606
607(defun time-stamp-yy/mm/dd ()
e1f40b28 608 "Return the current date as a string in \"YY/MM/DD\" form."
b8944601 609 (format-time-string "%y/%m/%d"))
9565745a
RS
610
611;;; RCS 5 date
612
613(defun time-stamp-yyyy/mm/dd ()
e1f40b28 614 "Return the current date as a string in \"YYYY/MM/DD\" form."
b8944601 615 (format-time-string "%Y/%m/%d"))
9565745a 616
e1f40b28 617;;; ISO 8601 date
9565745a 618
e1f40b28
RS
619(defun time-stamp-yyyy-mm-dd ()
620 "Return the current date as a string in \"YYYY-MM-DD\" form."
b8944601 621 (format-time-string "%Y-%m-%d"))
9565745a 622
e1f40b28
RS
623(defun time-stamp-yymmdd ()
624 "Return the current date as a string in \"YYMMDD\" form."
b8944601 625 (format-time-string "%y%m%d"))
9565745a
RS
626
627(defun time-stamp-hh:mm:ss ()
e1f40b28 628 "Return the current time as a string in \"HH:MM:SS\" form."
b8944601 629 (format-time-string "%T"))
9565745a 630
9565745a 631(defun time-stamp-hhmm ()
e1f40b28 632 "Return the current time as a string in \"HHMM\" form."
b8944601 633 (format-time-string "%H%M"))
9565745a
RS
634
635(provide 'time-stamp)
636
637;;; time-stamp.el ends here