Calendrica
The Millennium Edition

by Nachum Dershowitz and Edward M. Reingold

Mathematica translation version 2.0 by Robert C. McNally <calendrica@dangerousgames.com>

Calendrica is a package for generalized manipulation and conversion of dates through various modern and historical calendars. It is based on the work of Nachum Dershowitz and Edward M. Reingold in their book Calendrical Calculations, the Millennium Edition, published by Cambridge University Press.

Version Notes

2.0 (20 March 2000)

Calendrica 2.0 has beeen completely updated to conform with Calendrical Calculations, the Millennium Edition. This includes such additions as support for Egyptian, Armenian, Roman, Islamic Observational, Arithmetic Persian, and Balinese calendars, as well as many improvements and bug fixes over the previous version. Most functions are compatible with Calendrica 1.0, but compatibilty is not guaranteed.

License

;;;; The Functions (code, comments, and definitions) contained in this
;;;; file (the "Program") were written by Edward M. Reingold and Nachum
;;;; Dershowitz (the "Authors"), who retain all rights to them except as
;;;; granted in the License and subject to the warranty and liability
;;;; limitations below.  These Functions are explained in the Authors'
;;;; book, "Calendrical Calculations: The Millennium Edition" (Cambridge
;;;; University Press, 2001), and are subject to an international
;;;; copyright and a Patent Pending on certain functions.
;;;;
;;;; The Authors' public service intent is more liberal than suggested
;;;; by the License below, as are their licensing policies for otherwise
;;;; nonallowed uses such as--without limitation--those in commercial,
;;;; web-site, and large-scale academic contexts.  Please see the
;;;; web-site
;;;;
;;;;     http://www.calendarists.com
;;;;
;;;; for all uses not authorized below; in case there is cause for doubt
;;;; about whether a use you contemplate is authorized, please contact
;;;; the Authors (e-mail: reingold@cs.uiuc.edu).  For commercial
;;;; licensing information, contact the first author at the Department
;;;; of Computer Science, 1304 West Springfield Avenue, University of
;;;; Illinois at Urbana-Champaign, Urbana, IL 61801-2987, USA.
;;;;
;;;; 1. LICENSE.  The Authors grant you a license for personal use only.
;;;; This means that for strictly personal use you may copy and use the
;;;; code, and keep a backup or archival copy also.  Any other uses,
;;;; including without limitation, allowing the code or its output to be
;;;; accessed, used, or available to others, is not permitted.
;;;;
;;;; 2. WARRANTY.
;;;;
;;;; (a) THE AUTHORS PROVIDE NO WARRANTIES OF ANY KIND, EITHER
;;;;     EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITING THE
;;;;     GENERALITY OF THE FOREGOING, ANY IMPLIED WARRANTY OF
;;;;     MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
;;;;
;;;; (b) THE AUTHORS SHALL NOT BE LIABLE TO YOU OR ANY THIRD PARTIES
;;;;     FOR DAMAGES OF ANY KIND, INCLUDING WITHOUT LIMITATION, ANY LOST
;;;;     PROFITS, LOST SAVINGS, OR ANY OTHER INCIDENTAL OR CONSEQUENTIAL
;;;;     DAMAGES ARISING OUT OF OR RELATED TO THE USE, INABILITY TO USE,
;;;;     OR INACCURACY OF CALCULATIONS, OF THE CODE AND FUNCTIONS
;;;;     CONTAINED HEREIN, OR THE BREACH OF ANY EXPRESS OR IMPLIED
;;;;     WARRANTY, EVEN IF THE AUTHORS OR PUBLISHER HAVE BEEN ADVISED OF
;;;;     THE POSSIBILITY OF THOSE DAMAGES.
;;;;
;;;; (c) THE FOREGOING WARRANTY MAY GIVE YOU SPECIFIC LEGAL
;;;;     RIGHTS WHICH MAY VARY FROM STATE TO STATE IN THE U.S.A.
;;;;
;;;; 3. LIMITATION OF LICENSEE REMEDIES.  You acknowledge and agree that
;;;; your exclusive remedy (in law or in equity), and Authors' entire
;;;; liability with respect to the material herein, for any breach of
;;;; representation or for any inaccuracy shall be a refund of the license
;;;; fee or service and handling charge which you paid the Authors, if any.
;;;;
;;;; SOME STATES IN THE U.S.A. DO NOT ALLOW THE EXCLUSION OR LIMITATION OF
;;;; LIABILITY FOR INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE
;;;; EXCLUSIONS OR LIMITATION MAY NOT APPLY TO YOU.
;;;;
;;;; 4. DISCLAIMER.  Except as expressly set forth above, the Authors:
;;;;
;;;;   (a) make no other warranties with respect to the material in the
;;;;   Program and expressly disclaim any others;
;;;;
;;;;   (b) do not warrant that the material contained in the Program will
;;;;   meet your requirements or that their operation shall be
;;;;   uninterrupted or error-free;
;;;;
;;;;   (c) license this material on an "as is" basis, and the entire risk
;;;;   as to the quality, accuracy, and performance of the Program is
;;;;   yours, should the code prove defective (except as expressly
;;;;   warranted herein).  You alone assume the entire cost of all
;;;;   necessary corrections.
;;;;
;;;; Sample values for the functions (useful for debugging) are given in
;;;; Appendix C of the book and on the accompanying CD.

