Finally, we have all the background knowledge required to understand how we might calculate the French Republican Calendar. This is a calendar that was created and saw widespread use during the French Revolution for around 12 years from 1793 to 1805, when Napoleon abolished it in favour of the Gregorian calendar. These days, it is mainly of interest historically, as we might see in names of events like the Coup of 18 Brumaire.

The idea of the calendar is simple: every year is divided into 12 months of 30 days each, named Vendémiaire, Brumaire, Frimaire, Nivôse, Pluviôse, Ventôse, Germinal, Floréal, Prairial, Messidor, Thermidor, Fructidor. Since a solar year is around 365¼ days, it adds 5 complementary days, and one more in leap years: la Fête de la Vertu, la Fête du Génie, la Fête du Travail, la Fête de l’Opinion, la Fête des Récompenses, and la Fête de la Révolution (leap years only). The first year started on September 22, 1792, the founding of the French Republic, which also happens to be the autumnal equinox.

The part about the calendar that I found intriguing was the way it handled leap years — every year started on the date of the autumnal equinox at the Paris Observatory, no matter what. As such, a year is a leap year if the next autumnal equinox happens 366 days later instead of the normal 365, and the calendar will never drift against the seasons — at least if we followed the calendar as originally specified. Unfortunately, perhaps due to laziness, all the versions of the calendar I could find online used alternative leap year schemes that reduced the calendar into a mere variant of the Gregorian calendar, complete with its ability to drift out of sync with the seasons.

The most popular scheme for leap years these days is the so-called Romme method, which follows the same leap year rules as the Gregorian calendar, except applied to the years of the French Republic. I find it distasteful, mostly because it made years 4, 8, and 12 leap years when historically, years 3, 7, and 11 were leap years instead, thus altering history on top of eliminating one of the intriguing features of the calendar.

For this reason, I constructed my own version based completely on equinoxes, and I will be explaining exactly how to calculate the dates so that no one has to keep making Romme versions out of ignorance.

Date of the Equinox

To understand how we might calculate the French Republican Calendar, we must first understand what it means to take the date of an equinox. This may sound simple, as in part 3 we explored how to do exactly that. However, as you may recall from part 2, there are many different time scales, and the JPL DE440 and DE441 ephemerides we used yielded Barycentric Dynamical Time (TDB), which has no relation to the sun.

So what do we do? Well, it’s quite obvious we need solar time — none of the uniform time scales were invented back then during the French Revolution, and until very recently, people have always conceptualized a day based on the motion of the sun.

Naturally, this means we need to use UT1 plus some offset to account for the longitude of the Paris Observatory, which is 2°20′14.025″ E, or 2.337229° E. Using the formula from part 2, we can see that:

MSTPOUT1=λPO1h15°=2.337229°1h15°=0.155815 h=560.935 s\begin{align*}\text{MST}_\text{PO} - \text{UT1} &= \lambda_\text{PO} \frac{1\,\text{h}}{15\degree} = 2.337229\degree\cdot\frac{1\,\text{h}}{15\degree} \\ &= 0.155815~\text{h} = 560.935~\text{s} \end{align*}

This means that in general, the mean solar time in Paris Observatory is around 9 minutes, 21 seconds ahead of UT1. Therefore, we simply have to convert the TDB value of the equinox into UT1+00:09:21 and take the date.1

How would we do that? You’ll notice in the code that we again used the skyfield library, but here’s how it works:

  1. We know that TDB is within a few milliseconds of TT, and most of the difference is periodic, so we compute the difference as a series of sinusoids, which the skyfield library sourced from this USNO publication (page 15). Subtracting this difference from TDB yields the TT value.
  2. Recall that ΔT=TTUT\Delta T = \text{TT} - \text{UT}. To find UT1 from TT, we must subtract the value based on the ΔT\Delta T at that point in time. This is not easily predictable, so we instead turn to the tables published by IERS.
  3. Finally, after obtaining the UT1, we add 561 seconds to obtain UT1+00:09:21.

And now we have the date of the equinox!

The astute of you might have noticed a quirk based on our discretization process — if the equinox is close to noon, it does not really matter how accurate our results are, but if the equinox is close to midnight, then the tiniest fraction of a second off will result in the wrong date. Fortunately, it is rather unlikely. The only time the equinox is within a second of midnight in the data used for my version is in the year -12584, at which point we have much bigger precision issues from the uncertainty in ΔT\Delta T.

Converting the Dates

How do we convert the dates from the French Republican Calendar to the Gregorian calendar and vice versa? If you remembered part 1, you probably expected Julian Day Numbers (JDNs), and you would be right.

