Skip to content

Commit

Permalink
First working (it would seem) implementation
Browse files Browse the repository at this point in the history
This is the first working implementation of converting
Gregorian date to Korean lunar date and vice vesa.
  • Loading branch information
cinsk committed Sep 27, 2011
1 parent d577cd6 commit 55afdf2
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 20 deletions.
11 changes: 10 additions & 1 deletion Rakefile
Expand Up @@ -3,7 +3,7 @@ require 'rake/clean'


task :default => [:generate] task :default => [:generate]


SRC = FileList['script/lunar-ko-*.rb'] SRC = FileList['script/lunar-ko-mdays.rb']


SRC.each do |script| SRC.each do |script|
target = File.basename(script.sub(/\.rb$/, ".el")) target = File.basename(script.sub(/\.rb$/, ".el"))
Expand All @@ -16,3 +16,12 @@ SRC.each do |script|
task :generate => target task :generate => target
end end


CLEAN.include("cache.dat")
task :cachedata => ["script/lunar-ko-cache.rb"] do |t|
sh "./script/lunar-ko-cache.rb -dscript/ko-lunar.db > cache.dat"
end

file "lunar-ko-cache.el" => [:cachedata] do |t|
sh "emacs -q -L . --batch -l gencache -f lunar-ko-generate-cache cache.dat lunar-ko-cache.el"
end
task :generate => "lunar-ko-cache.el"
81 changes: 68 additions & 13 deletions gencache.el
Expand Up @@ -20,15 +20,38 @@


;;; Commentary: ;;; Commentary:


;; ;; In my first implementation, I used to generate "lunar-ko-cache.el"
;; using a Ruby script, since Ruby does have support for sqlite3
;; database. In that implementation, I generate (julian . kld) pair
;; where JULIAN is the Astronomical Julian Day(AJD) number, and KLD is
;; the numerical representation of Korean lunar date.
;;
;; Unfortunately, the Emacs algorithm that convert Gregorian date to
;; julian day number is different from that of Ruby. For example,
;;
;; Gregorian Emacs AJD Ruby AJD
;; ---------- --------- ---------
;; 1582-10-04 2299149.5 2299159.5
;; 1582-10-05 2299150.5 N/A
;; ... ... N/A
;; 1582-10-14 2299159.5 N/A
;; 1582-10-15 2299160.5 2299160.5
;;
;; (Note that Gregorian calendar starts from 1582-10-15.)
;;
;; Thus, I first create intermediate file using Ruby to read sqlite3
;; database, then using Emacs lisp to generate "lunar-ko-cache.el".


;;; Code: ;;; Code:


(require 'calendar) (require 'calendar)


;; To run:
;; ;;
;;emacs -L . -l gencache --batch --eval '(lunar-ko-generate-cache "./script/cache.dat" "cache.el"))' ;; $ emacs -q -L . -l gencache --batch \
;; -f lunar-ko-generate-cache "./script/cache.dat" "cache.el"
;; ;;
;; See "Rakefile" for more.


