ついカッっとなって
書いてしまいました。
これで「あの人は今日で n 歳と m ヶ月なのかな」という疑問にすぐに答えらます :)
emacs lisp です。
(defun combined-date-number (&optional year month day) (string-to-int (format-time-string "%Y%m%d" (when (and year month day) (encode-time 0 0 0 day month year))))) (defun how-old (birth:year birth:month birth:day) "返り値はリストです。 car が 年齢、cadr が誕生日からの経過月になっています。 経過月の計算には `birth:day' が `today:day' 未満かどうかの 判定が含まれています。 例えば 1 月 15 日生まれの場合、2 月 15 日を越えてはじめて \"誕生日から 1 箇月経過\"となります。" (let ((today:num (combined-date-number)) (birthday:num (combined-date-number birth:year birth:month birth:day)) (today:month (nth 4 (decode-time))) (today:day (nth 3 (decode-time)))) (list (truncate (/ (- today:num birthday:num) 10000.0)) (+ (- today:month birth:month) (if (< today:month birth:month) (if (>= today:day birth:day) 12 11) 0))))) (defun time-of-the-child (birth:year birth:month birth:day &optional base:old) (let ((old (how-old birth:year birth:month birth:day)) (base:old (or (if base:old (or (and (listp base:old) (remove nil (mapcar #'(lambda (arg) (when (numberp arg) arg)) base:old))) (and (atom base:old) (numberp base:old) (list base:old)))) (list 4 6 17)))) ;; default (concat (format-time-string "%Y 年 %m 月 %d 日現在, ") (mapconcat #'(lambda (arg) (when (numberp arg) (format "%s 歳と %s 箇月" arg (+ (* (- (car old) arg) 12) (cadr old))))) base:old ", ") "です.")))
(time-of-the-child 1973 5 29) ;;=> 2008 年 01 月 30 日現在, 4 歳と 368 箇月, 6 歳と 344 箇月, 17 歳と 212 箇月です.
基準値を与えられます。
(time-of-the-child 1973 5 29 20) ;;=> 2008 年 01 月 30 日現在, 20 歳と 176 箇月です.
基準値にはリストも渡せます。
(time-of-the-child 1973 5 29 (list 10 20 30)) ;;=> 2008 年 01 月 30 日現在, 10 歳と 296 箇月, 20 歳と 176 箇月, 30 歳と 56 箇月です.
無効な optional 引数が渡された場合は、初期値を用いて計算します。
(time-of-the-child 1973 5 29 'a) ;;=> 2008 年 01 月 30 日現在, 4 歳と 368 箇月, 6 歳と 344 箇月, 17 歳と 212 箇月です.
- 年齢計算に「今日の日付を連結した数字から、誕生日に連結した数字を引いて 10000 で割る」を使ってみました。
- 初めて使いました。便利なような。
- and や or を重ねるのが好きです。
- remove と mapcar で要らない子を削るのも好きです。
- symbol-name に : を含められるのを思い出して使ってみました。
- 慣習を知らないので格好悪いことになっているかも。
そうそう、ぼくは 1973 年生まれではありません*1ので、あしからず :)
*1:じゃあ誰なの