Inspired by How do you write dates in Latin?


Given a month-and-day date, output that date in abbreviated Latin, as explained below.


Input is flexible, following conventions from other and challenges. You may choose to:

  • Take a date in mm/dd or dd/mm format or two separate month,day arguments;
  • Take a date in your language's date format;
  • Take an integer in interval [0, 364] corresponding to a day in the year;
  • Take some other reasonable input that can encode all 365 days of the year;
  • Take no user input but output the current day's date;
  • Take no input and output all 365 days of the year in order;

Importantly, you only need to care about the month and day, not about the year, and you can assume that the year is not a leap year.


Output is the date in abbreviated Latin, as specified in this section in BNF, and as explained more verbosely in the next section.

<output> ::= <delay> <event> <month>
<event> ::= "Kal" | "Non" | "Eid"
<month> ::= "Ian" | "Feb" | "Mar" | "Apr" | "Mai" | "Iun" | "Iul" | "Aug" | "Sep" | "Oct" | "Nov" | "Dec"
<delay> ::= "" | <one-day-delay> | <n-days-delay>
<one-day-delay> ::= "prid"
<n-day-delay> ::= "a d" <roman-numeral>
<roman-numeral> ::= "III" | "IV" | "V" | "VI" | "VII" | "VIII" | "IX" | "X" | "XI" | "XII" | "XIII" | "XIV" | "XV" | "XVI" | "XVII" | "XVIII" | "XIX"

How do you write dates in abbreviated Latin?

Adapted from How do you write dates in Latin?

There are 36 special days in the year.

  • A date which is a special day is encoded by giving the name of that special day;
  • A date which is just before a special day is encoded by writing prid followed by the name of that special day;
  • Another day is encoded by writing a d followed by the number of days between that date and the next special day, counting inclusively, using Roman numerals, followed by the name of that special day.

Counting inclusively, there are for instance 3 days between January 3rd and January 5th.

The Roman counting system is oddly inclusive to modern taste. Whenever we would say that something is n days earlier, the Romans would have said n+1. The day just before the special day is two days before it (we'd say one day) and uses prid instead of numbering, so the unnamed days start their numbering at 3.

The 36 special days are:

  • The Kalendae, first day of the month: 01/01, 02/01, ..., 12/01, written Kal <month>, respectively: Kal Ian, Kal Feb, Kal Mar, Kal Apr, Kal Mai, Kal Iun, Kal Iul, Kal Aug, Kal Sep, Kal Oct, Kal Nov, Kal Dec;
  • The Nonae, 5th or 7th day of the month: 01/05, 02/05, 03/07, 04/05, 05/07, 06/05, 07/07, 08/05, 09/05, 10/07, 11/05, 12/05, written Non <month>, respectively: Non Ian, Non Feb, Non Mar, Non Apr, Non Mai, Non Iun, Non Iul, Non Aug, Non Sep, Non Oct, Non Nov, Non Dec;
  • The Ides, 13th or 15th day of the month: 01/13, 02/13, 03/15, 04/13, 05/15, 06/13, 07/15, 08/13, 09/13, 10/15, 11/13, 12/13, written Eid <month>, respectively: Eid Ian, Eid Feb, Eid Mar, Eid Apr, Eid Mai, Eid Iun, Eid Iul, Eid Aug, Eid Sep, Eid Oct, Eid Nov, Eid Dec.

Note the Nonae and Ides come two days later in the four months of March, May, July and October.

Because of these rules, only Roman numerals between 3 and 19 are required.

Test cases

mm/dd  -->  abbrev. Lat.

01/01  -->  Kal Ian
01/02  -->  a d IV Non Ian
01/03  -->  a d III Non Ian
01/04  -->  prid Non Ian
01/05  -->  Non Ian
02/02  -->  a d IV Non Feb
02/27  -->  a d III Kal Mar
02/28  -->  prid Kal Mar
03/01  -->  Kal Mar
03/02  -->  a d VI Non Mar
04/02  -->  a d IV Non Apr
05/02  -->  a d VI Non Mai
06/02  -->  a d IV Non Iun
07/02  -->  a d VI Non Iul
08/02  -->  a d IV Non Aug
08/05  -->  Non Aug
09/02  -->  a d IV Non Sep
10/02  -->  a d VI Non Oct
10/15  -->  Eid Oct
10/12  -->  a d IV Eid Oct
10/13  -->  a d III Eid Oct
10/14  -->  prid Eid Oct
10/17  -->  a d XVI Kal Nov
11/02  -->  a d IV Non Nov
12/02  -->  a d IV Non Dec
12/14  -->  a d XIX Kal Ian
12/30  -->  a d III Kal Ian
12/31  -->  prid Kal Ian


  • This is code-golf, the shortest code in bytes wins!
  • \$\begingroup\$ Presumably 31st of December is prid Kal Ian? Might be a good test case. \$\endgroup\$
    – Neil
    Dec 3, 2023 at 19:15
  • \$\begingroup\$ @Neil Correct; added. \$\endgroup\$
    – Stef
    Dec 3, 2023 at 19:21
  • \$\begingroup\$ If the input really is flexible, can we just take the month and the day as two separate arguments? \$\endgroup\$
    – Arnauld
    Dec 3, 2023 at 20:07
  • \$\begingroup\$ I suggest <delay> ::= "" | <one-day-delay> | <n-days-delay> \$\endgroup\$
    – matteo_c
    Dec 3, 2023 at 20:12
  • \$\begingroup\$ @matteo_c You are absolutely right! \$\endgroup\$
    – Stef
    Dec 3, 2023 at 21:55

3 Answers 3


Charcoal, 163 bytes

F³⁶⁵⊞υωF¹⁹F¹²F³§≔υ⁺⁺I§⪪”)¶O↥…⊞H₂;≦'⪫⦃π0S|”³κ∧λ⊗⁻×⁴λ∨№1358Iκ²ι⪫Φ⟦׋ι¹⁷a d§⪪”{⧴,π⁶δυW≦χVM⪫mSDfZ<hνHm¬⍘ψc⎇⊖MlR5ρν” ι§⪪KalNonEid³λ§⪪”>-b∧⊖αθ?|¬Y≔⁼IΦ«wS▷NAº⁸Fω&↗”³κ⟧μ υ

