Archive for 2016年3月月15日|Daily archive page

日付関数の日本語化

 newLISP の日付関数には、date, date-list, date-parse, date-value, now 等がありますが、date 以外はグリニッジ標準時なので、日本時間で使うには補正が必要です。
 また、date

> (date)
"Tue Mar 15 16:00:19 2016"
> 

 こんな風に、英語表記です。
 そこで、日本語表記、日本時間用の日付関数を定義してみました。

(context 'MAIN:jdate)
(setq YEAR0 1900 EPOCH_YR 1970 SECS_DAY (* 24 60 60))
(define (calcDateValue year month day (hour 0) (int-min 0) (sec 0))
; Algorithm quoting from newLISP source.
  (let (dateValue)
    (setq dateValue (+ (* 367 year) (- (/ (* 7 (+ year (/ (+ month 9) 12))) 4)) (/ (* 275 month) 9) day 1721013))
    (setq dateValue (+ (* dateValue 24 3600) (* hour 3600) (* int-min 60) sec -413319296)) 
    (setq dateValue (& dateValue 0xFFFFFFFF))
    (if (>= dateValue 4107596400) (-- dateValue 86400) dateValue)))
(define (leap (y ((now) 0)))
  (if (and (zero? (% y 4))
       (or (zero? (% y 400))
           (not (zero? (% y 100))))) 1 0))
(define (yearsize year) (+ (leap year) 365))
(define _ytab '((31 28 31 30 31 30 31 31 30 31 30 31)(31 29 31 30 31 30 31 31 30 31 30 31)))
(define (gmtime tm)
; Algorithm quoting from common C-library source.
  (letn (year EPOCH_YR
         dayclock (% tm SECS_DAY)
         dayno (/ tm SECS_DAY)
         tm_sec (% dayclock 60)
         tm_min (/ (% dayclock 3600) 60)
         tm_hour (/ dayclock 3600)
         tm_wday (% (+ 4 dayno) 7))
    (while (>= dayno (yearsize year)) 
      (-- dayno (yearsize year))
      (++ year))
    (let (tm_year (- year 0); YEAR0
          tm_yday dayno
          tm_mon 0
          tm_mday 1)
       (while (>= dayno (_ytab (leap year) tm_mon))
         (-- dayno (_ytab (leap year) tm_mon))
         (++ tm_mon))
       (++ tm_mday dayno)
       (list tm_year (++ tm_mon) tm_mday tm_hour tm_min tm_sec (++ tm_yday) tm_wday))))
(define (jdate:now (offset 540) idx)
  (if idx (MAIN:now offset idx) (MAIN:now offset)))
(define (jdate:value)
  (if (args) (- (apply calcDateValue (args)) (* 9 60 60))
    (date-value)))
(define (jdate:list (sec (jdate:value)) idx)
  (letn (offset (* 9 60 60)
         lst (gmtime (+ sec offset)))
    (if idx (idx lst) lst)))
(define (jdate:jdate (value (jdate:value)))
  (let (lst (jdate:list value)
        str (if utf8 '(227 128 63 230 156 136 231 129 171 230 176 180 230 156 168 233 135 145 229 156 159 
 230 151 165)
                     '(129 64 140 142 137 206 144 133 150 216 139 224 147 121 147 250)))
    (append (join (map string (0 3 lst)) "/") " "
            (join (map string (3 3 lst)) ":") " "
            (if utf8 ((* 3 (lst 7)) 3 (pack (dup "b" (length str)) str))
                     ((* 2 (lst 7)) 2 (pack (dup "b" (length str)) str))))))
(define (jdate:parse dateStr formatStr , res)
  (if (= formatStr "%c") (setq formatStr "%m/%d/%y %H:%M:%S"))
  (let (specs (find-all "(%.)" formatStr)
        regStr (replace "(%.)" (replace "." formatStr "\\.") "(.+)" 0)
        months '("" "Jan" "Feb" "Mar" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec")
        Months '("" "January" "February" "March" "April" "May" "June" 
                 "July" "August" "September" "October" "November" "December")
        dateLst '(1900 1 1 0 0 0))
    (setq res (regex regStr dateStr))
    (when res 
       (setq res (rest (filter string? res)))
       (when (= (length specs) (length res))
          (dolist (i (transpose (MAIN:list specs res)))
             (case (i 0) 
               ("%b" (setf (dateLst 1) (find (i 1) months 1)))
               ("%B" (setf (dateLst 1) (find (i 1) Months 1)))
               ("%d" (setf (dateLst 2) (int (i 1) 0 10)))
               ("%H" (setf (dateLst 3) (int (i 1) 0 10)))
               ("%m" (setf (dateLst 1) (int (i 1) 0 10)))
               ("%M" (setf (dateLst 4) (int (i 1) 0 10)))
               ("%S" (setf (dateLst 5) (int (i 1) 0 10)))
               ("%Y" (setf (dateLst 0) (int (i 1) 0 10)))
               ("%y" (setf (dateLst 0) (int (string "20" (i 1)))))
               (true )))))
  (if-not (find nil dateLst) (apply jdate:value dateLst))))
(context MAIN)

 使える関数は、jdate, jdate:list, jdate:parse, jdate:value, jdate:now で、それぞれ date, date-list, date-parse, date-value, now に対応します。
 使い方は、

> (jdate)
"2016/3/16 17:8:15 火"
> (jdate:list)
(2016 3 16 17 8 23 75 2)
> (jdate:value 2016 3 16)
1458054000
> (jdate:now)
(2016 3 15 17 8 48 630885 75 2 600 -60)
> (jdate:parse "2010.10.18 7:00" "%Y.%m.%d %H:%M")
1287352800
> (jdate:list (jdate:parse "2010.10.18 7:00" "%Y.%m.%d %H:%M"))
(2010 10 18 7 0 0 291 1)
> 

 こんな感じ、解説は次回に、、、

広告