Naming Conventions

The conversion between most names in the Lisp implementation and the Mathematica implementation is straightforward: intercapitalization is substituted for hyphenated names, and predicates end with "Q" instead of "?". For example, no-major-solar-term? becomes NoMajorSolarTermQ[].

The only major changes are:

1) Functions which convert to and from fixed dates have overloaded names. For example, fixed-from-chinese becomes ToFixed[] which takes a Chinese date, and chinese-from-fixed becomes Chinese[] which takes an integer.

2) Components of dates are accessed by functions such as CYear[] which determine the position of the component from the type of the date, and replace Lisp functions such as standard-year.

3) Certain internal functions such as sum have been renamed (MSum[], in this case) to avoid conflicts with already-established Mathematica names.

Getting Started

Once you have placed the file "Calendrica.m" in the root of your Mathematica packages hierarchy, this loads it for use:

<< Calendrica`

Looking at Global Symbols

This shows you all the symbols which Calendrica exports to the global namespace:

?Calendrica`*

Prefixing the symbol with ? gives general information on that symbol

?Gregorian

?Sunday

Constructing a Date

This shows you all the calendars which Calendrica supports:

Calendars[]

This displays the components in a date on a given calendar. Component names are prefixed with 'C':

Gregorian[]

To construct a date, create a Mathematica expression whose head is the name of the calendar, and whose body consists of each component in order:

Gregorian[1965,  5, 15]

Calendrica formats the output for easy reading, but keeps the internal structure.

% // FullForm

You can use symbolic constants for the standard months and weekdays. Make sure you put empty brackets after all symbolic constants.:

May

May[]

Gregorian[1965,  May[], 15]

You can retrieve components of calendar dates by name, regardless of their position in the date:

CYear[Gregorian[1965,  May[], 15]]

HinduLunar[]

CYear[HinduLunar[2022,  2, False, 15, False]]

Converting to Fixed Dates

Any calendar date can be converted to a fixed (R.D.) date by passing the calendar date to the routine ToFixed[]:

ToFixed[Gregorian[1965,  May[], 15]]

Converting to Calendar Dates

Any fixed date can be converted into any calendar by passing the fixed date to the routine which has the same name as the calendar:

Gregorian[717471]

Chinese[717471]

Note this is not the same as constructing a date from its components (described above). In this case, you are passing a single integer; in the previous case, you are passing a list of date components.

Converting Between Calendars

To convert a date in one calendar to another calendar in a single step, use the ConvertDateTo[] routine:

ConvertDateTo[Gregorian[1965, May[], 15], HinduLunar]

This converts the result of the previous conversion back to the Gregorian calendar:

ConvertDateTo[%, Gregorian]

Here is a date converted to all available calendars.