Since we know the start of year YY by calculating the date of the equinox, we can store this number as a JDN JDY,1,1\text{JD}_{Y,1,1}. Then, if we assign numerical value MM to the months (1 for Vendémiaire, 2 for Brumaire, …, 12 for Fructidor), and use DD the 1-based day of the month, we can easily calculate the JDN of any given day:

JDY,M,D=JDY,1,1+30M+D31\text{JD}_{Y,M,D} = \text{JD}_{Y,1,1} + 30M + D - 31

To extend this to complementary days, we treat them as numbered days for a 13th pseudo-month, e.g. la Fête de la Révolution as the 6th day of the 13th month, and this formula will work.

Once we have the JDN, we can use the algorithms given in part 1 to convert them to Gregorian dates.

If we want to go the other way, we convert from the Gregorian calendar to JDN JJ first, and then follow this algorithm:

  1. Identify the year YY such that JDY,1,1J<JDY+1,1,1\text{JD}_{Y,1,1} \le J < \text{JD}_{Y+1,1,1}. This can be done through binary search.
  2. Then, compute the date offset O=JJDY,1,1O = J-\text{JD}_{Y,1,1}. Perform the integer division of OO by 30 to obtain O=30Q+RO = 30Q + R. The month is Q+1Q+1 and the day is R+1R + 1. Complementary days will again be the 13th “month.”

Compact Storage

Storing the JDN values of the 1 Vendémiaire of every year will allow easy conversion to and from Gregorian, but this is not efficient — the JDN range for the full French Republican years covered by the DE441 ephemeris is [3099887,8000190][-3\,099\,887,8\,000\,190], which requires at least 24 bits per year to store.

Since a leap year happens either 4 or 5 years after the previous one for the range our ephemerides cover, it only takes 1 bit of data to cover every leap year cycle. In fact, since a leap year happening 5 years after the previous one is a rare occurrence (less than once per century), we can likely store the intervals between these occurrences instead, yielding even more savings. We only need to also store the number of the first year y0y_0 and the JDN of its first day JDy0,1,1JD_{y_0,1,1} to reconstruct the whole sequence.

However, I did not ultimately choose this approach, since they make things like looking up whether a year is a leap year or not more cumbersome. Instead, I opted to simply store whether every year is a leap year or not. This would theoretically require 1 bit per year, plus the fixed overhead of y0y_0 and JDy0,1,1JD_{y_0,1,1}. Since we have data for some 30 thousand years, it should take around 3.7 KiB. In practice, I stored it as JSON for simplicity, taking 2 bytes per year. However, after gzip, it only uses 452 bytes, even better than the “theoretical” value (mostly due to the patterns described above). This is good enough for my purposes, since I am embedding it in the webpack JavaScript bundle, which is most certainly compressed when served to the client.

Then, to quickly compute JDy,1,1JD_{y,1,1} for the conversions above, I applied a prefix sum to the lookup table of whether a year is a leap year or not, obtaining the array AA. I opted to prepend a 0 to AA, such that A[yy0]A[y-y_0] is the number of leap years in the range [y,y0)[y,y_0). We can then compute JDy,1,1\text{JD}_{y,1,1} efficiently as JDy0,1,1+365(yy0)+A[Yy0]\text{JD}_{y_0,1,1}+365(y-y_0)+A[Y-y_0]. This takes O(1)O(1) time.

Organization of Days

The French Republican Calendar organizes each month (all exactly 30 days long) into three décades of 10 days each. This is akin to the concept of weeks. The days of the week are named, perhaps uncreatively: primidi, duodi, tridi, quartidi, quintidi, sextidi, septidi, octidi, nonidi, and décadi.2

An interesting aspect of the French Republican Calendar is the rural variant, which named each day of the year after something associated with the rural economy. This was created during the French Revolution to replace the calendar of saints published by the Catholic Church, as the revolution wished to reduce their influence.

In the rural calendar, every quintidi is named after an agricultural tool, every décadi after an animal, and the other days after various plants. The naming is supposed to correspond with the time of the year. Perhaps, for this reason, an exception is made for the month of Nivôse, which starts around the December solstice, representing the height of winter in France: the days that would normally be named after plants were instead named after minerals.

If you want to see the exact names of every day, you can do so on my calendar. The names are displayed in French beneath the Gregorian date. Hover (or tap if you are on mobile) to see the English translation. For example, this post is published on the 19th of Ventôse, which is named cerfeuil, meaning chervil, which is sometimes called French parsley.

