proglog

主にプログラミングに関する断片的メモ

howmファイルの切り分け:日付とファイル名

1日1ファイルのhowmのファイル名は現在、2009-04-15.howmとかいう、「YYYY-mm-dd.howm」という形式。
各メモのヘッダ行直下には「[2009-04-15 01:25] 」という、「YYYY-mm-dd HH:MM」でタイムスタンプが入っている。(タイムヘッダとする。)
ここから「2009-04-15-012500.homw」というような、「YYYY-mm-dd-HHMMSS.howm」という1メモ1ファイル名を作る。

なお、直下にタイムヘッダが無い、フォーマットが違う、直前のものと同じか遡っている場合、それらを無視して、直前で使った日付に1秒足したものをファイル名とする。

そんなわけで、そのデータは大域変数に保存すればいいけど、クロージャを使ってみる。

こんな感じで、例によってまずは闇雲に書く。

モジュールsrfi-19に時間や日付関係のものが集まっている。
timeとdateのクラスを行き来してれば、細かい操作もできていい感じ。

(use srfi-19)
(define (make-time-header filename)
  (let ((time-cur
	 (date->time-monotonic (make-date 0 0 0 0 (string->number (substring filename 8 10)) (string->number (substring filename 5 7)) (string->number (substring filename 0 4)) (* 9 60 60)))))

しかし、よく見ると、string->dateで文字列からdateオブジェクトが生成できるっぽい。
読み込みのフォーマット、テンプレート文字列はdate->stringのものをそのまま。

(use srfi-19)
(define (make-time-header filename)
  (let ((time-cur
	 (date->time-monotonic (string->date (substring filename 0 10) "~Y-~m-~d") )))
    (lambda (time-h)
      (let ((time-tmp 0) (duration 0))
	(cond ((= 16 (string-length time-h))
	       (set! time-tmp (date->time-monotonic (string->date time-h "~Y-~m-~d ~H:~M")))
	       (cond ((time>? time-tmp time-cur)
		      (set! time-cur time-tmp)
		      (set! duration 0))
		     (else
		      (set! duration 1))))
	      (else
	       (set! duration 1)))
	(set-time-second! time-cur (+ (time-second time-cur) duration))
	(date->string (time-monotonic->date time-cur (date-zone-offset (current-date))) "~Y-~m-~d-~H~M~S")))))

(define get-basename (make-time-header "2010-02-12.howm"))
(get-basename "2010-02-13 09:13")
(get-basename "")
(get-basename "2010-02-19 10:13")

time-curに直前の日付を保存しておいて、読み込んだタイムヘッダと比較。そして1秒足すかそのまま使うか、という場合分け。
とやってると迷宮に入り込んだ。

要は、ファイル名作成に使うデータを、最新にすればいい、ということになる。
そして使ったら1秒増やしてtime-curに保存。

(use srfi-19)

(define (make-basename-generator filename)
  (let ((time-cur
	 (date->time-monotonic (string->date (substring filename 0 10) "~Y-~m-~d") )))
    (lambda (time-h)
      (let ((time-tmp (make-time time-monotonic 0 0)))
	(when (and (string? time-h) (= 16 (string-length time-h)))
	       (set! time-tmp (date->time-monotonic (string->date time-h "~Y-~m-~d ~H:~M"))))
	(when (time<? time-tmp time-cur)
	       (set-time-second! time-tmp (time-second time-cur)))
	(set-time-second! time-cur (+ (time-second time-tmp) 1))
	(date->string (time-monotonic->date time-tmp (date-zone-offset (current-date))) "~Y-~m-~d-~H~M~S")))))


(define get-basename (make-basename-generator "2010-02-12.howm"))
(get-basename "2010-02-13 09:13")
(get-basename #f)
(get-basename "2010-02-16 00:00")

と考えると、こんな感じかなあ。


オブジェクトのコピーのつもりでつい、「(set! time-tmp time-cur)」とかやっちゃいがちだった。
set!は参照先を切り替えるだけなんだな。