home *** CD-ROM | disk | FTP | other *** search
/ Windows 95 v2.4 Fix / W95-v2.4fix.iso / ACADWIN / SAMPLE / JULIAN.LSP < prev    next >
Encoding:
Text File  |  1995-02-08  |  15.2 KB  |  382 lines

  1. ; Next available MSG number is     8 
  2. ; MODULE_ID JULIAN_LSP_
  3. ;;;
  4. ;;;    JULIAN.LSP
  5. ;;;    
  6. ;;;    Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994 by Autodesk, Inc.
  7. ;;;
  8. ;;;    Permission to use, copy, modify, and distribute this software
  9. ;;;    for any purpose and without fee is hereby granted, provided
  10. ;;;    that the above copyright notice appears in all copies and
  11. ;;;    that both that copyright notice and the limited warranty and
  12. ;;;    restricted rights notice below appear in all supporting
  13. ;;;    documentation.
  14. ;;;
  15. ;;;    AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
  16. ;;;    AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
  17. ;;;    MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC.
  18. ;;;    DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
  19. ;;;    UNINTERRUPTED OR ERROR FREE.
  20. ;;;
  21. ;;;    Use, duplication, or disclosure by the U.S. Government is subject to
  22. ;;;    restrictions set forth in FAR 52.227-19 (Commercial Computer
  23. ;;;    Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) 
  24. ;;;    (Rights in Technical Data and Computer Software), as applicable.
  25. ;;;
  26. ;;;.
  27. ;;;
  28. ;;;----------------------------------------------------------------------------
  29. ;;;
  30. ;;; DESCRIPTION
  31. ;;;
  32. ;;;         AutoCAD Julian date / calendar date conversion routines
  33. ;;;
  34. ;;; CTOJ  --  Converts calendar date and time to Julian date
  35. ;;;
  36. ;;;     Call:     (ctoj <year> <month> <day> <hour> <minute> <second/fraction>)
  37. ;;;     Input:    Calendar date as argument list, for example:
  38. ;;;                     (ctoj 1957 10 4 19 26 24) ; Launch of Sputnik 1
  39. ;;;     Returns:  Julian date / fraction, as in DATE setvar
  40. ;;;
  41. ;;;
  42. ;;; DTOJ  --  Converts AutoCAD calendar date/time to Julian date
  43. ;;;
  44. ;;;     Call:     (dtoj <calendar date>)
  45. ;;;     Input:    Real number YYYYMMDD<.HHMMSSmsec>, like CDATE setvar.
  46. ;;;     Returns:  Julian date / fraction, as in DATE setvar
  47. ;;;
  48. ;;;
  49. ;;; JTOC  --  Converts Julian date to calendar date list
  50. ;;;
  51. ;;;     Call:     (jtoc <Julian date>)
  52. ;;;     Input:    Real number <Julian day>.<fraction>, like DATE setvar
  53. ;;;     Returns:  Calendar date/time list:
  54. ;;;                 (<year> <month> <day> <hour> <minute> <second/fraction>)
  55. ;;;
  56. ;;;
  57. ;;; JTOD  --  Converts Julian date to AutoCAD calendar date/time
  58. ;;;
  59. ;;;     Call:     (jtod <Julian date>)
  60. ;;;     Input:    Real number <Julian day>.<fraction>, like DATE setvar
  61. ;;;     Returns:  Calendar date/time, as in CDATE setvar
  62. ;;;
  63. ;;;
  64. ;;; JTOW  --  Determines day of the week for a given Julian day
  65. ;;;
  66. ;;;     Call:     (jtow <Julian date>)
  67. ;;;     Input:    Real number <Julian day>.<fraction>, like DATE setvar
  68. ;;;     Returns:  Integer day of the week, 0 = Sunday, 1 = Monday, ...
  69. ;;;               6 = Saturday
  70. ;;;
  71. ;;;
  72. ;;; C:DATE  --  Implements DATE command to display the current date/time
  73. ;;;             in the format: Day YYYY/M/D HH:MM:SS.msec
  74. ;;;
  75. ;;;     Call:     DATE  (at AutoCAD's Command: prompt)
  76. ;;;     Input:    None (obtains DATE setvar in Julian format)
  77. ;;;     Returns;  Nothing
  78. ;;;
  79. ;;;     Uses (JTOD) to convert to calendar format, and edits the date/time
  80. ;;;     from there.  Day of the week is calculated with (JTOW).
  81. ;;;
  82. ;;;
  83. ;;; Note  that  a  Julian  date  returned  by AutoCAD's DATE setvar or
  84. ;;; computed from the CDATE setvar is a true Julian date only  if  the
  85. ;;; system's clock is set to UTC/Zulu  (Greenwich Mean Time).   Julian
  86. ;;; dates  are easily compared for earlier/later, and durations can be
  87. ;;; computed via simple subtraction.  However,  such calculations  are
  88. ;;; accurate  only  for  readings obtained in the same time zone, with
  89. ;;; the same clock or synchronized clocks.
  90. ;;;
  91. ;;;
  92. ;;; DETAILS
  93. ;;;
  94. ;;; If  you're  interested  solely  in  converting  contemporary dates
  95. ;;; provided by AutoCAD between Julian and calendar  date  format  you
  96. ;;; can  ignore  the  following  discussion.  If you wish to use these
  97. ;;; functions for general work with Julian  dates  over  their  entire
  98. ;;; historical  span  of validity (any day beginning with the start of
  99. ;;; the year 4713 B.C. has a valid Julian day number), read on.
  100. ;;;
  101. ;;; 1.  B.C. versus negative year numbers
  102. ;;;
  103. ;;;     Historians refer to the first year of the Christian era as  "1
  104. ;;;     A.D." with the year that preceded it called "1 B.C.".  This is
  105. ;;;     consistent with usage at the time, since  zero  did  not  come
  106. ;;;     into  use  until much later, but creates a messy discontinuity
  107. ;;;     in the numbering of  years  which  complicates  any  algorithm
  108. ;;;     which attempts to calculate across that boundary.  Astronomers
  109. ;;;     have adopted the convention that the  year  which  preceded  1
  110. ;;;     A.D. is  denoted  "year 0", the year before that "year -1" and
  111. ;;;     so on.  Thus any year less than 1  can  be  converted  to  the
  112. ;;;     nomenclature  used  by  historians  by discarding the sign and
  113. ;;;     adding one to  get  the  B.C. year  number.   These  functions
  114. ;;;     follow  the  astronomical convention for years prior to 1 A.D.
  115. ;;;     and hence the year in  which  Julius  Caesar  established  the
  116. ;;;     Julian  calendar  in  the Roman Empire, 46 B.C. in the history
  117. ;;;     books, is specified as "-45" when using these functions.
  118. ;;;
  119. ;;; 2.  Julian versus Gregorian calendar
  120. ;;;
  121. ;;;     In  October  of  1582,  the  modern  Gregorian  calendar   was
  122. ;;;     proclaimed  by the Vatican, replacing the less-accurate Julian
  123. ;;;     calendar.  At the same time, 10 days were skipped  to  correct
  124. ;;;     the  inaccuracy  in  the  date  of the equinoxes and solstices
  125. ;;;     which had accumulated over the almost six centuries the Julian
  126. ;;;     calendar  had  been  used.   Thus  Thursday,  October  4, 1582
  127. ;;;     (Julian calendar) was followed by  Friday,  October  15,  1582
  128. ;;;     (Gregorian calendar).  These functions assume, therefore, that
  129. ;;;     dates on or before October 4, 1582 are in the Julian  calendar
  130. ;;;     and dates thereafter in the Gregorian.  If you're working with
  131. ;;;     dates from history, you must be extremely  careful  to  verify
  132. ;;;     which  calendar  they  are  specified in, as not all countries
  133. ;;;     adopted  the  Gregorian calendar immediately.  Britain and its
  134. ;;;     colonies, for example, remained on the Julian  calendar  until
  135. ;;;     Wednesday,  September 2, 1752, at which time 11 days had to be
  136. ;;;     dropped to align with  the  Gregorian  calendar  on  Thursday,
  137. ;;;     September  14,  1752.   Russia remained on the Julian calendar
  138. ;;;     until after the 1917 revolution, and Turkey did not adopt  the
  139. ;;;     Gregorian   calendar  until  1927.   The  later  the  date  of
  140. ;;;     adoption, naturally, the greater the number of days of  Julian
  141. ;;;     calendar error skipped.
  142. ;;;
  143. ;;; 3.  Round-off in "calendar date" format
  144. ;;;
  145. ;;;     AutoCAD's calendar date format as returned by (getvar "cdate")
  146. ;;;     is defined as a floating-point number interpreted as:
  147. ;;;
  148. ;;;         yyyymmdd.hhiissttt
  149. ;;;
  150. ;;;     where yyyy = year, mm = month number, dd = year number,  hh  =
  151. ;;;     hours,  ii = minutes, ss = seconds, and ttt = thousandths of a
  152. ;;;     second.  If you look carefully at  this  format,  you'll  note
  153. ;;;     that  the  full  specification  occupies 17 digits, while IEEE
  154. ;;;     floating-point numbers as used in AutoCAD have a precision  of
  155. ;;;     16 digits at best and less than that once you start to perform
  156. ;;;     calculations on them.  Thus,  extracting  millisecond  timings
  157. ;;;     from  calendar  dates is problematic, and using calendar dates
  158. ;;;     for any but the simplest calculations can lead to obscure  and
  159. ;;;     intermittent errors due to round-off.  The best approach is to
  160. ;;;     avoid   using   "calendar   dates"   entirely,   perform   all
  161. ;;;     calculations  with  Julian  dates, and  use  the JTOC and CTOJ
  162. ;;;     functions to convert calendar dates to and from Julian.  Since
  163. ;;;     these functions don't try to pack an entire calendar date into
  164. ;;;     one floating point number, they avoid the  round-off  problems
  165. ;;;     which plague AutoCAD "calendar dates".
  166. ;;; 
  167. ;;;
  168. ;;; REFERENCES
  169. ;;;
  170. ;;; The algorithms and test cases used herein may be found in Chapter 7
  171. ;;; (pages 59-66) of:
  172. ;;;
  173. ;;;     Meeus, Jean.  Astronomical Algorithms.  Richmond: Willman-Bell, 1991.
  174. ;;;
  175. ;;;----------------------------------------------------------------------------
  176. ;;;
  177. ;;; (CTOJ <year> <month> <day> <hour> <minute> <second/fraction>)
  178. ;;;
  179. (defun ctoj (yr m d hh mm ss / y a b)
  180.     (setq y yr)
  181.  
  182.     (if (<= m 2)
  183.         (setq y (1- y)
  184.               m (+ m 12)
  185.         )
  186.     )
  187.  
  188.     (if (or (< yr 1582)
  189.             (and (= yr 1582) (or (< m 10) (and (= m 10) (< d 5)))))
  190.         (setq b 0)                    ; Julian calendar
  191.         (setq a (fix (/ y 100))       ; Gregorian calendar
  192.               b (+ (- 2 a) (fix (/ a 4)))
  193.         )
  194.     )
  195.  
  196.     (+ (fix (+ (* 365.25 (+ y 4716)) (fix (* 30.6001 (+ m 1)))))
  197.          d b -1524.0 (/ (+ (* (+ (* hh 60) mm) 60) ss) (* 24.0 60 60)))
  198. )
  199. ;;;
  200. ;;;----------------------------------------------------------------------------
  201. ;;;
  202. ;;; (DTOJ <calendar date>)  --  convert calendar date/time to Julian
  203. ;;;
  204. (defun dtoj (cdate / c f yr ys m d)
  205.     (setq ys (if (< cdate 0) -1 1)    ; Sign on year
  206.           c (fix (abs cdate))         ; Date in unsigned digits
  207.           yr (* (/ c 10000) ys)       ; Get year
  208.           m (rem (/ c 100) 100)       ; Get month
  209.           d (rem c 100)               ; Get day
  210.           f (rem (abs cdate) 1)       ; Fraction of day
  211.     )
  212.     (ctoj yr m d (fix (+ (* f 100) 0.1))
  213.                   (rem (fix (+ (* f 10000) 0.1)) 100)
  214.                   (+ (rem (fix (+ (* f 1000000) 0.1)) 100)
  215.                      (/ (rem (fix (+ (* f 1000000000) 0.1)) 1000) 1000.0)))
  216. )
  217. ;;;
  218. ;;;----------------------------------------------------------------------------
  219. ;;;
  220. ;;; (JTOC <Julian date>)  --  convert Julian date/time to calendar date list
  221. ;;;
  222. (defun jtoc (td / time a b c d e alpha z m hh mm)
  223.     (setq time (* 86400.0 (- td (setq z (fix td)))))
  224.     (if (< z 2299161)
  225.         (setq a z)                                         ; Julian calendar
  226.         (setq alpha (fix (/ (- z 1867216.25) 36524.25))    ; Gregorian calendar
  227.               a (- (+ z 1 alpha) (fix (/ alpha 4)))
  228.         )
  229.     )
  230.  
  231.     (setq b (+ a 1524)
  232.           c (fix (/ (- b 122.1) 365.25))
  233.           d (fix (* 365.25 c))
  234.           e (fix (/ (- b d) 30.6001))
  235.     )
  236.  
  237.     (setq m (fix (if (< e 14) (1- e) (- e 13))))
  238.  
  239.     ; Determine the clock time from the fraction of a day
  240.  
  241.     (setq hh (fix (/ time 3600.0))
  242.           time (- time (* hh 3600.0))
  243.           mm (fix (/ time 60.0))
  244.     )
  245.  
  246.     ; Return calendar date as list
  247.  
  248.     (list (fix (- c (if (> m 2) 4716 4715))) m (fix (- b d (fix (* 30.6001 e))))
  249.           hh mm 
  250.           (- time (* mm 60))
  251.     )
  252. )
  253. ;;;
  254. ;;;
  255. ;;;----------------------------------------------------------------------------
  256. ;;;
  257. ;;; (JTOD <Julian date>)  --  convert Julian date/time to calendar
  258. ;;;
  259. (defun jtod (td / j)
  260.     (setq j (jtoc td))
  261.  
  262.     ; Return calendar date in form YYYYMMDD.HHMMSSmsec
  263.  
  264.     (* (+ (* (abs (car j)) 10000)     ; year
  265.           (* (cadr j) 100)            ; month
  266.           (caddr j)                   ; day
  267.           (/ (cadddr j) 100.0)        ; hour
  268.           (/ (nth 4 j) 10000.0)       ; minute
  269.           (/ (nth 5 j) 1000000.0)     ; seconds, milliseconds
  270.        )
  271.        (if (< (car j) 0) -1 1)        ; apply sign to year
  272.     )
  273. )
  274. ;;;
  275. ;;;----------------------------------------------------------------------------
  276. ;;;
  277. ;;; (JTOW <Julian date>)  --  Convert a Julian date to day of week
  278. ;;;
  279. (defun jtow (j)
  280.     (fix (rem (1+ j) 7))
  281. )
  282. ;;;
  283. ;;;----------------------------------------------------------------------------
  284. ;;;
  285. ;;;   (c:JTEST)  --  Internal test program for Julian date functions
  286. ;;;                  Displays several lines of numbers.  If none are
  287. ;;;                  flagged with "** Error **", all is okay.
  288. ;;;
  289. ;(defun c:JTEST (/ dl jl cjl cdl err eps)
  290. ;    (setq dl '(20000101.12    19870127.0   19870619.12  19880127.0
  291. ;               19880619.12    19000101.0   16000101.0   16001231.0
  292. ;                8370410.0712 -10000712.12 -10000229.0  -10010817.2136
  293. ;              -47120101.12   -47120101.0   19930309.12  15821004.0
  294. ;               15821015.0     19770426.0   19571004.0   19100420.0
  295. ;               19860209.0      3330127.0   -5840528.0)
  296. ;          jl '(2451545.5 2446823.0 2446966.5 2447188.0 2447332.5
  297. ;               2415021.0 2305448.0 2305813.0 2026872.3 1356001.5
  298. ;               1355867.0 1355671.9       0.5       0.0 2449056.5
  299. ;               2299160.0 2299161.0 2443260.0 2436116.0 2418782.0
  300. ;               2446471.0 1842713.0 1507900.0)
  301. ;          eps 0.00005
  302. ;    )
  303. ;
  304. ;    ; Test DTOJ
  305. ;
  306. ;    (setq cjl (mapcar 'dtoj dl)
  307. ;          err (mapcar '- cjl jl))
  308. ;    (mapcar '(lambda (x y z w) (princ (rtos x 2 4)) (princ " ")
  309. ;                               (princ (rtos y 2 12)) (princ " ")
  310. ;                               (princ (rtos z 2 12)) (princ " ")
  311. ;                               (princ w)
  312. ;                               (if (> (abs w) eps) (princ " ** Error **"))
  313. ;                               (terpri))
  314. ;        dl jl cjl err)
  315. ;    (terpri)
  316. ;
  317. ;    ; Test JTOD
  318. ;
  319. ;    (setq cdl (mapcar 'jtod jl)
  320. ;          err (mapcar '- cdl dl))
  321. ;    (mapcar '(lambda (x y z w) (princ (rtos x 2 4)) (princ " ")
  322. ;                               (princ (rtos y 2 12)) (princ " ")
  323. ;                               (princ (rtos z 2 12)) (princ " ")
  324. ;                               (princ w)
  325. ;                               (if (> (abs w) eps) (princ " ** Error **"))
  326. ;                               (terpri))
  327. ;        jl dl cdl err)
  328. ;
  329. ;    ; Test JTOW
  330. ;
  331. ;    (if (or (/= (jtow (dtoj 19540630)) 3)
  332. ;            (/= (jtow (dtoj 15821004)) 4)
  333. ;            (/= (jtow (dtoj 15821015)) 5)
  334. ;        )
  335. ;        (princ "\n** Error in jtow.\n")
  336. ;    )
  337. ;
  338. ;    (princ)
  339. ;)
  340. ;;;
  341. ;;;----------------------------------------------------------------------------
  342. ;;;
  343. ;;; (C:DATE)  --  Implement DATE command to display date/time
  344. ;;;
  345. (defun c:date (/ j c cdate m d y hh mm ss msec)
  346.    (setq cdate (jtod (setq j (getvar "date")))
  347.          c (fix cdate)
  348.          y (/ c 10000)              ; Get year
  349.          m (rem (/ c 100) 100)      ; Ger month
  350.          d (rem c 100)              ; Get day
  351.          c (- cdate (fix cdate))    ; Strip date from date/time
  352.          c (fix (* c 1000000000))   ; Scale time to get HHMMSSmmm integer
  353.          hh (/ c 10000000)          ; Get hours
  354.          mm (rem (/ c 100000) 100)  ; Get minutes
  355.          ss (rem (/ c 1000) 100)    ; Get seconds
  356.          msec (rem c 1000)          ; Get milliseconds
  357.    )
  358.  
  359.    ; Print the day of the week
  360.  
  361.    (princ (nth (jtow j) '("Dom" "Lun" "Mar" "MiΘ" "Jue" "Vie" "Sßb")))
  362.    (princ " ")
  363.  
  364.    ; Print the date.  YYYY/M/D
  365.  
  366.    (princ (strcat (itoa y) "/" (itoa m) "/" (itoa d)))
  367.  
  368.    ; Print the time.  HH:MM:SS.msec
  369.  
  370.    (princ (strcat " " (if (> hh 9) "" "0") (itoa hh)))
  371.    (princ (strcat ":" (if (> mm 9) "" "0") (itoa mm)))
  372.    (princ (strcat ":" (if (> ss 9) "" "0") (itoa ss)))
  373.    (princ (cond ((> msec 99) "."  )
  374.                 ((> msec 9)  ".0" )
  375.                 (T           ".00")
  376.           )
  377.    )
  378.    (princ msec)
  379.    (terpri)
  380.    (princ)
  381. )       
  382.