The French Revolution also adopted a new way of reckoning the time of day — the decimal time. This partitions a day into 10 equal hours, each divided into 100 equal minutes, which itself is divided into 100 equal seconds. This results in a decimal hour that is 2.4 normal hours, a decimal minute that is 1.44 normal minutes, and a decimal second that is 0.864 normal seconds. This makes it very easy to convert between decimal time and fractional dates, which are used quite often in astronomical calculations. For example, decimal time 5:67:72 (around 13:37:31) on January 1, 2000 can be represented as 2000-01-01.56772. This is also shown on my calendar webapp.

Precision Issues

A downside with calculating calendars based on astronomy is that we are at the mercy of our ability to predict the future. The precision of our calculations inevitably drops as we dig further into the past or predict further into the future. For this reason, the values in the distant past or future should be taken with a grain of salt. It is, however, important to note that my calculations are almost certainly correct from year 1 of the French Republic (1792 CE) to a hundred years in the future. But where do the errors come from?

We do a fairly good job of predicting the motion of celestial bodies. While the ephemerides did not make their precisions explicit, we can nevertheless infer it. For example, the paper about DE430 and DE431 claims that:

Very long baseline interferometry measurements of spacecraft at Mars allow the orientation of the ephemeris to be tied to the International Celestial Reference Frame with an accuracy of 0″.0002. This orientation is the limiting error source for the orbits of the terrestrial planets, and corresponds to orbit uncertainties of a few hundred meters.

This means that the predicted position of the Earth may differ by less than 1 km. Given that the Earth orbits at 29.78 km/s on average, this is a very small error. (Note that the paper for DE440 and DE441 claims a similar accuracy.)

Most of the error in our calculation instead come from our knowledge of ΔT\Delta T. In part 2, we mentioned how the its standard deviation was measured in hours once we get a few millennia from the present. The same source gives the following formula for standard deviation:

σ=365.25NyrNQ3(1+NM)\sigma = \frac{365.25N}{\text{yr}}\sqrt{\frac{NQ}{3}\cdot\left(1+\frac{N}{M}\right)}

where NN is the difference between the target year and the calibration year (-500 for years before 500 BCE, 2005 for future years), MM is 2500 years, and Q=0.058ms2/yrQ = 0.058\,\text{ms}^2/\text{yr}. This means that at the extreme end of the ephemeris (17191 CE), σ=252768s\sigma = 252\,768\,\text{s}, which is almost 3 days!

Intuitively, this kind of uncertainty makes sense, since we can’t predict far in advance whether we need a leap second or not. Most of this is caused by the variable rate of Earth’s rotation, which can be caused by things like earthquakes. For example, the 2004 Sumatra Earthquake shortened the length of a day by 2.68μs2.68\,\text{μs}, which changed ΔT\Delta T by around 1 second per millennium.

This means that leap years and the Gregorian date conversions in my version of the French Republican Calendar more than a few millennia from present may be off, and those in the far ends of ephemerides are probably off. However, despite this, I find it remarkable that this is about as close to the true values as we could get with the current state of human knowledge. The algorithm works: as more accurate ephemerides get published, we simply have to rerun the script and the future (and perhaps the past) values will get progressively more accurate.

For some, this uncertainty is disturbing, instead preferring a calendar system that is fully predictable. For others, this uncertainty is a part of life — the price we pay for a calendar that truly reflects the seasons for the next million years. In the future, we shall examine two distinct calendar systems that reflect the extreme positions: the fixed cycles of the Mayan calendars, a reflection of the tropic civilization for whom the seasons did not really exist, and the Chinese calendar, a reflection of the burning desire to perfectly track the motions of the sun and the moon.


  1. You may have noticed the slight rounding here. This is to avoid adding undue precision to the calculation. The truth is that I am unable to find a precise time offset from UT1, and calculating it based on longitude is inherently imprecise. As you’ll see, this is not going to be a problem — for years where it might be, the uncertainty in ΔT\Delta T dominates. 

  2. These names literally mean first day, second day, third day, etc. Perhaps they should have kept and extended the Roman names for the days of the week instead, as those were based on the celestial bodies, i.e. lundi for Moon-day, mardi for Mars-day, mercredi for Mercury-day, jeudi for Jupiter-day, vendredi for Venus-day. The French equivalent for Saturday and Sunday are samedi (Sabbath-day) and dimanche (Lord’s day), but could be reverted to something derived from the original Latin names, e.g. saturdi (Saturn-day) and solidi (Sun-day). We are still three days short, but we could use the other planets — perhaps something like urandi (Uranus-day), neptundi (Neptune-day), and terridi (Earth-day).