; ;
; TODO: consult `batch-byte-compile' and modify ; TODO: consult `batch-byte-compile' and modify
Expand All @@ -42,23 +65,50 @@ Julian day number. See also `calendar-astro-date-string'."
(calendar-astro-from-absolute (calendar-astro-from-absolute
(calendar-absolute-from-gregorian date))) (calendar-absolute-from-gregorian date)))


(defun lunar-ko-generate-cache (srcfile &optional outfile) (defvar cache-header
(format ";;; lunar-ko-cache.el --- cache data for Korean lunar calendar
;; Automatically generated by gencache.el in %s
(defconst korean-lunar-cache
[" (current-time-string))
"cache header")

(defvar cache-tail
"]
\"Solar to Korean lunar cache\")
(provide 'lunar-ko-cache)"
"cache tail")

(defun lunar-ko-generate-cache (&optional srcfile outfile)
(let ((coding-system-for-read 'utf-8) (let ((coding-system-for-read 'utf-8)
(coding-system-for-write 'utf-8)) (coding-system-for-write 'utf-8))
(if (and noninteractive
(consp command-line-args-left)
(> (length command-line-args-left) 0))
(setq srcfile (car command-line-args-left)
outfile (cadr command-line-args-left)))
(let* ((srcpath (expand-file-name srcfile)) (let* ((srcpath (expand-file-name srcfile))
(outpath (expand-file-name (outpath (expand-file-name
(or outfile (or outfile
(replace-regexp-in-string "\\.[^.]*$" ".el" srcfile))))) (replace-regexp-in-string
(message "srcpath: %s" srcpath) "\\.[^.]*$" ".el" srcfile)))))
(message "outpath: %s" outpath) ;;(message "srcpath: %s" srcpath)
(message "args: %S" command-line-args-left) ;;(message "outpath: %s" outpath)
(let ((srcbuf (find-file-noselect srcpath t t)) ;;(message "args: %S" command-line-args-left)

(if (not (file-readable-p srcpath))
(error "error: cannot find %s" srcpath))
(let ((srcbuf (find-file-noselect srcpath t))
(outbuf (create-file-buffer outpath))) (outbuf (create-file-buffer outpath)))
(save-current-buffer (save-current-buffer
(set-buffer outbuf) (set-buffer outbuf)
(setq buffer-file-name outpath) (setq buffer-file-name outpath)
;;(setq buffer-file-coding-system 'utf-8) ;;(setq buffer-file-coding-system 'utf-8)
(emacs-lisp-mode)) ;;(set-buffer-multibyte t)
(emacs-lisp-mode)
(insert cache-header))
(save-current-buffer (save-current-buffer
(set-buffer srcbuf) (set-buffer srcbuf)
(goto-char (point-min)) (goto-char (point-min))
Expand All @@ -69,7 +119,9 @@ Julian day number. See also `calendar-astro-date-string'."
(month (string-to-number (match-string-no-properties 2))) (month (string-to-number (match-string-no-properties 2)))
(day (string-to-number (match-string-no-properties 3))) (day (string-to-number (match-string-no-properties 3)))
(lunar (match-string-no-properties 4)) (lunar (match-string-no-properties 4))
(text (match-string-no-properties 5))) (text (string-to-multibyte (match-string-no-properties 5))))
(if (string-match "???001001$" lunar)
(message "Generating cache for ..%d.." year))
(save-current-buffer (save-current-buffer
(set-buffer outbuf) (set-buffer outbuf)
(goto-char (point-max)) (goto-char (point-max))
Expand All @@ -80,10 +132,13 @@ Julian day number. See also `calendar-astro-date-string'."
lunar text))))))) lunar text)))))))
(save-current-buffer (save-current-buffer
(set-buffer outbuf) (set-buffer outbuf)
(goto-char (point-max))
(insert cache-tail)
(save-buffer)) (save-buffer))
(kill-buffer srcbuf) (when nil
(kill-buffer outbuf))))) (kill-buffer srcbuf)

(kill-buffer outbuf))
))))




(provide 'gencache) (provide 'gencache)
Expand Down
13 changes: 7 additions & 6 deletions lunar-ko.el
Expand Up @@ -147,7 +147,7 @@ of (MONTH DAY YEAR). See also `calendar-astro-goto-day-number'."
;; `korean-lunar-cache' is generated by Ruby, we cannot convert the ;; `korean-lunar-cache' is generated by Ruby, we cannot convert the
;; julian date in `korean-lunar-cache' if DATE is prior to ;; julian date in `korean-lunar-cache' if DATE is prior to
;; 1582-10-*. ;; 1582-10-*.
(assert (> date 2299177) "out of range: %S") ;;(assert (> date 2299177) "out of range: %S")
(calendar-gregorian-from-absolute (calendar-gregorian-from-absolute
(floor (calendar-astro-to-absolute date)))) (floor (calendar-astro-to-absolute date))))


Expand Down Expand Up @@ -262,20 +262,21 @@ is the index value of the vector in `korean-lunar-months' (0-12)."
The internal form is like (MONTH-INDEX DAY YEAR), where MONTH-INDEX The internal form is like (MONTH-INDEX DAY YEAR), where MONTH-INDEX
is the index value of the vector in `korean-lunar-months' (0-12)." is the index value of the vector in `korean-lunar-months' (0-12)."
(let* ((month (lunar-ko-month impl)) (let* ((midx (lunar-ko-month impl))
(day (lunar-ko-day impl)) (day (lunar-ko-day impl))
(year (lunar-ko-year impl)) (year (lunar-ko-year impl))
(entry (or cache (entry (or cache
(gethash year korean-lunar-months))) (gethash year korean-lunar-months)))
(leap-month (car entry))) (leap-month (car entry)))
(cond ((null leap-month) (list (1+ month) day year)) (cond ((null leap-month) (list (1+ midx) day year))
((< month leap-month) (list (1+ month) day year)) ((< midx leap-month) (list (1+ midx) day year))
((= month leap-month) (list (1+ month) day year t)) ((= midx leap-month) (list midx day year t))
((> month leap-month) (list month day year))))) ((> midx leap-month) (list midx day year)))))


(defun lunar-ko-advance (ldatespec days) (defun lunar-ko-advance (ldatespec days)
"Return the lunar date, advanced DAYS days from LDATESPEC." "Return the lunar date, advanced DAYS days from LDATESPEC."
(let ((date (lunar-ko-date-to-impl ldatespec))) (let ((date (lunar-ko-date-to-impl ldatespec)))
(setq days (round days))
(while (> days 0) (while (> days 0)
(let* ((year (lunar-ko-year date)) (let* ((year (lunar-ko-year date))
(entry (gethash year korean-lunar-months)) (entry (gethash year korean-lunar-months))
Expand Down

0 comments on commit 55afdf2

Please sign in to comment.