Map[List[#, ConvertDateTo[Gregorian[1965, May[], 15], #]] &, 
        Calendars[]] // ColumnForm

({{{Egyptian, "\!\(14\) Thoth \!\(2714\)"}}, {{Armenian, "\!\(14\) Mareri \!\(1414\)"}}, {{Gregorian, "Saturday, \!\(15\) May \!\(1965\)"}}, {{Julian, "\!\(2\) May \!\(1965\) C.E."}}, {{Roman, "ante diem VI Nones May, \!\(1965\) C.E."}}, {{Coptic, "\!\(7\) Bashans \!\(1681\) A.M."}}, {{Ethiopic, "Kidamme, \!\(7\) Genbot \!\(1957\) E.E."}}, {{ISO, "Saturday, Week \!\(19\), \!\(1965\)"}}, {\({Islamic, "yaum as-sabt, 14 Muharram 1385 A.H."}\)}, {{Hebrew, "yom shabbat, \!\(13\) Iyyar \!\(5725\) A.M."}}, {{OldHinduSolar, "Sanivara, \!\(30\) Mesha \!\(5066\) \
K.Y."}}, {{OldHinduLunar, "Sanivara, \!\(15\) Vaisakha \!\(5066\) \
K.Y."}}, {{MayanLongCount, "\!\(12\).\!\(17\).\!\(11\).\!\(12\).\!\(13\)\
"}}, {{MayanHaab, "\!\(11\) Uo"}}, {{MayanTzolkin, "\!\(11\) Ben"}}, {{Bahai, "Istiqlal, Mulk Jamal, Jad of Vahid \!\(7\), \
Kull-i-Shay \!\(1\) B.E."}}, {{ArithmeticPersian,"\!\(25\) Ordibehesht \!\(1344\) A.P."}}, {{ModifiedFrench,"Decade III, Quintidi de Floreal de l'Annee \!\(173\) de la Revolution"}}, {{Balinese, "Menga Kajeng Sri Paing Urukung Saniscara Ludra \
Dadi Dewa (Ukir)"}}, {{ObservationalIslamic,"yaum as-sabt, \!\(14\) Muharram \!\(1385\) A.H."}}, {{Persian, "\!\(25\) Ordibehesht \!\(1344\) A.P."}}, {{FutureBahai,"Istijlal, Sultan Jamal, Jad of Vahid \!\(7\), Kull-i-Shay \!\(1\) B.E."}}, {{French, "Decade III, Quintidi de Floreal de l'Annee \!\(173\) \
de la Revolution"}}, {{Chinese, "cycle \!\(77\), year Yi-Si, month \!\(4\), day \
\!\(15\)"}}, {{HinduLunar, "Sanivara, \!\(15\) Vaisakha \!\(2022\) \
V.E."}}, {{HinduSolar, "Sanivara, \!\(2\) Vrishabha \!\(1887\) \
S.E."}}})

Converting Times of Day

?TimeOfDay

TimeOfDay[]

This represents 3:30:10 AM:

TimeOfDay[3, 30, 10]

To convert the last expression to a fraction of a day:

ToMoment[%]

And this converts a fixed date which may include a fraction of a day to a time of day:

TimeOfDay[%]

The Current Date and Time

?CurrentDate

Gregorian[CurrentDate[]]

?CurrentMoment

TimeOfDay[CurrentMoment[]]

The following won't work because calendar conversions only work on integers.

Gregorian[CurrentMoment[]]

This will work.

Gregorian[Floor[CurrentMoment[]]]

Locations

A number of functions take a location on the Earth's surface as an argument.

?Location

Location[]

?CZone

Locations needed by the various calendars are built-in, along with a couple of sample Locations that have nothing to do with the calendrs.

LosAngeles[]

Calendrica formats the output for easy reading, but keeps the internal structure.

% // InputForm

Urbana[]

Jerusalem[]

Here is a calculation involving a Location.

?Sunrise

?LocalFromStandard

Sunrise[ToFixed[Gregorian[2000, 1, 1]], Jerusalem[]] // 
      InputForm

LocalFromStandard[%, Jerusalem[]] // InputForm

TimeOfDay[%]

Validating Data Types

Each structured data type has a corresponding function that validates it.

?Gregorian

?GregorianQ

Gregorian[]

GregorianQ[Gregorian[1965, 5, 15]]

GregorianQ[Gregorian[1965, 5, 15, 1]]

GregorianQ[Roman[1965, 5, 15]]

GregorianQ[Gregorian[1965, True, 15]]

?LocationQ

?TimeOfDayQ

Accessing Non-Global Symbols

Previous versions of Calendrica only exported a subset of all routines to the global namespace, requiring manipulation of the Mathematica context to access some routines. This version exports almost every routine to the global namespace, except for minor housekeeping functions, and data structures used internally.

Test Suite

Calendrica includes a test suite to help ensure the accuracy of its algorithms. For each calendar, the test suite converts a list of 33 fixed dates to calendar dates and compares its results with a table of calendar dates transcribed by hand from Calendrical Calculations. It then converts the list of calendar dates in the table back to fixed dates, and compares its results with the table of fixed dates. If any discrepancies are found, a list including the fixed dates and calendar dates from the tables is generated and printed instead of "OK". The test suite can take a number of minutes to run:

CalendricaTest[]