cal-china.el 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. ;;; cal-china.el --- calendar functions for the Chinese calendar
  2. ;; Copyright (C) 1995, 1997, 2001-2012 Free Software Foundation, Inc.
  3. ;; Author: Edward M. Reingold <reingold@cs.uiuc.edu>
  4. ;; Maintainer: Glenn Morris <rgm@gnu.org>
  5. ;; Keywords: calendar
  6. ;; Human-Keywords: Chinese calendar, calendar, holidays, diary
  7. ;; Package: calendar
  8. ;; This file is part of GNU Emacs.
  9. ;; GNU Emacs is free software: you can redistribute it and/or modify
  10. ;; it under the terms of the GNU General Public License as published by
  11. ;; the Free Software Foundation, either version 3 of the License, or
  12. ;; (at your option) any later version.
  13. ;; GNU Emacs is distributed in the hope that it will be useful,
  14. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. ;; GNU General Public License for more details.
  17. ;; You should have received a copy of the GNU General Public License
  18. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  19. ;;; Commentary:
  20. ;; See calendar.el.
  21. ;; The rules used for the Chinese calendar are those of Baolin Liu
  22. ;; (see L. E. Doggett's article "Calendars" in the Explanatory
  23. ;; Supplement to the Astronomical Almanac, second edition, 1992) for
  24. ;; the calendar as revised at the beginning of the Qing dynasty in
  25. ;; 1644. The nature of the astronomical calculations is such that
  26. ;; precise calculations cannot be made without great expense in time,
  27. ;; so that the calendars produced may not agree perfectly with
  28. ;; published tables--but no two pairs of published tables agree
  29. ;; perfectly either! Liu's rules produce a calendar for 2033 which is
  30. ;; not accepted by all authorities. The date of Chinese New Year is
  31. ;; correct from 1644-2051.
  32. ;; Note to maintainers:
  33. ;; Use `chinese-year-cache-init' every few years to recenter the default
  34. ;; value of `chinese-year-cache'.
  35. ;;; Code:
  36. (require 'calendar)
  37. (require 'lunar) ; lunar-new-moon-on-or-after
  38. ;; solar-date-next-longitude brought in by lunar.
  39. ;;;(require 'solar)
  40. ;; calendar-astro-to-absolute and from-absolute are cal-autoloads.
  41. ;;;(require 'cal-julian)
  42. (defgroup calendar-chinese nil
  43. "Chinese calendar support."
  44. :prefix "calendar-chinese-"
  45. :group 'calendar)
  46. (define-obsolete-variable-alias 'chinese-calendar-time-zone
  47. 'calendar-chinese-time-zone "23.1")
  48. (defcustom calendar-chinese-time-zone
  49. '(if (< year 1928)
  50. (+ 465 (/ 40.0 60.0))
  51. 480)
  52. "Minutes difference between local standard time for Chinese calendar and UTC.
  53. Default is for Beijing. This is an expression in `year' since it changed at
  54. 1928-01-01 00:00:00 from UT+7:45:40 to UT+8."
  55. :type 'sexp
  56. :group 'calendar-chinese)
  57. ;; It gets eval'd.
  58. ;;;###autoload
  59. (put 'calendar-chinese-time-zone 'risky-local-variable t)
  60. ;;;###autoload
  61. (put 'chinese-calendar-time-zone 'risky-local-variable t)
  62. (define-obsolete-variable-alias 'chinese-calendar-location-name
  63. 'calendar-chinese-location-name "23.1")
  64. ;; FIXME unused.
  65. (defcustom calendar-chinese-location-name "Beijing"
  66. "Name of location used for calculation of Chinese calendar."
  67. :type 'string
  68. :group 'calendar-chinese)
  69. (define-obsolete-variable-alias 'chinese-calendar-daylight-time-offset
  70. 'calendar-chinese-daylight-time-offset "23.1")
  71. (defcustom calendar-chinese-daylight-time-offset 0
  72. ;; The correct value is as follows, but the Chinese calendrical
  73. ;; authorities do NOT use DST in determining astronomical events:
  74. ;; 60
  75. "Minutes difference between daylight saving and standard time.
  76. Default is for no daylight saving time."
  77. :type 'integer
  78. :group 'calendar-chinese)
  79. (define-obsolete-variable-alias 'chinese-calendar-standard-time-zone-name
  80. 'calendar-chinese-standard-time-zone-name "23.1")
  81. (defcustom calendar-chinese-standard-time-zone-name
  82. '(if (< year 1928)
  83. "PMT"
  84. "CST")
  85. "Abbreviated name of standard time zone used for Chinese calendar.
  86. This is an expression depending on `year' because it changed
  87. at 1928-01-01 00:00:00 from `PMT' to `CST'."
  88. :type 'sexp
  89. :group 'calendar-chinese)
  90. (define-obsolete-variable-alias 'chinese-calendar-daylight-time-zone-name
  91. 'calendar-chinese-daylight-time-zone-name "23.1")
  92. (defcustom calendar-chinese-daylight-time-zone-name "CDT"
  93. "Abbreviated name of daylight saving time zone used for Chinese calendar."
  94. :type 'string
  95. :group 'calendar-chinese)
  96. (define-obsolete-variable-alias 'chinese-calendar-daylight-savings-starts
  97. 'calendar-chinese-daylight-saving-start "23.1")
  98. (defcustom calendar-chinese-daylight-saving-start nil
  99. ;; The correct value is as follows, but the Chinese calendrical
  100. ;; authorities do NOT use DST in determining astronomical events:
  101. ;; '(cond ((< 1986 year) (calendar-nth-named-day 1 0 4 year 10))
  102. ;; ((= 1986 year) '(5 4 1986))
  103. ;; (t nil))
  104. "Sexp giving the date on which daylight saving time starts.
  105. Default is for no daylight saving time. See documentation of
  106. `calendar-daylight-savings-starts'."
  107. :type 'sexp
  108. :group 'calendar-chinese)
  109. (define-obsolete-variable-alias 'chinese-calendar-daylight-savings-ends
  110. 'calendar-chinese-daylight-saving-end "23.1")
  111. (defcustom calendar-chinese-daylight-saving-end nil
  112. ;; The correct value is as follows, but the Chinese calendrical
  113. ;; authorities do NOT use DST in determining astronomical events:
  114. ;; '(if (<= 1986 year) (calendar-nth-named-day 1 0 9 year 11))
  115. "Sexp giving the date on which daylight saving time ends.
  116. Default is for no daylight saving time. See documentation of
  117. `calendar-daylight-savings-ends'."
  118. :type 'sexp
  119. :group 'calendar-chinese)
  120. (define-obsolete-variable-alias 'chinese-calendar-daylight-savings-starts-time
  121. 'calendar-chinese-daylight-saving-start-time "23.1")
  122. (defcustom calendar-chinese-daylight-saving-start-time 0
  123. "Number of minutes after midnight that daylight saving time starts.
  124. Default is for no daylight saving time."
  125. :type 'integer
  126. :group 'calendar-chinese)
  127. (define-obsolete-variable-alias 'chinese-calendar-daylight-savings-ends-time
  128. 'calendar-chinese-daylight-saving-end-time "23.1")
  129. (defcustom calendar-chinese-daylight-saving-end-time 0
  130. "Number of minutes after midnight that daylight saving time ends.
  131. Default is for no daylight saving time."
  132. :type 'integer
  133. :group 'calendar-chinese)
  134. (define-obsolete-variable-alias 'chinese-calendar-celestial-stem
  135. 'calendar-chinese-celestial-stem "23.1")
  136. (defcustom calendar-chinese-celestial-stem
  137. ["Jia" "Yi" "Bing" "Ding" "Wu" "Ji" "Geng" "Xin" "Ren" "Gui"]
  138. "Prefixes used by `calendar-chinese-sexagesimal-name'."
  139. :group 'calendar-chinese
  140. :type '(vector (string :tag "Jia")
  141. (string :tag "Yi")
  142. (string :tag "Bing")
  143. (string :tag "Ding")
  144. (string :tag "Wu")
  145. (string :tag "Ji")
  146. (string :tag "Geng")
  147. (string :tag "Xin")
  148. (string :tag "Ren")
  149. (string :tag "Gui")))
  150. (define-obsolete-variable-alias 'chinese-calendar-terrestrial-branch
  151. 'calendar-chinese-terrestrial-branch "23.1")
  152. (defcustom calendar-chinese-terrestrial-branch
  153. ["Zi" "Chou" "Yin" "Mao" "Chen" "Si" "Wu" "Wei" "Shen" "You" "Xu" "Hai"]
  154. "Suffixes used by `calendar-chinese-sexagesimal-name'."
  155. :group 'calendar-chinese
  156. :type '(vector (string :tag "Zi")
  157. (string :tag "Chou")
  158. (string :tag "Yin")
  159. (string :tag "Mao")
  160. (string :tag "Chen")
  161. (string :tag "Si")
  162. (string :tag "Wu")
  163. (string :tag "Wei")
  164. (string :tag "Shen")
  165. (string :tag "You")
  166. (string :tag "Xu")
  167. (string :tag "Hai")))
  168. ;;; End of user options.
  169. (defun calendar-chinese-sexagesimal-name (n)
  170. "The N-th name of the Chinese sexagesimal cycle.
  171. N congruent to 1 gives the first name, N congruent to 2 gives the second name,
  172. ..., N congruent to 60 gives the sixtieth name."
  173. (format "%s-%s"
  174. (aref calendar-chinese-celestial-stem (% (1- n) 10))
  175. (aref calendar-chinese-terrestrial-branch (% (1- n) 12))))
  176. (defun calendar-chinese-zodiac-sign-on-or-after (d)
  177. "Absolute date of first new Zodiac sign on or after absolute date D.
  178. The Zodiac signs begin when the sun's longitude is a multiple of 30 degrees."
  179. (let* ((year (calendar-extract-year (calendar-gregorian-from-absolute d)))
  180. (calendar-time-zone (eval calendar-chinese-time-zone)) ; uses year
  181. (calendar-daylight-time-offset
  182. calendar-chinese-daylight-time-offset)
  183. (calendar-standard-time-zone-name
  184. calendar-chinese-standard-time-zone-name)
  185. (calendar-daylight-time-zone-name
  186. calendar-chinese-daylight-time-zone-name)
  187. (calendar-daylight-savings-starts
  188. calendar-chinese-daylight-saving-start)
  189. (calendar-daylight-savings-ends
  190. calendar-chinese-daylight-saving-end)
  191. (calendar-daylight-savings-starts-time
  192. calendar-chinese-daylight-saving-start-time)
  193. (calendar-daylight-savings-ends-time
  194. calendar-chinese-daylight-saving-end-time))
  195. (floor
  196. (calendar-astro-to-absolute
  197. (solar-date-next-longitude (calendar-astro-from-absolute d) 30)))))
  198. (defun calendar-chinese-new-moon-on-or-after (d)
  199. "Absolute date of first new moon on or after absolute date D."
  200. (let* ((year (calendar-extract-year (calendar-gregorian-from-absolute d)))
  201. (calendar-time-zone (eval calendar-chinese-time-zone))
  202. (calendar-daylight-time-offset
  203. calendar-chinese-daylight-time-offset)
  204. (calendar-standard-time-zone-name
  205. calendar-chinese-standard-time-zone-name)
  206. (calendar-daylight-time-zone-name
  207. calendar-chinese-daylight-time-zone-name)
  208. (calendar-daylight-savings-starts
  209. calendar-chinese-daylight-saving-start)
  210. (calendar-daylight-savings-ends
  211. calendar-chinese-daylight-saving-end)
  212. (calendar-daylight-savings-starts-time
  213. calendar-chinese-daylight-saving-start-time)
  214. (calendar-daylight-savings-ends-time
  215. calendar-chinese-daylight-saving-end-time))
  216. (floor
  217. (calendar-astro-to-absolute
  218. (lunar-new-moon-on-or-after (calendar-astro-from-absolute d))))))
  219. (defun calendar-chinese-month-list (start end)
  220. "List of starting dates of Chinese months from START to END."
  221. (if (<= start end)
  222. (let ((new-moon (calendar-chinese-new-moon-on-or-after start)))
  223. (if (<= new-moon end)
  224. (cons new-moon
  225. (calendar-chinese-month-list (1+ new-moon) end))))))
  226. (defun calendar-chinese-number-months (list start)
  227. "Assign month numbers to the lunar months in LIST, starting with START.
  228. Numbers are assigned sequentially, START, START+1, ..., 11, with
  229. half numbers used for leap months. First and last months of list
  230. are never leap months."
  231. (when list
  232. (cons (list start (car list)) ; first month
  233. ;; Remaining months.
  234. (if (zerop (- 12 start (length list)))
  235. ;; List is too short for a leap month.
  236. (calendar-chinese-number-months (cdr list) (1+ start))
  237. (if (and (cddr list) ; at least two more months...
  238. (<= (nth 2 list)
  239. (calendar-chinese-zodiac-sign-on-or-after
  240. (cadr list))))
  241. ;; Next month is a leap month.
  242. (cons (list (+ start 0.5) (cadr list))
  243. (calendar-chinese-number-months (cddr list) (1+ start)))
  244. ;; Next month is not a leap month.
  245. (calendar-chinese-number-months (cdr list) (1+ start)))))))
  246. (defun calendar-chinese-compute-year (y)
  247. "Compute the structure of the Chinese year for Gregorian year Y.
  248. The result is a list of pairs (i d), where month i begins on absolute date d,
  249. of the Chinese months from the Chinese month following the solstice in
  250. Gregorian year Y-1 to the Chinese month of the solstice of Gregorian year Y."
  251. (let* ((next-solstice (calendar-chinese-zodiac-sign-on-or-after
  252. (calendar-absolute-from-gregorian
  253. (list 12 15 y))))
  254. (list (calendar-chinese-month-list
  255. (1+ (calendar-chinese-zodiac-sign-on-or-after
  256. (calendar-absolute-from-gregorian
  257. (list 12 15 (1- y)))))
  258. next-solstice))
  259. (next-sign (calendar-chinese-zodiac-sign-on-or-after (car list))))
  260. (if (= (length list) 12)
  261. ;; No room for a leap month, just number them 12, 1, 2, ..., 11.
  262. (cons (list 12 (car list))
  263. (calendar-chinese-number-months (cdr list) 1))
  264. ;; Now we can assign numbers to the list for y.
  265. ;; The first month or two are special.
  266. (if (or (> (car list) next-sign) (>= next-sign (cadr list)))
  267. ;; First month on list is a leap month, second is not.
  268. (append (list (list 11.5 (car list))
  269. (list 12 (cadr list)))
  270. (calendar-chinese-number-months (cddr list) 1))
  271. ;; First month on list is not a leap month.
  272. (append (list (list 12 (car list)))
  273. (if (>= (calendar-chinese-zodiac-sign-on-or-after (cadr list))
  274. (nth 2 list))
  275. ;; Second month on list is a leap month.
  276. (cons (list 12.5 (cadr list))
  277. (calendar-chinese-number-months (cddr list) 1))
  278. ;; Second month on list is not a leap month.
  279. (calendar-chinese-number-months (cdr list) 1)))))))
  280. (defvar calendar-chinese-year-cache
  281. ;; Maintainers: delete existing value, position point at start of
  282. ;; empty line, then call M-: (calendar-chinese-year-cache-init N)
  283. '((2000 (12 730126) (1 730155) (2 730185) (3 730215) (4 730244) (5 730273)
  284. (6 730303) (7 730332) (8 730361) (9 730391) (10 730420) (11 730450))
  285. (2001 (12 730480) (1 730509) (2 730539) (3 730569) (4 730598) (4.5 730628)
  286. (5 730657) (6 730687) (7 730716) (8 730745) (9 730775) (10 730804)
  287. (11 730834))
  288. (2002 (12 730863) (1 730893) (2 730923) (3 730953) (4 730982) (5 731012)
  289. (6 731041) (7 731071) (8 731100) (9 731129) (10 731159) (11 731188))
  290. (2003 (12 731218) (1 731247) (2 731277) (3 731307) (4 731336) (5 731366)
  291. (6 731396) (7 731425) (8 731455) (9 731484) (10 731513) (11 731543))
  292. (2004 (12 731572) (1 731602) (2 731631) (2.5 731661) (3 731690) (4 731720)
  293. (5 731750) (6 731779) (7 731809) (8 731838) (9 731868) (10 731897)
  294. (11 731927))
  295. (2005 (12 731956) (1 731986) (2 732015) (3 732045) (4 732074) (5 732104)
  296. (6 732133) (7 732163) (8 732193) (9 732222) (10 732252) (11 732281))
  297. (2006 (12 732311) (1 732340) (2 732370) (3 732399) (4 732429) (5 732458)
  298. (6 732488) (7 732517) (7.5 732547) (8 732576) (9 732606) (10 732636)
  299. (11 732665))
  300. (2007 (12 732695) (1 732725) (2 732754) (3 732783) (4 732813) (5 732842)
  301. (6 732871) (7 732901) (8 732930) (9 732960) (10 732990) (11 733020))
  302. (2008 (12 733049) (1 733079) (2 733109) (3 733138) (4 733167) (5 733197)
  303. (6 733226) (7 733255) (8 733285) (9 733314) (10 733344) (11 733374))
  304. (2009 (12 733403) (1 733433) (2 733463) (3 733493) (4 733522) (5 733551)
  305. (5.5 733581) (6 733610) (7 733639) (8 733669) (9 733698) (10 733728)
  306. (11 733757))
  307. (2010 (12 733787) (1 733817) (2 733847) (3 733876) (4 733906) (5 733935)
  308. (6 733965) (7 733994) (8 734023) (9 734053) (10 734082) (11 734112))
  309. (2011 (12 734141) (1 734171) (2 734201) (3 734230) (4 734260) (5 734290)
  310. (6 734319) (7 734349) (8 734378) (9 734407) (10 734437) (11 734466))
  311. (2012 (12 734496) (1 734525) (2 734555) (3 734584) (4 734614) (4.5 734644)
  312. (5 734673) (6 734703) (7 734732) (8 734762) (9 734791) (10 734821)
  313. (11 734850))
  314. (2013 (12 734880) (1 734909) (2 734939) (3 734968) (4 734998) (5 735027)
  315. (6 735057) (7 735087) (8 735116) (9 735146) (10 735175) (11 735205))
  316. (2014 (12 735234) (1 735264) (2 735293) (3 735323) (4 735352) (5 735382)
  317. (6 735411) (7 735441) (8 735470) (9 735500) (9.5 735530) (10 735559)
  318. (11 735589))
  319. (2015 (12 735618) (1 735648) (2 735677) (3 735707) (4 735736) (5 735765)
  320. (6 735795) (7 735824) (8 735854) (9 735884) (10 735914) (11 735943))
  321. (2016 (12 735973) (1 736002) (2 736032) (3 736061) (4 736091) (5 736120)
  322. (6 736149) (7 736179) (8 736208) (9 736238) (10 736268) (11 736297))
  323. (2017 (12 736327) (1 736357) (2 736386) (3 736416) (4 736445) (5 736475)
  324. (6 736504) (6.5 736533) (7 736563) (8 736592) (9 736622) (10 736651)
  325. (11 736681))
  326. (2018 (12 736711) (1 736741) (2 736770) (3 736800) (4 736829) (5 736859)
  327. (6 736888) (7 736917) (8 736947) (9 736976) (10 737006) (11 737035))
  328. (2019 (12 737065) (1 737095) (2 737125) (3 737154) (4 737184) (5 737213)
  329. (6 737243) (7 737272) (8 737301) (9 737331) (10 737360) (11 737389))
  330. (2020 (12 737419) (1 737449) (2 737478) (3 737508) (4 737538) (4.5 737568)
  331. (5 737597) (6 737627) (7 737656) (8 737685) (9 737715) (10 737744)
  332. (11 737774)))
  333. "Alist of Chinese year structures as determined by `chinese-year'.
  334. The default can be nil, but some values are precomputed for efficiency.")
  335. (defun calendar-chinese-year (y)
  336. "The structure of the Chinese year for Gregorian year Y.
  337. The result is a list of pairs (i d), where month i begins on absolute date d,
  338. of the Chinese months from the Chinese month following the solstice in
  339. Gregorian year Y-1 to the Chinese month of the solstice of Gregorian year Y.
  340. The list is cached in `calendar-chinese-year-cache' for further use."
  341. (let ((list (cdr (assoc y calendar-chinese-year-cache))))
  342. (or list
  343. (setq list (calendar-chinese-compute-year y)
  344. calendar-chinese-year-cache (append calendar-chinese-year-cache
  345. (list (cons y list)))))
  346. list))
  347. ;; Maintainer use.
  348. (defun calendar-chinese-year-cache-init (year)
  349. "Insert an initialization value for `calendar-chinese-year-cache' after point.
  350. Computes values for 10 years either side of YEAR."
  351. (setq year (- year 10))
  352. (let (calendar-chinese-year-cache end)
  353. (save-excursion
  354. (insert "'(")
  355. (dotimes (n 21)
  356. (princ (cons year (calendar-chinese-compute-year year))
  357. (current-buffer))
  358. (insert (if (= n 20) ")" "\n"))
  359. (setq year (1+ year)))
  360. (setq end (point)))
  361. (save-excursion
  362. ;; fill-column -/+ 5.
  363. (while (and (< (point) end)
  364. (re-search-forward "^.\\{65,75\\})" end t))
  365. (delete-char 1)
  366. (insert "\n")))
  367. (indent-region (point) end)))
  368. (defun calendar-chinese-to-absolute (date)
  369. "The number of days elapsed between the Gregorian date 12/31/1 BC and DATE.
  370. DATE is a Chinese date (cycle year month day). The Gregorian date
  371. Sunday, December 31, 1 BC is imaginary."
  372. (let* ((cycle (car date))
  373. (year (cadr date))
  374. (month (nth 2 date))
  375. (day (nth 3 date))
  376. (g-year (+ (* (1- cycle) 60) ; years in prior cycles
  377. (1- year) ; prior years this cycle
  378. -2636))) ; years before absolute date 0
  379. (+ (1- day) ; prior days this month
  380. (cadr ; absolute date of start of this month
  381. (assoc month (append (memq (assoc 1 (calendar-chinese-year g-year))
  382. (calendar-chinese-year g-year))
  383. (calendar-chinese-year (1+ g-year))))))))
  384. (define-obsolete-function-alias 'calendar-absolute-from-chinese
  385. 'calendar-chinese-to-absolute "23.1")
  386. (defun calendar-chinese-from-absolute (date)
  387. "Compute Chinese date (cycle year month day) corresponding to absolute DATE.
  388. The absolute date is the number of days elapsed since the (imaginary)
  389. Gregorian date Sunday, December 31, 1 BC."
  390. (let* ((g-year (calendar-extract-year
  391. (calendar-gregorian-from-absolute date)))
  392. (c-year (+ g-year 2695))
  393. (list (append (calendar-chinese-year (1- g-year))
  394. (calendar-chinese-year g-year)
  395. (calendar-chinese-year (1+ g-year)))))
  396. (while (<= (cadr (cadr list)) date)
  397. ;; The first month on the list is in Chinese year c-year.
  398. ;; Date is on or after start of second month on list...
  399. (if (= 1 (caar (cdr list)))
  400. ;; Second month on list is a new Chinese year...
  401. (setq c-year (1+ c-year)))
  402. ;; ...so first month on list is of no interest.
  403. (setq list (cdr list)))
  404. (list (/ (1- c-year) 60)
  405. ;; Remainder of c-year/60 with 60 instead of 0.
  406. (1+ (mod (1- c-year) 60))
  407. (caar list)
  408. (1+ (- date (cadr (car list)))))))
  409. ;; Bound in calendar-generate.
  410. (defvar displayed-month)
  411. (defvar displayed-year)
  412. ;;;###holiday-autoload
  413. (defun holiday-chinese-new-year ()
  414. "Date of Chinese New Year, if visible in calendar.
  415. Returns (((MONTH DAY YEAR) TEXT)), where the date is Gregorian."
  416. (let ((m displayed-month)
  417. (y displayed-year)
  418. chinese-new-year)
  419. ;; In the Gregorian calendar, CNY falls between Jan 21 and Feb 20.
  420. ;; Jan is visible if displayed-month = 12, 1, 2; Feb if d-m = 1, 2, 3.
  421. ;; If we shift the calendar forward one month, we can do a
  422. ;; one-sided test, namely: d-m <= 4 means CNY might be visible.
  423. (calendar-increment-month m y 1) ; shift forward a month
  424. (and (< m 5)
  425. (calendar-date-is-visible-p
  426. (setq chinese-new-year
  427. (calendar-gregorian-from-absolute
  428. (cadr (assoc 1 (calendar-chinese-year y))))))
  429. (list
  430. (list chinese-new-year
  431. (format "Chinese New Year (%s)"
  432. (calendar-chinese-sexagesimal-name (+ y 57))))))))
  433. ;;;###holiday-autoload
  434. (defun holiday-chinese-qingming ()
  435. "Date of Chinese Qingming Festival, if visible in calendar.
  436. Returns (((MONTH DAY YEAR) TEXT)), where the date is Gregorian."
  437. (when (memq displayed-month '(3 4 5)) ; is April visible?
  438. (list (list (calendar-gregorian-from-absolute
  439. ;; 15 days after Vernal Equinox.
  440. (+ 15
  441. (calendar-chinese-zodiac-sign-on-or-after
  442. (calendar-absolute-from-gregorian
  443. (list 3 15 displayed-year)))))
  444. "Qingming Festival"))))
  445. ;;;###holiday-autoload
  446. (defun holiday-chinese-winter-solstice ()
  447. "Date of Chinese winter solstice, if visible in calendar.
  448. Returns (((MONTH DAY YEAR) TEXT)), where the date is Gregorian."
  449. (when (memq displayed-month '(11 12 1)) ; is December visible?
  450. (list (list (calendar-gregorian-from-absolute
  451. (calendar-chinese-zodiac-sign-on-or-after
  452. (calendar-absolute-from-gregorian
  453. (list 12 15 (if (eq displayed-month 1)
  454. (1- displayed-year)
  455. displayed-year)))))
  456. "Winter Solstice Festival"))))
  457. ;;;###holiday-autoload
  458. (defun holiday-chinese (month day string)
  459. "Holiday on Chinese MONTH, DAY called STRING.
  460. If MONTH, DAY (Chinese) is visible, returns the corresponding
  461. Gregorian date as the list (((month day year) STRING)).
  462. Returns nil if it is not visible in the current calendar window."
  463. (let ((date
  464. (calendar-gregorian-from-absolute
  465. ;; A basic optimization. Chinese year can only change if
  466. ;; Jan or Feb are visible. FIXME can we do more?
  467. (if (memq displayed-month '(12 1 2 3))
  468. ;; This is calendar-nongregorian-visible-p adapted for
  469. ;; the form of chinese dates: (cycle year month day) as
  470. ;; opposed to (month day year).
  471. (let* ((m1 displayed-month)
  472. (y1 displayed-year)
  473. (m2 displayed-month)
  474. (y2 displayed-year)
  475. ;; Absolute date of first/last dates in calendar window.
  476. (start-date (progn
  477. (calendar-increment-month m1 y1 -1)
  478. (calendar-absolute-from-gregorian
  479. (list m1 1 y1))))
  480. (end-date (progn
  481. (calendar-increment-month m2 y2 1)
  482. (calendar-absolute-from-gregorian
  483. (list m2 (calendar-last-day-of-month m2 y2)
  484. y2))))
  485. ;; Local date of first/last date in calendar window.
  486. (local-start (calendar-chinese-from-absolute start-date))
  487. (local-end (calendar-chinese-from-absolute end-date))
  488. ;; When Chinese New Year is visible on the far
  489. ;; right of the calendar, what is the earliest
  490. ;; Chinese month in the previous year that might
  491. ;; still visible? This test doesn't have to be precise.
  492. (local (if (< month 10) local-end local-start))
  493. (cycle (car local))
  494. (year (cadr local)))
  495. (calendar-chinese-to-absolute (list cycle year month day)))
  496. ;; Simple form for when new years are not visible.
  497. (+ (cadr (assoc month (calendar-chinese-year displayed-year)))
  498. (1- day))))))
  499. (if (calendar-date-is-visible-p date)
  500. (list (list date string)))))
  501. ;;;###cal-autoload
  502. (defun calendar-chinese-date-string (&optional date)
  503. "String of Chinese date of Gregorian DATE.
  504. Defaults to today's date if DATE is not given."
  505. (let* ((a-date (calendar-absolute-from-gregorian
  506. (or date (calendar-current-date))))
  507. (c-date (calendar-chinese-from-absolute a-date))
  508. (cycle (car c-date))
  509. (year (cadr c-date))
  510. (month (nth 2 c-date))
  511. (day (nth 3 c-date))
  512. (this-month (calendar-chinese-to-absolute
  513. (list cycle year month 1)))
  514. (next-month (calendar-chinese-to-absolute
  515. (list (if (= year 60) (1+ cycle) cycle)
  516. (if (= (floor month) 12) (1+ year) year)
  517. ;; Remainder of (1+(floor month))/12, with
  518. ;; 12 instead of 0.
  519. (1+ (mod (floor month) 12))
  520. 1))))
  521. (format "Cycle %s, year %s (%s), %smonth %s%s, day %s (%s)"
  522. cycle
  523. year (calendar-chinese-sexagesimal-name year)
  524. (if (not (integerp month))
  525. "second "
  526. (if (< 30 (- next-month this-month))
  527. "first "
  528. ""))
  529. (floor month)
  530. (if (integerp month)
  531. (format " (%s)" (calendar-chinese-sexagesimal-name
  532. (+ (* 12 year) month 50)))
  533. "")
  534. day (calendar-chinese-sexagesimal-name (+ a-date 15)))))
  535. ;;;###cal-autoload
  536. (defun calendar-chinese-print-date ()
  537. "Show the Chinese date equivalents of date."
  538. (interactive)
  539. (message "Computing Chinese date...")
  540. (message "Chinese date: %s"
  541. (calendar-chinese-date-string (calendar-cursor-to-date t))))
  542. (define-obsolete-function-alias 'calendar-print-chinese-date
  543. 'calendar-chinese-print-date "23.1")
  544. (defun calendar-chinese-months-to-alist (l)
  545. "Make list of months L into an assoc list."
  546. (and l (car l)
  547. (if (and (cdr l) (cadr l))
  548. (if (= (car l) (floor (cadr l)))
  549. (append
  550. (list (cons (format "%s (first)" (car l)) (car l))
  551. (cons (format "%s (second)" (car l)) (cadr l)))
  552. (calendar-chinese-months-to-alist (cddr l)))
  553. (append
  554. (list (cons (number-to-string (car l)) (car l)))
  555. (calendar-chinese-months-to-alist (cdr l))))
  556. (list (cons (number-to-string (car l)) (car l))))))
  557. (defun calendar-chinese-months (c y)
  558. "A list of the months in cycle C, year Y of the Chinese calendar."
  559. (memq 1 (append
  560. (mapcar (lambda (x)
  561. (car x))
  562. (calendar-chinese-year (calendar-extract-year
  563. (calendar-gregorian-from-absolute
  564. (calendar-chinese-to-absolute
  565. (list c y 1 1))))))
  566. (mapcar (lambda (x)
  567. (if (> (car x) 11) (car x)))
  568. (calendar-chinese-year (calendar-extract-year
  569. (calendar-gregorian-from-absolute
  570. (calendar-chinese-to-absolute
  571. (list (if (= y 60) (1+ c) c)
  572. (if (= y 60) 1 y)
  573. 1 1)))))))))
  574. ;;;###cal-autoload
  575. (defun calendar-chinese-goto-date (date &optional noecho)
  576. "Move cursor to Chinese date DATE.
  577. Echo Chinese date unless NOECHO is non-nil."
  578. (interactive
  579. (let* ((c (calendar-chinese-from-absolute
  580. (calendar-absolute-from-gregorian (calendar-current-date))))
  581. (cycle (calendar-read
  582. "Chinese calendar cycle number (>44): "
  583. (lambda (x) (> x 44))
  584. (number-to-string (car c))))
  585. (year (calendar-read
  586. "Year in Chinese cycle (1..60): "
  587. (lambda (x) (and (<= 1 x) (<= x 60)))
  588. (number-to-string (cadr c))))
  589. (month-list (calendar-chinese-months-to-alist
  590. (calendar-chinese-months cycle year)))
  591. (month (cdr (assoc
  592. (completing-read "Chinese calendar month: "
  593. month-list nil t)
  594. month-list)))
  595. (last (if (= month
  596. (nth 2
  597. (calendar-chinese-from-absolute
  598. (+ 29
  599. (calendar-chinese-to-absolute
  600. (list cycle year month 1))))))
  601. 30
  602. 29))
  603. (day (calendar-read
  604. (format "Chinese calendar day (1-%d): " last)
  605. (lambda (x) (and (<= 1 x) (<= x last))))))
  606. (list (list cycle year month day))))
  607. (calendar-goto-date (calendar-gregorian-from-absolute
  608. (calendar-chinese-to-absolute date)))
  609. (or noecho (calendar-chinese-print-date)))
  610. (define-obsolete-function-alias 'calendar-goto-chinese-date
  611. 'calendar-chinese-goto-date "23.1")
  612. (defvar date)
  613. ;; To be called from diary-list-sexp-entries, where DATE is bound.
  614. ;;;###diary-autoload
  615. (defun diary-chinese-date ()
  616. "Chinese calendar equivalent of date diary entry."
  617. (format "Chinese date: %s" (calendar-chinese-date-string date)))
  618. (provide 'cal-china)
  619. ;;; cal-china.el ends here