Try it online! Link is to verbose version of code. Outputs all 365 days. Explanation:


Allocate an array of 365 days so that cyclic indexing will fill in some of the January values.


Start from a d XIX Kal Feb...a d XIX Kal Ian and work forward to Kal Feb...Kal Ian.


Loop from Feb to Ian. (This avoids a negative number below.)


Loop over Kal, Non and Eid.


Calculate the day of year that this day would be (if it existed).

⪫Φ⟦׋ι¹⁷a d§⪪”...” ι§⪪KalNonEid³λ§⪪”...”³κ⟧μ 

Overwrite it with the name of this day, made up of four optional parts: a d, the day number (or prid), the special day, and the month, joined with a space (which is at the end of the above line).


Output all of the days of the year.


Jelly, 125 bytes

“Y8ṁ`yƈʋIƊĠSṖḶ⁾İ2’ṃ“XVI ”Ḳ“a d ”;Ɱ““prid”;
“-gBƥ]ṢḲ@’b6s2+“¢Ñ‘j€8FRUị¢ṭ€"“¡Qḟ8i,ȷıƊḳė¦øsÑNpq>ė7 “¢Zıƒ>ɠ’ṃØas€3ŒtƊŒpṙ1¤Ẏ⁸ịṚ¹ƇK

Try it online!

A pair of links called as a monad, taking an integer from 0 to 364 and returning a string representing the relevant date. (Technically will also work for numbers outside that range since it uses a modular index into a list of all 365 possibilities.)


“Y8ṁ`yƈʋIƊĠSṖḶ⁾İ2’ṃ“XVI ”Ḳ“a d ”;Ɱ““prid”;                                          # ‎⁡Helper link: called as a nilad, generates the delay parts of the date
“Y8ṁ`yƈʋIƊĠSṖḶ⁾İ2’                                                                  # ‎⁢Base 250 integer 84034955351979905312914389471555862301
                  ṃ“XVI ”                                                           # ‎⁣Base decompress into "XVI "
                         Ḳ                                                          # ‎⁤Split on spaces
                          “a d ”;Ɱ                                                  # ‎⁢⁡Prepend each with "a d "
                                  ““prid”;                                          # ‎⁢⁢Prepend an empty string and then "prid"
“-gBƥ]ṢḲ@’b6s2+“¢Ñ‘j€8FRUị¢ṭ€"“¡Qḟ8i,ȷıƊḳė¦øsÑNpq>ė7 “¢Zıƒ>ɠ’ṃØas€3ŒtƊŒpṙ1¤Ẏ⁸ịṚ¹ƇK  # ‎⁢⁤Main link: takes an integer and returns a string representing the date
“-gBƥ]ṢḲ@’                                                                          # ‎⁣⁡Base 250 integer 2833073888199044565
          b6                                                                        # ‎⁣⁢Convert to base 6
            s2                                                                      # ‎⁣⁣Split into pieces of length 2
              +“¢Ñ‘                                                                 # ‎⁣⁤Add 1 to the first member of each sublist and 16 to the second
                   j€8                                                              # ‎⁤⁡Join each with 8
                      F                                                             # ‎⁤⁢Flatten
                       R                                                            # ‎⁤⁣Ranges from 1..z for each z in this list
                        U                                                           # ‎⁤⁤Reverse each range
                         ị¢                                                         # ‎⁢⁡⁡Index into the helper link
                           ṭ€"                                            ¤         # ‎⁢⁡⁢Tag each member of each of the sublists of strings onto the corresponding sublist from the following:
                              “¡Qḟ8i,ȷıƊḳė¦øsÑNpq>ė7 “¢Zıƒ>ɠ’                       # ‎⁢⁡⁣Base 250 integers 302811639626768516702588802453858478870563499076533, 2309009953410
                                                                     Ɗ              # ‎⁢⁡⁤Following as a monad (used to avoid having to have ¤ after each of the nilads in the following)
                                                             ṃØa                    # ‎⁢⁢⁡- Base decompress into lowercase letters
                                                                s€3                 # ‎⁢⁢⁢- Split each into pieces length 3
                                                                   Œt               # ‎⁢⁢⁣- Convert to title case
                                                                      Œp            # ‎⁢⁢⁤Cartesian product
                                                                        ṙ1          # ‎⁢⁣⁡Rotate left one (moves Ian Kal to the end)
                                                                           Ẏ        # ‎⁢⁣⁢Join outer lists (after this step we have all 365 dates but with their component pieces in the wrong order and not yet joined with spaces)
                                                                            ⁸ị      # ‎⁢⁣⁣Index the main link’s argument into this
                                                                              Ṛ     # ‎⁢⁣⁤Reverse
                                                                               ¹Ƈ   # ‎⁢⁤⁡Keep only those that are non-empty (removes the space from before the exact special dates)
                                                                                 K  # ‎⁢⁤⁢Join with spaces

Created with the help of Luminespire.


JavaScript (ES6),  268 ... 262  252 bytes

Expects (month)(day).

m=>d=>([t=0,q=2384>>m&2^4,q+8,m-2?~-m%1.7^31:28].every(k=>(n=k+1-d)<0&&++t,A="KalNonEidIanFebMarAprMaiIunIulAugSepOctNovDecIanI II III IV V VI VII VIII IX  ".match(/[IVX]* |.../g))|n?n-1?"a d "+(n>8?"X":"")+A[n%10+16]:"prid ":"")+A[t%3]+" "+A[m+=2^t>2]

Try it online!


The every() loop looks for the first 0-indexed special day that is greater than or equal to \$d-1\$.

Once completed:

  • The number of days before the next special day is loaded in \$n\in[0\dots18]\$.
  • The type of the special day is loaded in \$t\in[0\dots3]\$:
    • \$t=0\$ → first day of the current month
    • \$t=1\$ → Nonae
    • \$t=2\$ → Ides
    • \$t=3\$ → first day of the next month


  • q = 2384 >> m & 2 ^ 4 gives the 0-indexed day of the Nonae for month \$m\$ (either \$4\$ or \$6\$).
  • q + 8 gives the 0-indexed day of the Ides for month \$m\$ (either \$12\$ or \$14\$).
  • ~-m % 1.7 ^ 31 gives the number of days in month \$m\$, except for February which is processed separately. I first used this decimal remainder trick in one of my solutions to this other challenge.

Lookup string

Most substrings are stored into a single lookup string:

"KalNonEidIanFebMarAprMaiIunIulAugSepOctNovDecIanI II III IV V VI VII VIII IX  "
  special                 months                     Roman numeral suffixes
   days         (wrapping from Dec to Ian)           (followed by a space)

which is split with the following regular expression:

/[IVX]* |.../g  // either a Roman numeral suffix followed by a space
                // or 3 characters

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.