The kalendarium Package
Andrew Smith
∗Version v1.0 — Released a.d. XV Kal. Iul. MMDCCLXXI a.u.c.
Abstract
Thekalendariumpackage provides several macros with which to print dates in clas- sical Latin given days on the Julian or Gregorian calendars, using the same syntax used by ancient Roman authors. The format of these dates may be customised either in the package options or on a per-command basis; these options also allow for the generation of date strings according to different eras of the Classical period.
1 Prerequisites
kalendariumis written in LATEX3, and thus requiresxparseand the LATEX3 kernel to be installed. Furthermore, in order to parse key-value package and command options, the packagel3keys2eis also required.
2 Usage and configuration
Most simply,kalendariummay be imported with default formatting in the usual fashion, with\usepackage{kalendarium}. Global formatting options may be set on import via key-value pairs; for example, to display all dates with no abbreviation, numbers fully written out in Latin, and years calculatedab urbe condita, this import string may be used:
\usepackage[abbreviate=false,dayfmt=latin,era=auc]{kalendarium}
A complete list of formatting options may be found in Section??.
3 The Roman calendar
Thekalendariumpackage provides utilities to format dates according to its namesake, the ancient Romankalendarium.1 While in early Rome, the calendar was subject to great variation at the discretion of the high priests of thereligio Romana, this package implements the more standardised version used after the Julian reforms of 46 bce. In addition, it provides formatting options to display dates according to even more modern standards, such as writing yearsanno Dominiinstead ofab urbe conditaand avoiding thebissextum Februarium. This section describes the basics of thekalendariumand some historical variations thereupon.
3.1 Roman months
Prior to the Roman Republic, a ten-month calendar ascribed to Romulus is reported to have been used. Since this calendar had already fallen out of use by the Classical period and it required the insertion of fifty-one intercalary days between and during months—sometimes methodically, but often at random—utilities for writing dates according to the Romulan calendar are not provided by this package.
Following the Tarquin expulsion, this legendary calendar was replaced with a twelve-month system with an intercalary month inserted between theTerminalia andRegifugium(23 and 24 February, a newly-added month).2 While this iteration of the calendar resolved many of the issues present in the Romulan calendar, it still did not accurately portray the length of a year, having only 354 days per year, and the intercalary month was still somewhat unstable.
In 46 bce, the victorious pontifex maximusJulius Caesar conducted further calendrical reforms. The thus-named Julian calendar distributed the days of the intercalary month amongst the other months of the year, instituting the month lengths still used today. Furthermore, to compensate for the fact that the length of a year cannot be described in a perfect integer number of days, Caesar’s calendar inserted an intercalary day (bissextum) between theTerminaliaandRegifugiumevery four years.3 Thus, a somewhat modern calendar was achieved:
Days in month
Month Romulan Republican Julian
March Martius 31 31 31
April Aprilis 30 29 30
May Maius 31 31 31
June Iunius 30 29 30
July Quintilis 31 31 31
August Sextilis 30 29 31
September September 30 29 30
October October 31 31 31
November November 30 29 30
December December 30 29 31
January Ianuarius 29 31
February Februarius 28 28or29
Intercalary Mercedonius 51 22/23 None
Following the assassination of Julius Caesar in 44 bce, Mark Antony renamed the month of Quintilis to Iulius(July) in honour of the late emperor. Furthermore, following the death of Augustus, the monthSextiliswas renamedAugustus(August) according to a referendum in 8 bce.4
As a further refinement, in the year 1582 ce, Pope Gregory XIII added additional criteria for the calculation ofbissexta, or leap years: an additional day was to be added to the month of February if the year was divisible by 4, but not if it was divisible by 100, yet still if it was divisible by 400.5 Adopted throughout nearly all of the
2Plutarch,Parallel Lives18.
3Macrobius,SaturnaliaI.14.
4Macrobius,SaturnaliaI.12.
5Pope Gregory XIII,Inter gravissimas.
modern world, this Gregorian calendar is used in all Western nations; nevertheless, for historical compatibility, this package provides support for converting dates on both the Julian and Gregorian calendars.
3.2 Roman days
Each Roman month was ascribed three named days: the Kalends, the Nones, and the Ides. The Kalends (Kalendae,Kal.) fell on the first day of every month, without variation. The Ides (Idus, Id.) fell on the fifteenth day of “full” months—months which comprised 31 days on the Romulan calendar, thus March, May, July/Quintilis, and October—and the thirteenth day of the other “hollow” months. Finally, the Nones (Nonae,Non.) fell eight (nine inclusively) days before the Ides, on the seventh day of full months and the fifth day of hollow ones.
Roman days were counted inclusively, meaning that the current day was taken into consideration when calculating the number of days between two dates. Thus, a Roman would state that 3 January is not two days after 1 January, but three. This system of inclusive counting appears throughout theKalendarium, in which dates are expressed in relation to the next closest Nones or Ides of the current month, or the Kalends of the following month. An exception occurs for the day immediately preceding one of these named days, which is referenced only aspridie. The conjugate term for the day following,postridie, does not appear in the Roman calendar.
3.3 Roman weeks
During the monarchic and republican periods, Roman weeks were delineated in eight-day cycles, callednundina(sg.nundinum) on account of their inclusive counting of calendar days. Under this nundinal system, the days of the week were assigned letters A–H, with public markets and festivals occurring on thenundinaeand not again for the next eight days. These market-days acted as a form of weekend for Roman workers, with farmers breaking from their work to travel into the city, sell their wares, and buy provisions to last through the nextnundinum.6
In the early imperial period, the nundinal cycle was replaced by the seven-day week (hebdomas), influenced by the influx of eastern religion and philosophy to the western Roman empire. While these hebdomadal days continued to be assigned letters A–G, they were also named after pagan gods and goddesses in the fashion of the Greeks:
Modern Latin Namesake
Sunday dies Solis Sol (the Sun) Monday dies Lunae $ Luna (the Moon) Tuesday dies Martis ♂ Mars
Wednesday dies Mercurii ' Mercury
Thursday dies Iovis X Jupiter (gen.Iovis) Friday dies Veneris ♀ Venus (gen.Veneris) Saturday dies Saturni Y Saturn
Like many other facets of the Roman calendar, these pagan references survived the Christianisation of Rome and continue to appear in the lexica of the modern Romance languages.
3.4 Roman years
Methods used to refer to specific years on the Roman calendar have varied throughout history, beginning with regnal references to the acting king, ordinary consuls, or Diocletian Indiction. While not ubiquitous in Classical texts, theab urbe condita(auc,
“from the founding of the city (of Rome)”) reckoning, which measures dates in terms of their distance from the legendary founding of Rome in 753 bce counted inclusively, has been widely accepted amongst classicists. In this era, the year 753 bce would be rendered 1 auc, and 2018 ce would be 2771 auc (2018 + 753).
In 525 ce, the monk Dionysius Exiguus devised theanno Domini(ad, “in the year of the Lord”) era, which measures years non-inclusively after the birth of Jesus of Nazareth.7 To represent dates before this event, the eraante Christum(ac, “before (the Nativity of) Christ”) was popularised by theologian Dionysius Petavius in 1627 ce.8 These eras are still frequently used in the modern Gregorian calendar, although the non-sectarian Common Era (ce) replacements have become somewhat common.
Furthermore, the phraseanno Dominiis sometimes shortened to onlyanno(a).
3.5 Latin date syntax
The syntax used in Latin date expressions is rather peculiar, albeit almost entirely formulaic. Unlike in many modern languages, the names of months were not consid- ered to be nouns, but were adjectives, requiring agreement with their antecedents;
additionally, certain phrases were fossilised to the point that they began to be used in expressions that would otherwise be considered ungrammatical.
Dates on the named days of each month, which were always plural, were expressed independently using the ablative case of time when (“on the. . . ”). Thus, they would appear asKalendis Februariis,Nonis Septembribus,Idibus Iuniis, etc. While this syntax was common for all date expressions in early Latin, Classical authors often opted for another approach for non-named days.
Dates that did not fall on the Kalends, Nones, or Ides were expressed in terms of their relation to the next named day. Thus, a date after the Kalends of a month but before the Nones would be named by the number of days, counted inclusively, until the Nones; a date after the Nones but before the Ides, by the days until the Ides; and a date after the Ides, by the days until the Kalends of the following month. These numbers of days were often preceded by the expressionante diem(a.d.) and followed by their respective named day and month in the accusative case, plural. An exception to this format occurred for days immediately preceding a named day, which were expressed aspridie(prid.), then the named day and month in the accusative plural.
A further exception occurred for the month of February in leap years. Leap days were considered to be a single day under Roman law, and were treated as such when counting days until the next Kalends. When a leap day was inserted into the month, it was known as thebissextumand writtenante diem bis VI Kalendas Martias; the normal day five days prior to the end of the month was still writtenante diem VI Kalendas Martias.
Counted numbers of days were often written with Roman numerals, as above;
however, they were sometimes written out as full ordinal numbers in the accusative case, masculine singular, in agreement withdiem. For further elucidation, some months are written in full on the following page.
7Dionysius Exiguus, Easter tables.
8Dionysius Petavius (Denis Péteau),De doctrina temporum.
January February Full Hollow
Day Full Latin Abbreviated Regular year Leap year March April
1 Kalendis Ianuariis Kal. Ian. Kal. Feb. Kal. Feb. Kal. Mar. Kal. Apr.
2 ante diem quartum Nonas Ianuarias a.d. IV Non. Ian. a.d. IV Non. Feb. a.d. IV Non. Feb. a.d. VI Non. Mar. a.d. IV Non. Apr.
3 ante diem tertium Nonas Ianuarias a.d. III Non. Ian. a.d. III Non. Feb. a.d. III Non. Feb. a.d. V Non. Mar. a.d. III Non. Apr.
4 pridie Nonas Ianuarias prid. Non. Ian. prid. Non. Feb. prid. Non. Feb. a.d. IV Non. Mar. prid. Non. Apr.
5 Nonis Ianuariis Non. Ian. Non. Feb. Non. Feb. a.d. III Non. Mar. Non. Apr.
6 ante diem octavum Idus Ianuarias a.d. VIII Id. Ian. a.d. VIII Id. Feb. a.d. VIII Id. Feb. prid. Non. Mar. a.d. VIII Id. Apr.
7 ante diem septimum Idus Ianuarias a.d. VII Id. Ian. a.d. VII Id. Feb. a.d. VII Id. Feb. Non. Mar. a.d. VII Id. Apr.
8 ante diem sextum Idus Ianuarias a.d. VI Id. Ian. a.d. VI Id. Feb. a.d. VI Id. Feb. a.d. VIII Id. Mar. a.d. VI Id. Apr.
9 ante diem quintum Idus Ianuarias a.d. V Id. Ian. a.d. V Id. Feb. a.d. V Id. Feb. a.d. VII Id. Mar. a.d. V Id. Apr.
10 ante diem quartum Idus Ianuarias a.d. IV Id. Ian. a.d. IV Id. Feb. a.d. IV Id. Feb. a.d. VI Id. Mar. a.d. IV Id. Apr.
11 ante diem tertium Idus Ianuarias a.d. III Id. Ian. a.d. III Id. Feb. a.d. III Id. Feb. a.d. V Id. Mar. a.d. III Id. Apr.
12 pridie Idus Ianuarias prid. Id. Ian. prid. Id. Feb. prid. Id. Feb. a.d. IV Id. Mar. prid. Id. Apr.
13 Idibus Ianuariis Id. Ian. Id. Feb. Id. Feb. a.d. III Id. Mar. Id. Apr.
14 ante diem undevicesimum Kalendas Februarias a.d. XIX Kal. Feb. a.d. XVI Kal. Mar. a.d. XVI Kal. Mar. prid. Id. Mar. a.d. XVIII Kal. Mai.
15 ante diem duodevicesimum Kalendas Februarias a.d. XVIII Kal. Feb. a.d. XV Kal. Mar. a.d. XV Kal. Mar. Id. Mar. a.d. XVII Kal. Mai.
16 ante diem septimum decimum Kalendas Februarias a.d. XVII Kal. Feb. a.d. XIV Kal. Mar. a.d. XIV Kal. Mar. a.d. XVII Kal. Apr. a.d. XVI Kal. Mai.
17 ante diem sextum decimum Kalendas Februarias a.d. XVI Kal. Feb. a.d. XIII Kal. Mar. a.d. XIII Kal. Mar. a.d. XVI Kal. Apr. a.d. XV Kal. Mai.
18 ante diem quintum decimum Kalendas Februarias a.d. XV Kal. Feb. a.d. XII Kal. Mar. a.d. XII Kal. Mar. a.d. XV Kal. Apr. a.d. XIV Kal. Mai.
19 ante diem quartum decimum Kalendas Februarias a.d. XIV Kal. Feb. a.d. XI Kal. Mar. a.d. XI Kal. Mar. a.d. XIV Kal. Apr. a.d. XIII Kal. Mai.
20 ante diem tertium decimum Kalendas Februarias a.d. XIII Kal. Feb. a.d. X Kal. Mar. a.d. X Kal. Mar. a.d. XIII Kal. Apr. a.d. XII Kal. Mai.
21 ante diem duodecimum Kalendas Februarias a.d. XII Kal. Feb. a.d. IX Kal. Mar. a.d. IX Kal. Mar. a.d. XII Kal. Apr. a.d. XI Kal. Mai.
22 ante diem undecimum Kalendas Februarias a.d. XI Kal. Feb. a.d. VIII Kal. Mar. a.d. VIII Kal. Mar. a.d. XI Kal. Apr. a.d. X Kal. Mai.
23 ante diem decimum Kalendas Februarias a.d. X Kal. Feb. a.d. VII Kal. Mar. a.d. VII Kal. Mar. a.d. X Kal. Apr. a.d. IX Kal. Mai.
24 ante diem nonum Kalendas Februarias a.d. IX Kal. Feb. a.d. VI Kal. Mar. a.d. bis VI Kal. Mar. a.d. IX Kal. Apr. a.d. VIII Kal. Mai.
25 ante diem octavum Kalendas Februarias a.d. VIII Kal. Feb. a.d. V Kal. Mar. a.d. VI Kal. Mar. a.d. VIII Kal. Apr. a.d. VII Kal. Mai.
26 ante diem septimum Kalendas Februarias a.d. VII Kal. Feb. a.d. IV Kal. Mar. a.d. V Kal. Mar. a.d. VII Kal. Apr. a.d. VI Kal. Mai.
27 ante diem sextum Kalendas Februarias a.d. VI Kal. Feb. a.d. III Kal. Mar. a.d. IV Kal. Mar. a.d. VI Kal. Apr. a.d. V Kal. Mai.
4 Basic commands
4.1 Writing a date
\KalDate[hoptionsi]{hyeari}{hmonthi}{hdayi}
\kal_date:nnn {hyeari} {hmonthi} {hdayi}
This command renders the specified date according to the Roman calendar. Regardless of century, thehyearimust be specified in full: \KalDate{18}{6}{14}will result in the year 18 ce, not 2018. Ifhoptionsiare specified, they will apply only to the date rendered by their respective instance of this command.
Example
Here, we render the date 4 July 2018 with default formatting (no abbreviations, day written in Roman numerals,anno Dominiera):
\KalDate{2018}{7}{4}⇒ante diem IV Nonas Iulias anno Domini MMXVIII
\KalDate ?
\kal_date:nnn ?
4.2 Writing a date from a string
\KalDateStr[hoptionsi]{hformati}{hdelimiteri}{hdate stringi}
\kal_date_string:nnn {hformati} {hdelimiteri} {hdate stringi}
While the previous command works well for predefined, manually-typed dates, dates generated by macros nearly always appear in the form of a single string, not three sep- arate arguments. For such scenarios,kalendariumprovides the\KalDateStrcommand, which converts ahdate stringiin the specifiedhformatiwith segments separated by thehdelimiteriinto a Roman date. Thehformatishould consist of a maximum of three characters—Yfor the year,Mfor the month, andDfor the day of the month—in the order in which they appear in thehdate stringi.
Example
Here, we render the date 4 July 2018 from ISO format (YYYY-MM-DD) and standard United States format (M/D/YYYY) in the Roman calendar:
\KalDateStr{YMD}{-}{2018-07-04}⇒
ante diem IV Nonas Iulias anno Domini MMXVIII
\KalDateStr{MDY}{/}{7/4/2018}⇒
ante diem IV Nonas Iulias anno Domini MMXVIII
When using the standard LATEX command\KalDateStr, thehdate stringiis expanded once to allow for the use of macros as input; this is equivalent to the LATEX3 command
\kal_date_string:nno.
Example
Here, we render the date on which thekalendariumstyle file was last generated according to the\filedatemacro (⇒2018-06-17) in the Roman calendar:
\KalDateStr{YMD}{-}{\filedate}⇒
ante diem XV Kalendas Iulias anno Domini MMXVIII
\KalDateStr ?
\kal_date_string:nnn ?
\kal_date_string:nno ?
4.3 Writing the current date
\KalToday[hoptionsi]
This command renders the current date according to the Roman calendar, serving as thekalendariumequivalent of the\todaymacro.
Example
Here, we render the date on which this document was generated (September 21, 2018) in the Roman calendar:
\KalToday⇒ante diem XI Kalendas Octobres anno Domini MMXVIII
\KalToday ?
4.4 Determining the weekday of a date
\KalWeekday[hoptionsi]{hyeari}{hmonthi}{hdayi}
\kal_weekday:n {hyeari} {hmonthi} {hdayi}
This command determines the day of the week of a given day and displays its Latin name. Like the rest of kalendarium, it can handle dates on both the Julian and Gregorian calendars and takes the same set ofhoptionsias other commands.
Example
Here, we determine the day of the week on which 4 July 2018 will fall:
dies \KalWeekday{2018}{7}{4}⇒dies Mercurii
dies \KalWeekday[abbreviate=true]{2018}{7}{4}⇒dies Merc.
\KalWeekday ?
\kal_weekday:nnn ?
5 Customisation
5.1 Format options
In order to provide the ability to render dates on the Roman calendar through vari- ous ages of the Classical period,kalendariumprovides many options to customise the format in which dates are displayed. These options may be set in the global pack- age options (\usepackagestatement) or for individual commands via thehoptionsi argument. Regardless of which means of configuration is used, options are set via comma-separated key-value pairs of the form[hkey1i=hvalue1i,hkey2i=hvalue2i,...], in whichhkeyniis any of the options in the left margin of this section andhvalueniis one of the accepted choices listed thereby. Values with a
blue bell to their left are the default values for their respective options.This variable determines whether to use common abbreviations (a.d. forante diem, Kal. forKalendas, etc.) instead of full Latin phrases when displaying dates.
Accepted values
true Display dates in abbreviated format.
false Display dates in full, unabbreviated Latin.Example
Here, we render the date 4 July 2018, first unabbreviated, then with the abbreviateoption set totrue:
\KalDate[abbreviate=false]{2018}{7}{4}⇒
ante diem IV Nonas Iulias anno Domini MMXVIII
\KalDate[abbreviate=true]{2018}{7}{4}⇒ a.d.
ante diem|{z}
IV Non.
| {z }
Nonas
Iul.
Iulias|{z}
a.d.
|{z}anno Domini
MMXVIII abbreviate
This variable determines whether to display the day portion of dates in the Classical ante diemstyle or in the Medieval ablative ordinal style.
Accepted values
true Display days in Classical style, prefixed byante diem(a.d.) and as an ordinal in the accusative case, when appropriate.false Display days in Medieval style, with no prefix and as an ordinal in the ablative case, when appropriate.
Example
Here, we render the date 4 May 1886 in both the Classical and Medieval styles:
\KalDate[antediem=true]{1886}{5}{4}⇒
ante diem IV Nonas Maias anno Domini MDCCCLXXXVI
\KalDate[antediem=false]{1886}{5}{4}⇒
IV Nonas Maias anno Domini MDCCCLXXXVI antediem
This variable determines whether to display dates in February of leap years with a bissextumon 24 February or to continue the counting of days through theTerminalia.
Accepted values
true Display 24 February asa.d. bissextum Kalendas Martiasin leap years.false Display 24 February asa.d. septimum Kalendas Martiasin leap years.
Example
Here, we render the date 24 February 2016, first with abissextumthen without:
\KalDate[bissextum=true]{2016}{2}{24}⇒
ante diem bis VI Kalendas Martias anno Domini MMXVI
\KalDate[bissextum=false]{2016}{2}{24}⇒
ante diem VII Kalendas Martias anno Domini MMXVI Example
Here, we render the same dates, but with Latin ordinal numbers instead of Roman numerals:
\KalDate[bissextum=true,dayfmt=latin]{2016}{2}{24}⇒ ante diem bissextum Kalendas Martias anno Domini MMXVI
\KalDate[bissextum=false,dayfmt=latin]{2016}{2}{24}⇒ ante diem septimum Kalendas Martias anno Domini MMXVI bissextum
This variable determines the format in which to display the day portion of anante diemdate. If an invalid value is set, days will be displayed in Roman numerals, as is default.
Accepted values
roman Display the day in Roman numerals.latin Display the day in full Latin text. If the optionantediemis set totrue, the ordinal number will be in the accusative singular;
otherwise, it will be in the ablative, in Medieval style.
arabic Display the day in Arabic numerals.
Example
Here, we render the date 27 November 1095 with all supported day formats:
\KalDate[dayfmt=roman]{1095}{11}{27}⇒
ante diem V Kalendas Decembres anno Domini MXCV
\KalDate[dayfmt=latin]{1095}{11}{27}⇒
ante diem quintum Kalendas Decembres anno Domini MXCV
\KalDate[dayfmt=latin,antediem=false]{1095}{11}{27}⇒ quinto Kalendas Decembres anno Domini MXCV
\KalDate[dayfmt=arabic]{1095}{11}{27}⇒
ante diem 5 Kalendas Decembres anno Domini MXCV dayfmt
This variable determines the era in which to display the specified year, or the prefix or suffix to be placed around the year number.
Accepted values
ad Display years in anno Domini(a.d.) and ante Christum(a.c.) format.adshort Same asad, exceptanno Dominiis shortened to onlyanno(a.).
auc Display yearsab urbe condita(a.u.c.), the time since the leg- endary founding of the city of Rome in 753 bce.
secular Display years in a Latinised form of the secular Before Com- mon Era and Common Era format, translated toante saeculum commune(a.s.c.) andsaeculo communi(s.c.), respectively.
none,* Do not display the year when rendering dates.
Example
Here, we render the date 7 November 1917 in all supported eras:
\KalDate[era=auc]{1917}{11}{7}⇒
ante diem VII Idus Novembres MMDCLXX ab urbe condita
\KalDate[era=ad]{1917}{11}{7}⇒
ante diem VII Idus Novembres anno Domini MCMXVII
\KalDate[era=adshort]{1917}{11}{7}⇒
ante diem VII Idus Novembres anno MCMXVII
\KalDate[era=secular]{1917}{11}{7}⇒
ante diem VII Idus Novembres saeculo communi MCMXVII
\KalDate[era=none]{1917}{11}{7}⇒ ante diem VII Idus Novembres era
This variable determines whether to determine leap years and weekdays according to the Julian or Gregorian calendar.
Accepted values
true Perform date calculations according to the Julian calendar.
false Perform date calculations according to the Gregorian calendar.Example
Here, we render the date 24 February 1900 on both the Julian and Gregorian calendars. On the Julian calendar, 1900 is considered a leap year, and thus 24 February is abissextum; however, on the Gregorian calendar, it is not.
\KalDate[julian=true]{1990}{2}{24}⇒
ante diem bis VI Kalendas Martias anno Domini MCMXC
\KalDate[julian=false]{1990}{2}{24}⇒
ante diem VI Kalendas Martias anno Domini MCMXC julian
This variable determines whether to display the Imperial names for the seventh and eighth months of the year,IuliusandAugustus, or the (pre-)Republican names, QuintilisandSextilis.
Accepted values
true Display month names as in the Republican period and prior.
false Display month names as in the Imperial period and after.Example
Here, we render the date 4 July 2018, first with its Republican nameQuintilis, then with its Imperial nameIulius:
\KalDate[oldmonths=true]{2018}{7}{4}⇒
ante diem IV Nonas Quintiles anno Domini MMXVIII
\KalDate[oldmonths=false]{2018}{7}{4}⇒
ante diem IV Nonas Iulias anno Domini MMXVIII oldmonths
This variable determines whether to display periods to indicate abbreviations for common calendrical phrases. If theabbreviateoption is set tofalse, this option will have no effect on the date format.
Accepted values
true Display periods to indicate abbreviated terms.false Do not display any periods amidst abbreviations.
Example
Here, we render the date 25 December 1776, first with periods, then with the periodsoption set tofalse:
\KalDate[abbreviate=true]{1776}{12}{25}⇒ a.d. VIII Kal. Ian. a. MDCCLXXVI
\KalDate[abbreviate=true,periods=false]{1776}{12}{25}⇒ ad VIII Kal Ian a MDCCLXXVI
periods
This variable determines the format in which to display the numeric year of a date for which the optionerais not set tonone. If an invalid value is set, years will be displayed in Roman numerals, as is default.
Accepted values
roman Display the year in Roman numerals.arabic Display the year in Arabic numerals.
Example
Here, we render the date 27 November 1095 with all supported year formats:
\KalDate[yearfmt=roman]{1095}{11}{27}⇒
ante diem V Kalendas Decembres anno Domini MXCV
\KalDate[yearfmt=arabic]{1095}{11}{27}⇒
ante diem V Kalendas Decembres anno Domini 1095 yearfmt
5.2 Formatting commands
In order to provide even more control over the formatting of Roman calendar dates, kalendariumprovides several commands that may be overridden to change the visual appearance of its output. By default, all Roman numerals are output in lowercase, so these formatting commands must perform any desired case transformations in addition to styling operations.
\KalAbbrFormat{habbreviationi}
This command controls the display of all single-letter abbreviations within date expressions. If the optionabbreviateis set tofalse, it will have no apparent effect on the output of any command.
Example
Here, we override\KalAbbrFormatto render all abbreviations in italics instead of the default small capitals:
\KalDate[abbreviate=true,era=adshort]{2018}{7}{4}⇒ a.d. IV Non. Iul. a. MMXVIII
\renewcommand{\KalAbbrFormat}[1]{\textit{#1}}
\KalDate[abbreviate=true,era=adshort]{2018}{7}{4}⇒ a.d.IV Non. Iul.a.MMXVIII
\KalAbbrFormat ?
\KalDayFormat{hdayi}
This command controls the display of all day numbers within date expressions. By default, it only serves to capitalise Roman numerals.
Example
Here, we override\KalDayFormatto underline and capitalise all day numbers:
\KalDate[abbreviate=true,era=adshort]{2018}{7}{4}⇒ a.d. IV Non. Iul. a. MMXVIII
\renewcommand{\KalDayFormat}[1]{\underline{\MakeUppercase{#1}}}
\KalDate[abbreviate=true,era=adshort]{2018}{7}{4}⇒ a.d. IV Non. Iul. a. MMXVIII
\KalDayFormat ?
\KalYearFormat{hyeari}
This command controls the display of all year numbers within date expressions. By default, it only serves to capitalise Roman numerals.
Example
Here, we override\KalYearFormatto overline all year numbers and render them in small capitals:
\KalDate[abbreviate=true,era=adshort]{2018}{7}{4}⇒ a.d. IV Non. Iul. a. MMXVIII
\renewcommand{\KalYearFormat}[1]{$\overline{\mbox{\textsc{#1}}}$}
\KalDate[abbreviate=true,era=adshort]{2018}{7}{4}⇒ a.d. IV Non. Iul. a. mmxviii
\KalYearFormat ?
6 Implementation
6.1 Package declaration and dependencies
1 h*packagei
2 \RequirePackage{xparse}
3 \RequirePackage{l3keys2e}
4 \ProvidesExplPackage
5 {kalendarium}
6 {2018-06-17}{1.0}
7 {A package to display dates in the classical Roman style}
8 \ExplSyntaxOn
6.2 Package options
Process global options immediately upon loading the package, setting default values for any options not specified by the user.
9 \keys_define:nn {kalendarium}{
10 abbreviate .bool_set:N = \l_kal_abbreviate_bool,
11 abbreviate .initial:n = { false },
13 periods .initial:n = { true },
14 era .tl_set:N = \l_kal_era_tl,
15 era .initial:n = { ad },
16 julian .bool_set:N = \l_kal_julian_bool,
17 julian .initial:n = { false },
18 dayfmt .tl_set:N = \l_kal_dayfmt_tl,
19 dayfmt .initial:n = { roman },
20 yearfmt .tl_set:N = \l_kal_yearfmt_tl,
21 yearfmt .initial:n = { roman },
22 antediem .bool_set:N = \l_kal_antediem_bool,
23 antediem .initial:n = { true },
24 bissextum .bool_set:N = \l_kal_bissextum_bool,
25 bissextum .initial:n = { true },
26 oldmonths .bool_set:N = \l_kal_oldmonths_bool,
27 oldmonths .initial:n = { false }
28 }
29 \ProcessKeysOptions {kalendarium}
6.3 Constant lists
In order to convert numeric dates to written Latin, lookup lists are allocated for each required conversion. Thus, not all genders, numbers, and cases of adjectives are listed, but only those that regularly appear in Roman date strings.
\c_kal_day_acc_clist Ordinal numbers 1–19 in the accusative singular masculine; thebissextum, while not the ordinal number 20, is allocated the twentieth position in this and other ordinal lists for the sake of convenience. Furthermore, the ordinalsprimumandsecundum do not appear in date strings but are included nonetheless to facilitate index lookups.
30 \clist_new:N \c_kal_day_acc_clist
31 \clist_set:Nn \c_kal_day_acc_clist {
32 primum,secundum,tertium,quartum,quintum,sextum,septimum,octavum,nonum,decimum,
33 undecimum,duodecimum,tertium\ decimum,quartum\ decimum,quintum\ decimum,
34 sextum\ decimum,septimum\ decimum,duodevicesimum,undevicesimum,bissextum
35 }
(End definition for\c_kal_day_acc_clist.)
\c_kal_day_abl_clist Ordinal numbers 1–19 in the ablative singular masculine; used only for the Medieval day format that forgoes the prefixante diem.
36 \clist_new:N \c_kal_day_abl_clist
37 \clist_set:Nn \c_kal_day_abl_clist {
38 primo,secundo,tertio,quarto,quinto,sexto,septimo,octavo,nono,decimo,
39 undecimo,duodecimo,tertio\ decimo,quarto\ decimo,quinto\ decimo,
40 sexto\ decimo,septimo\ decimo,duodevicesimo,undevicesimo,bissexto
41 }
(End definition for\c_kal_day_abl_clist.)
\c_kal_weekday_gen_clist Latin names of weekdays in the genitive singular case, intended to follow the word dies. Saturday is placed first due to the weekday indexing used in Zeller’s congruence.
42 \clist_new:N \c_kal_weekday_gen_clist
43 \clist_set:Nn \c_kal_weekday_gen_clist {
44 Saturni,Solis,Lunae,Martis,Mercurii,Iovis,Veneris }
(End definition for\c_kal_weekday_gen_clist.)
\c_kal_weekday_abbr_clist Abbreviated Latin names of weekdays; a simple truncation of values from\c_kal_- weekday_gen_clistcould not be performed due to the irregular lengths of the abbre- viations for Tuesday and Wednesday.
46 \clist_new:N \c_kal_weekday_abbr_clist
47 \clist_set:Nn \c_kal_weekday_abbr_clist {
48 Sat,Sol,Lun,Mart,Merc,Iov,Ven
49 }
(End definition for\c_kal_weekday_abbr_clist.)
\c_kal_month_acc_clist
\c_kal_month_abl_clist
\c_kal_month_abbr_clist
Full Latin names of months in the accusative and ablative plural feminine, along with abbreviations for the months. Note thatQuintilisandSextilisare considered the thirteenth and fourteenth months to facilitate list access; however,Quintilisis not considered the month after December when determining its Kalends reference.
August is repeated afterSextilisto facilitate Kalends referencing. These issues could be solved in a much cleaner manner if LATEX3 data structures were more than simple stacks.
50 \clist_new:N \c_kal_month_acc_clist
51 \clist_set:Nn \c_kal_month_acc_clist {
52 Ianuarias,Februarias,Martias,Apriles,Maias,Iunias,Iulias,Augustas,
53 Septembres,Octobres,Novembres,Decembres,Quintiles,Sextiles,Augustas
54 }
55 \clist_new:N \c_kal_month_abl_clist
56 \clist_set:Nn \c_kal_month_abl_clist {
57 Ianuariis,Februariis,Martiis,Aprilibus,Maiis,Iuniis,Iuliis,
58 Augustis,Septembribus,Octobribus,Novembribus,Decembribus,
59 Quintilibus,Sextilibus,Augustis
60 }
61 \clist_new:N \c_kal_month_abbr_clist
62 \clist_set:Nn \c_kal_month_abbr_clist {
63 Ian,Feb,Mar,Apr,Mai,Iun,Iul,Aug,Sept,Oct,Nov,Dec,Quin,Sex,Aug
64 }
(End definition for\c_kal_month_acc_clist,\c_kal_month_abl_clist, and\c_kal_month_abbr_clist.)
\c_kal_month_lengths_clist Number of days in all months, with February to be handled later.
65 \clist_new:N \c_kal_month_lengths_clist
66 \clist_set:Nn \c_kal_month_lengths_clist {
67 31,28,31,30,31,30,31,31,30,31,30,31,31,31
68 }
(End definition for\c_kal_month_lengths_clist.)
\c_kal_month_ides_clist Day on which the Ides of each month fall; determined by whether months are “full” or
“hollow” on the Romulan calendar.
69 \clist_new:N \c_kal_month_ides_clist
70 \clist_set:Nn \c_kal_month_ides_clist {
71 13,13,15,13,15,13,15,13,13,15,13,13,15,13
72 }
6.4 Internal utility functions
\kal_period:n Conditionally renders a period in abbreviations depending on the value of theperiods option; saves a moderate amount of typing.
73 \cs_new:Nn \kal_period:n {
74 \bool_if:NT \l_kal_periods_bool {.}
75 }
(End definition for\kal_period:n.)
\kal_abbr:nn Conditionally renders full text (#1) or an abbreviation (#2) followed by a period de- pending on the value of theabbreviateoption.
76 \cs_new:Npn \kal_abbr:nn #1#2 {
77 \bool_if:NTF \l_kal_abbreviate_bool {#2 \kal_period:n{}} {#1}
78 }
(End definition for\kal_abbr:nn.)
\kal_month:nn Conditionally renders the full name of the month at index#2in list#1or an abbrevia- tion depending on the value of theabbreviateoption.
79 \cs_new:Npn \kal_month:nn #1#2 {
80 \kal_abbr:nn
81 { \clist_item:Nn {#1} {#2} }
82 { \clist_item:Nn \c_kal_month_abbr_clist {#2} }
83 }
(End definition for\kal_month:nn.)
\kal_ante_diem:nn Renders the day portion (#1) of dates that would be preceded byante diemin the Classical period. If#2is equal to 1, the full Latin ordinal number for the day is rendered in the accusative case; otherwise, the number is rendered as-is.
84 \cs_new:Npn \kal_ante_diem:nn #1#2 {
85 \bool_if:nTF {\l_kal_antediem_bool}
86 {
87 \kal_abbr:nn {ante\ diem} {\KalAbbrFormat{a \kal_period:n{} d}}
88 \ \int_compare:nNnTF {#2} = {1}
89 { \clist_item:Nn \c_kal_day_acc_clist {#1} }
90 { #1 }
91 }
If the user has instead chosen to use the Medieval day syntax (noante diem), render the number in the ablative case.
92 {
93 \int_compare:nNnTF {#2} = {1}
94 { \clist_item:Nn \c_kal_day_abl_clist {#1} }
95 { #1 }
96 }
97 }
(End definition for\kal_ante_diem:nn.)
\kal_day:n Renders the full name of the day#1days before the next named day, inclusive. If it is the day directly before (2 days inclusive), renderpridie.
98 \cs_new:Npn \kal_day:n #1 {
99 \int_compare:nNnTF {#1} = {2}
{ \kal_abbr:nn {pridie} {prid} }
Otherwise, render the appropriateante diemnumber in the format set by the user in the optiondayfmt.
101 {
102 \str_case_x:nnF { \l_kal_dayfmt_tl }
103 {
104 { latin } { \kal_ante_diem:nn {#1} {1} }
105 { roman } { \kal_ante_diem:nn {\KalDayFormat{
106 \int_to_roman:n {#1}}} {0} }
107 { arabic } { \kal_ante_diem:nn {\int_eval:n {#1}} {0} }
108 }
If an invalid day format was set, use Roman numerals.
109 { \kal_ante_diem:nn {\KalDayFormat{\int_to_roman:n {#1}}} {0} }
110 }
111 }
(End definition for\kal_day:n.)
\kal_bissextum_day:n Renders the names of days (#1) in February in years for whichbissexta(leap days) are inserted. If the specified day is before 24 February, it can be rendered normally.
112 \cs_new:Npn \kal_bissextum_day:n #1 {
113 \int_compare:nNnTF {#1} < {24}
114 { \kal_day:n { \l_kal_month_length_int - #1 + 1 } }
If the day is after 24 February, we must add another day to the distance from the Kalends to compensate for thebissextum.
115 {
116 \int_compare:nNnTF {#1} > {24}
117 { \kal_day:n { \l_kal_month_length_int - #1 + 2 } }
If the specified day is thebissextumitself, render its unique string in the format requested by the user, or in Roman numerals if the format is invalid.
118 {
119 \str_case_x:nnF { \l_kal_dayfmt_tl }
120 {
121 { latin } { \kal_ante_diem:nn {20} {1} }
122 { roman } { \kal_ante_diem:nn {bis\ \KalDayFormat{vi} } {0} }
123 { arabic } { \kal_ante_diem:nn {bis\ \KalDayFormat{6} } {0} }
124 }
125 { \kal_ante_diem:nn {bis\ \KalDayFormat{vi} } {0} }
126 }
127 }
128 }
(End definition for\kal_bissextum_day:n.)
\kal_year:n Renders the year#1in the format set in the optionyearfmt, defaulting to Roman numerals if an invalid value was set.
129 \cs_new:Npn \kal_year:n #1 {
130 \KalYearFormat{
131 \str_case_x:nnF { \l_kal_yearfmt_tl }
132 {
133 { roman } { \int_to_roman:n {#1} }
136 { \int_to_roman:n {#1} }
137 }
138 }
(End definition for\kal_year:n.)
6.5 Date rendering
\l_kal_month_idx_int
\l_kal_month_length_int
\l_kal_month_ides_int
Begin by defining some scratch variables for the index of the month to pull from the constant lists, the length of the specified month, and the day on which the Ides of the month fall.
139 \int_new:N \l_kal_month_idx_int
140 \int_new:N \l_kal_month_length_int
141 \int_new:N \l_kal_month_ides_int
(End definition for\l_kal_month_idx_int,\l_kal_month_length_int, and\l_kal_month_ides_int.)
\kal_date:nnn We can now start the process of rendering a date string.
142 \cs_new:Npn \kal_date:nnn #1#2#3 {
Archaic months. The first quantity we must establish is the index of the month#2 to use from the constant lists. If the user has requested the archaic monthsQuintilis andSextilisvia theoldmonthsoption, target those values at indices 13 and 14.
143 \bool_if:nTF {\l_kal_oldmonths_bool}
144 {
145 \int_case:nnF {#2}
146 {
147 {7} { \int_set:Nn \l_kal_month_idx_int {13} }
148 {8} { \int_set:Nn \l_kal_month_idx_int {14} }
149 }
Otherwise, retrieve values from the index specified.
150 { \int_set:Nn \l_kal_month_idx_int {#2} }
151 }
152 { \int_set:Nn \l_kal_month_idx_int {#2} }
Leap years. Now we must deal with leap years. Since this package targets both the Julian and Gregorian calendars, we shall need to handle both at once. Begin by checking the criteria for a leap month common to both calendars: the month must be February, and the year must be evenly divisible by 4.
153 \int_compare:nNnTF {\l_kal_month_idx_int} = {2}
154 {
155 \int_compare:nNnTF { \int_mod:nn {#1} {4} } = {0}
156 {
If the user has chosen to use the Julian calendar or the specified year satisfies the Gregorian criterion of not being evenly divisible by 100, the month will be 29 days long.
157 \bool_if:nTF
158 {
159 \l_kal_julian_bool ||
160 \int_compare_p:n { \int_mod:nn {#1} {100} != 0 }
161 }
162 { \int_set:Nn \l_kal_month_length_int {29} }
If the Gregorian calendar is in use and the year is evenly divisible by 100, the month will have 28 days, except in the case that the year is also evenly divisible by 400, when it will have 29 days.
163 {
164 \int_compare:nNnTF { \int_mod:nn {#1} {400} } = {0}
165 { \int_set:Nn \l_kal_month_length_int {29} }
166 { \int_set:Nn \l_kal_month_length_int {28} }
167 }
168 }
If none of the leap year criteria are satisfied, February will have 28 days.
169 { \int_set:Nn \l_kal_month_length_int {28} }
170 }
Finally, if the specified month is not February, look up its length in the list of month durations.
171 {
172 \int_set:Nn \l_kal_month_length_int
173 { \clist_item:Nn \c_kal_month_lengths_clist {\l_kal_month_idx_int} }
174 }
Naming the day. Now that we have figured out how long our month is, we can render the name of the day#3. We shall begin by determining on which day of the month the Ides will fall, as many of the other days pivot thereupon.
175 \int_set:Nn \l_kal_month_ides_int
176 { \clist_item:Nn \c_kal_month_ides_clist {\l_kal_month_idx_int} }
We shall handle the named days themselves first: the Kalends on the first day of the month, the Nones eight (nine inclusively) days before the Ides, and the Ides.
177 \int_case:nnTF {#3}
178 {
179 { 1 } { \kal_abbr:nn {Kalendis} {Kal} }
180 { \l_kal_month_ides_int - 8 } { \kal_abbr:nn {Nonis} {Non} }
181 { \l_kal_month_ides_int } { \kal_abbr:nn {Idibus} {Id} }
182 }
If the specified day is one of these named days, render the month in the ablative plural.
183 { \ \kal_month:nn {\c_kal_month_abl_clist} {\l_kal_month_idx_int} }
If the specified day does not have a name ascribed to it, we must determine the next named day thereafter. We shall walk forward through the month to find this day, beginning with the days before the Nones, which take the Latin form ante diem. . . Nonas. Note that 7 days are subtracted from the Ides in this calculation as a further consequence of inclusive counting.
184 {
185 \int_compare:nNnTF {#3} < { \l_kal_month_ides_int - 8 }
186 {
187 \kal_day:n { \l_kal_month_ides_int - #3 - 7 }
188 \ \kal_abbr:nn {Nonas} {Non}
189 \ \kal_month:nn {\c_kal_month_acc_clist} {\l_kal_month_idx_int}
190 }
If the day is not before the Nones, it may be before the Ides and would take the Latin formante diem. . . Idus.
191 {
192 \int_compare:nNnTF {#3} < {\l_kal_month_ides_int}
193 {
194 \kal_day:n { \l_kal_month_ides_int - #3 + 1 }
195 \ \kal_abbr:nn {Idus} {Id}
196 \ \kal_month:nn {\c_kal_month_acc_clist} {\l_kal_month_idx_int}
197 }
If the day is before neither the Nones nor the Ides, it must reference the Kalends of the following month, taking the Latin formante diem. . . Kalendas. If it has been requested by the user, thebissextumfalls in this date span, so the month of February must be handled separately from all other dates.
198 {
199 \bool_if:nTF
200 {
201 \int_compare_p:nNn {\l_kal_month_idx_int} = {2} &&
202 \l_kal_bissextum_bool
203 }
204 { \kal_bissextum_day:n {#3} }
Outside of special Februaries, these dates may be handled normally. Note that two days are added to the specified day in calculation as a result of inclusive counting.
205 {
206 \kal_day:n { \l_kal_month_length_int - #3 + 2 }
207 }
208 \ \kal_abbr:nn {Kalendas} {Kal}
We must also handle the fact that the month following December is January, so the Kalends references of December dates will be in the first month. For all other months, reference the next month.
209 \ \int_compare:nNnTF {\l_kal_month_idx_int} = {12}
210 { \kal_month:nn {\c_kal_month_acc_clist} {1} }
211 {
212 \kal_month:nn {\c_kal_month_acc_clist}
213 {\l_kal_month_idx_int + 1}
214 }
215 }
216 }
217 }
Rendering the year. The only portion of the date that remains to be rendered is the year, in the format specified in theeraoption. If the era is not one of the ones listed below, the year is not displayed; the valuenoneis suggested to the user to avoid unintended side-effects of utilising other values.
218 \str_case_x:nn { \l_kal_era_tl }
219 {
The first date format we shall handle is theab urbe condita(auc) era, which measures years relative to the legendary founding of Rome in 753 bce. As opposed to the other supported eras,ab urbe conditahas one peculiar quirk: while theanno Dominiand Common Era formats omit the year zero,ab urbe conditacontinued through this year.
Thus, while the numeric difference between 1 bce and 1 ce is two years, the difference
between these yearsab urbe conditais only one year. To solve this problem, we can use different addends for dates before and after “0 ce”.
220 { auc } {
221 \ \KalYearFormat{
222 \int_compare:nNnTF {#1} < {0}
223 { \kal_year:n { #1 + 754 } }
224 { \kal_year:n { #1 + 753 } }
225 }
226 \ \kal_abbr:nn {ab\ urbe\ condita}
227 {\KalAbbrFormat{a \kal_period:n{} u \kal_period:n{} c}}
228 }
Theanno Dominiera is significantly simpler, as its years are congruent with those used as input for this function. If a date falls after “0 ce”, it is classified in theanno Domini(ad) era; if it falls before, it isante Christum(ac).
229 { ad } {
230 \int_compare:nNnTF {#1} < {0}
231 {
232 \ \KalYearFormat{\kal_year:n {\int_abs:n {#1}}}
233 \ \kal_abbr:nn {ante\ Christum}
234 {\KalAbbrFormat{a \kal_period:n{} c}}
235 }
236 {
237 \ \kal_abbr:nn {anno\ Domini}
238 {\KalAbbrFormat{a \kal_period:n{} d}}
239 \ \KalYearFormat{\kal_year:n {#1}}
240 }
241 }
Theanno, or “short ad,” pseudo-era is nearly identical, only replacing the phraseanno Dominiwith the shorteranno(a).
242 { adshort } {
243 \int_compare:nNnTF {#1} < {0}
244 {
245 \ \KalYearFormat{\kal_year:n {\int_abs:n {#1}}}
246 \ \kal_abbr:nn {ante\ Christum}
247 {\KalAbbrFormat{a \kal_period:n{} c}}
248 }
249 {
250 \ \kal_abbr:nn {anno} {\KalAbbrFormat{a}}
251 \ \KalYearFormat{\kal_year:n {#1}}
252 }
253 }
Finally, the Common Era (saeculum commune) shares the same year numbers as the anno Dominiera, but uses different verbiage.
254 { secular } {
255 \int_compare:nNnTF {#1} < {0}
256 {
257 \ \KalYearFormat{\kal_year:n {\int_abs:n {#1}}}
258 \ \kal_abbr:nn {ante\ saeculum\ commune}
259 {\KalAbbrFormat{a \kal_period:n{} s \kal_period:n{} c}}
260 }
263 {\KalAbbrFormat{s \kal_period:n{} c}}
264 \ \KalYearFormat{\kal_year:n {#1}}
265 }
266 }
267 }
268 }
(End definition for\kal_date:nnn.)
6.6 Rendering dates from strings
\l_kal_date_year_int
\l_kal_date_month_int
\l_kal_date_day_int
\l_kal_date_split_seq
\l_kal_date_idx_int
Begin by defining some scratch variables for the year, month, and day of the specified date; the date sequence after being split at the specified delimiters; and a loop index.
269 \int_new:N \l_kal_date_year_int
270 \int_new:N \l_kal_date_month_int
271 \int_new:N \l_kal_date_day_int
272 \seq_new:N \l_kal_date_split_seq
273 \int_new:N \l_kal_date_idx_int
(End definition for\l_kal_date_year_intand others.)
\kal_date_string:nnn To parse a date string (#3), we must first determine the order in which the year, month, and day are arranged in the format string (#1). We begin by splitting the date string at the specified delimiter (#2).
274 \cs_new:Npn \kal_date_string:nnn #1#2#3 {
275 \seq_set_split:Nnn \l_kal_date_split_seq {#2} {#3}
We now loop through the tokens in the format string, resolving each to one component of a fully-formed date. For each successful match, we set the corresponding variable to the element of the split sequence at the same index.
276 \int_set:Nn \l_kal_date_idx_int {1}
277 \int_do_until:nNnn {\l_kal_date_idx_int} = {4}
278 {
279 \str_case_x:nn {\tl_item:nn {#1} {\l_kal_date_idx_int}}
280 {
281 { Y } { \int_gset:Nn \l_kal_date_year_int
282 { \seq_item:Nn \l_kal_date_split_seq {\l_kal_date_idx_int} } }
283 { M } { \int_gset:Nn \l_kal_date_month_int
284 { \seq_item:Nn \l_kal_date_split_seq {\l_kal_date_idx_int} } }
285 { D } { \int_gset:Nn \l_kal_date_day_int
286 { \seq_item:Nn \l_kal_date_split_seq {\l_kal_date_idx_int} } }
287 }
288 \int_incr:N \l_kal_date_idx_int
289 }
Finally, we render the date normally from these resolved components.
290 \kal_date:nnn {\l_kal_date_year_int}
291 {\l_kal_date_month_int}
292 {\l_kal_date_day_int}
293 }
To allow this command to be used with macro arguments, we shall create a variant that expands the date string once.
294 \cs_generate_variant:Nn \kal_date_string:nnn { nno } (End definition for\kal_date_string:nnn.)
6.7 Determining weekdays of dates
\l_kal_weekday_idx_int
\l_kal_weekday_month_int
\l_kal_weekday_year_int
\l_kal_weekday_century_int
Begin by defining some scratch variables for the month, year, and zero-based century of the specified date, and a variable in which to store the weekday.
295 \int_new:N \l_kal_weekday_idx_int
296 \int_new:N \l_kal_weekday_month_int
297 \int_new:N \l_kal_weekday_year_int
298 \int_new:N \l_kal_weekday_century_int (End definition for\l_kal_weekday_idx_intand others.)
\kal_weekday:nnn To determine the day of the week of an arbitrary date on either the Julian or Gregorian calendars, we shall use an implementation of Zeller’s congruence. For the Gregorian calendar, this arithmetic algorithm is as follows:
w=
d+
13 (m+ 1) 5
+K+
K 4
+
J 4
+ 5J
mod 7
• wis the index of the day of the week, with Saturday at 0, Sunday at 1, Monday at 2, and so forth
• dis the day of the month
• mis the month, where all months follow their normal enumerations (March at 3, April at 4, etc.) except January and February, which are assigned indices 13 and 14, respectively
• Kis the year of the date within its century(y mod 100)
• J is the zero-based century of the year, y 100
. A similar formula exists for Julian dates:
w=
d+
13 (m+ 1) 5
+K+
K 4
+ 5 + 6J
mod 7
We begin our implementation by determining the index of the specified month. Since we already need to add 12 to the indices of January and February, and the termm only appears in the quantity(m+ 1), we shall combine these additions from the start.
299 \cs_new:Npn \kal_weekday:nnn #1#2#3 {
300 \int_compare:nNnTF {#2} < {3}
301 { \int_set:Nn \l_kal_weekday_month_int { #2 + 13 } }
302 { \int_set:Nn \l_kal_weekday_month_int { #2 + 1 } }
We now determine the year of the century of the specified date, along with its zero- based century, according to the equations above.
303 \int_set:Nn \l_kal_weekday_year_int { \int_mod:nn {#1} {100} }
304 \int_set:Nn \l_kal_weekday_century_int { \fp_eval:n { floor(#1 / 100) } } Next, we shall implement the portions of the algorithm that are shared between the Julian and Gregorian calendars, calculating all like terms between the two.
305 \int_set:Nn \l_kal_weekday_idx_int {#3}
306 \int_add:Nn \l_kal_weekday_idx_int
307 { \fp_eval:n { floor(13 * \l_kal_weekday_month_int / 5) } }
308 \int_add:Nn \l_kal_weekday_idx_int { \l_kal_weekday_year_int }
At this point, the algorithms diverge. If the date has been specified as Julian, we shall use the· · ·+ 5 + 6J termination.
311 \bool_if:nTF {\l_kal_julian_bool}
312 { \int_add:Nn \l_kal_weekday_idx_int { 5 + 6 * \l_kal_weekday_century_int } } Otherwise, we shall use the more complex Gregorian termination.
313 {
314 \int_add:Nn \l_kal_weekday_idx_int { \fp_eval:n
315 { 5 * \l_kal_weekday_century_int + floor(\l_kal_weekday_century_int / 4) }
316 }
317 }
Finally, we perform the modulus operation to reach an index value for the day of the week. As Zeller’s algorithm was designed for 0-indexed programming languages, we must add 1 to the index to compensate for LATEX3’s 1-based indexing.
318 \int_set:Nn \l_kal_weekday_idx_int { \int_mod:nn {\l_kal_weekday_idx_int} {7} }
319 \int_incr:N \l_kal_weekday_idx_int
We can now fetch the appropriate form of the weekday from the lookup lists.
320 \kal_abbr:nn
321 { \clist_item:Nn \c_kal_weekday_gen_clist { \l_kal_weekday_idx_int } }
322 { \clist_item:Nn \c_kal_weekday_abbr_clist { \l_kal_weekday_idx_int } }
323 }
(End definition for\kal_weekday:nnn.)
6.8 User-facing macros
\KalDate Render a Roman calendar date for the specified year (#2), month (#3), and day (#4) with the specified options (#1).
324 \DeclareDocumentCommand{\KalDate}{o m m m}
325 {
326 \IfValueTF{#1}
327 {
328 \group_begin:
329 \keys_set:nn {kalendarium} {#1}
330 \kal_date:nnn {#2} {#3} {#4}
331 \group_end:
332 }
333 { \kal_date:nnn {#2} {#3} {#4} }
334 }
(End definition for\KalDate. This function is documented on page??.)
\KalDateStr Convert the specified date string (#4), with components in the order of the format string (#2) and delimited by a consistent value (#3), to a Roman calendar date with the specified options (#1). To avoid user confusion, the date string is always expanded.
335 \DeclareDocumentCommand{\KalDateStr}{o m m m}
336 {
337 \IfValueTF{#1}
338 {
339 \group_begin:
340 \keys_set:nn {kalendarium} {#1}
341 \kal_date_string:nno {#2} {#3} {#4}
342 \group_end:
343 }
344 { \kal_date_string:nno {#2} {#3} {#4} }
345 }
(End definition for\KalDateStr. This function is documented on page??.)
\KalToday Render the Roman calendar date for the current date with the specified options (#1).
346 \DeclareDocumentCommand{\KalToday}{o}
347 {
348 \IfValueTF{#1}
349 {
350 \group_begin:
351 \keys_set:nn {kalendarium} {#1}
352 \kal_date:nnn {\the\year} {\the\month} {\the\day}
353 \group_end:
354 }
355 { \kal_date:nnn {\the\year} {\the\month} {\the\day} }
356 }
(End definition for\KalToday. This function is documented on page??.)
\KalWeekday Determine the Latin day of the week for the specified year (#2), month (#3), and day (#4) with the specified options (#1).
357 \DeclareDocumentCommand{\KalWeekday}{o m m m}
358 {
359 \IfValueTF{#1}
360 {
361 \group_begin:
362 \keys_set:nn {kalendarium} {#1}
363 \kal_weekday:nnn {#2} {#3} {#4}
364 \group_end:
365 }
366 { \kal_weekday:nnn {#2} {#3} {#4} }
367 }
368 \ExplSyntaxOff
(End definition for\KalWeekday. This function is documented on page??.)
\KalAbbrFormat
\KalDayFormat
\KalYearFormat
Commands to control the formatting of abbreviations, days, and years, respectively, in Roman calendar dates. The user is encouraged to override these commands to fit their particular æsthetic goals.
369 \newcommand{\KalAbbrFormat}[1]{\textsc{#1}}
370 \newcommand{\KalDayFormat}[1]{\MakeUppercase{#1}}
371 \newcommand{\KalYearFormat}[1]{\MakeUppercase{#1}}
(End definition for\KalAbbrFormat,\KalDayFormat, and\KalYearFormat. These functions are documented on page??.)
372 h/packagei