Created by Dr. Irv Bromberg, University of Toronto, Canada

[Click here to go back to the Symmetry454 / *Kalendis* home page]

The pseudocode calendrical calculations presented here are adapted from Gregorian and Julian calendar functions published by Reingold and Dershowitz, although those authors explicitly ignored the Revised Julian calendar (see page 57, footnote 4 in Calendrical Calculations: The Ultimate Edition, referred to hereinafter as CC4).

In the course of adding the Revised Julian calendar to my freeware *Kalendis* calendrical calculator, I found that there were no published sources for implementing its calendrical calculations, and that it is impossible to reproduce the published dates for this calendar unless its proleptic epoch is set equal to that of the Gregorian calendar.

This web page is freely and unconditionally presented in the public domain for anyone who wishes to implement the necessary functions for any purpose.

**Introduction to the Revised Julian Calendar****Epoch****Northward Equinox (Northern Hemisphere Vernal Equinox, March Equinox)****Overview of Revised Julian Calendrical Calculations****Fixed Days (ordinal day numbers relative to an epoch)****Check for Leap Year****Convert a Revised Julian Date to Fixed Days****Convert Fixed Days to a Revised Julian Date****Determine the Weekday**

For the history, correspondence to the Julian and Gregorian calendars, Easter controversies, list of countries and churches that have adopted this calendar and when, and criticism, please see the Wikipedia article here: https://en.wikipedia.org/wiki/Revised_Julian_calendar.

The Revised Julian calendar was first proposed at the 1923 Orthodox Church synod by Serbian scientist Milutin Milankovitch.

In 900 Julian years there are ^{900}/_{4} = 225 leap days, but the Revised Julian leap rule omits seven of nine century leap years, leaving 225 − 7 = 218 leap days per 900-year cycle. Thus the calendar mean year is 365 + ^{218}/_{900} days, but this is actually a double-cycle that reduces to 365 + ^{109}/_{450} = 365.242 days, or exactly 365 days 5 hours 48 minutes 48 seconds, which is exactly 24 seconds shorter than the Gregorian mean year of 365.2425 days, so in the long term on average the Revised Julian calendar pulls ahead of the Gregorian calendar by 86400 seconds per day / 24 seconds per year = 3600 years per day difference.

The number of days per Revised Julian cycle = 900 years × 365 days per common year + 218 leap days = 328,718 days. Taking this mod 7 leaves a remainder of 5, so like the Julian calendar, but unlike the Gregorian calendar, the Revised Julian calendar cycle does not contain a whole number of weeks. Therefore, a full repetition of the Revised Julian leap cycle with respect to the seven-day weekly cycle is seven times the cycle length = 7 × 900 years per cycle = 6300 years.

Instead of developing a fixed arithmetic Easter *computus* having a mean year equal to that of the Revised Julian Calendar, the synod proposed adoption of an astronomical rule (see the detailed criteria specified in the paragraph starting with The synod also proposed

on the Wikipedia page at https://en.wikipedia.org/wiki/Revised_Julian_calendar). Nevertheless, apparently because of a lack of authoritative consensus regarding the specific criteria to employ for such calculations, and perhaps the inherent uncertainties of astronomical calculations (especially when a variety of methods are compared), most Orthodox Churches continue to use the Easter *computus* of the Julian calendar, ignoring the problem that its mean year is 11 minutes and 12 seconds longer than the mean year of the Revised Julian calendar, and a few Orthodox Churches use the Gregorian Easter *computus*, ignoring the problem that its mean year is 24 seconds longer than the mean year of the Revised Julian calendar.

Easter is a feast, not a planet. You do not determine it to hours, minutes and seconds.

— Johannes Kepler, 1613 (see here, page 40 at the bottom, 195.)

The proleptic epoch of the original Julian calendar was on the Saturday before the Monday that was the epoch of the Gregorian calendar. In other words, Gregorian 1 January 1 AD = Julian 3 January 1 AD.

The Revised Julian reform, however, not only changed the leap rule but also made the epoch the same as that of the Gregorian calendar. This seems to have been carried out implicitly, and even scientific articles made no mention of this epoch shift.

Nevertheless, it is impossible to implement calendrical calculations and calendar date conversion software without appreciating this detail and taking the 2-day shift (with respect to the original Julian calendar) into account. If the original Julian calendar epoch is mistakenly used in such calculations then there is no way to reproduce the currently accepted dating of the Revised Julian calendar, which yields no difference between Gregorian and Revised Julian dates from the 17^{th} to the 28^{th} centuries and most other centuries since the start of the Christian era (including the two first), assuming that both calendars start dates at Local Mean Midnight.

The following is a scatter plot of actual astronomical northward equinox moments as numerically integrated by SOLEX 11 using DE421 mode with extended (80-bit) floating point precision, high integration order (18^{th} order), and forced solar mass loss (forced

means taken into account at all times). SOLEX can automatically search for northern hemisphere spring equinox moments by finding when the solar declination crosses the celestial equator in the northward direction, and then it outputs that data as the Terrestrial Time (TT) day and fraction of day relative to 1 January 2000 at noon (J2000.0 epoch = Julian Day 2451545.0 = *Rata Die* 730120.5). The progressive tidal slowing of the Earth rotation rate was accounted for by subtracting ΔT as calculated by the Espenak-Meeus polynomial set recommended at the NASA Eclipses web site to obtain the J2000.0-relative Universal Time (UT) moments, which were then properly converted to Revised Julian dates and Jerusalem local apparent time, taking local apparent midnight as the beginning of each calendar day. The year range of the chart was limited to dates before the year 4400 AD, because by then ΔT is expected to accumulate to about six hours, with an uncertainty of less than 2+^{1}/_{2} hours.

The chart shows that the average long-term astronomical equinox drift of the Revised Julian calendar is small, at least until 4400 AD. Aside from astronomical drift of the equinox, the cycle's medium-term wobble (jitter) spans 2+^{163}/_{450} days = 2.362 days because the leap years of the Revised Julian calendar are not distributed as smoothly as possible: they regularly occur at 4-year intervals but there are 8-year gaps at 7 of 9 centurial years in each cycle. Compare this with the Gregorian calendar jitter = 2+^{79}/_{400} days = 2.1975 days, which is less because it has only 400 years per cycle and only one 8-year gap per cycle. The minimum possible jitter for a reduced leap day solar calendar is one day minus ^{1}/_{(years per cycle)} of a day, for example the original Julian calendar jitter is only 4 − ^{1}/_{4} = ^{3}/_{4} day = 0.75 day (on the other hand, the astronomical equinox rapidly drifts through the original Julian calendar at a rate of about one calendar day earlier per 130.90 years because its calendar mean year is about 11 minutes longer than the mean northward equinoctial year).

Refer to CC4 methods for handling BC dates and the traditional omission of a year zero, both of which are ignored here. As a consequence, using the calendrical calculations presented herein, the year prior to 1 AD was year zero, and dates before year zero yield negative year numbers.

CC4 defines the MOD operator as *x* MOD *y* = *modulus*( *x*, *y* ) = *x* − *y* × *floor*( *x* / *y* ), because that expression is valid for negative and floating point operands, returning the remainder from dividing *x* by *y* while discarding the quotient (see the *modulus* function in CC4 on page 21 at the top, equation 1.17). Expressions like *floor*( *x* / *y* ) return the quotient from dividing *x* by *y* while discarding the remainder.

If you wish to copy/paste programming code from this web page into a computer program note that certain symbols, used for appearance sake, need to be adjusted: convert × to *, convert − to -, and extra spaces included for readability may be automatically dropped by the program editor. Pay attention to how funtions return results in your chosen programming language, especially for the case where multiple values are returned together: { *year*, *month*, *day* }. I have intentionally employed undeclared self-documenting verbose variable names.

Calendrical calculations are made consistent and straightforward for arithmetic operations if dates are first converted to an ordinal number of days relative to an agreed-upon epoch, in this case the Revised Julian epoch, which was the same as the Gregorian epoch. To find the difference between any two Revised Julian dates, convert both to ordinal day numbers and simply subtract. To find a past or future date, convert a given date to an ordinal day number, subtract or add the desired number of days, then convert the result to a Revised Julian date.

The calendrical calculation functions given here will not crash

if an invalid date is given. To verify that a given date is a valid Revised Julian date, convert it to an ordinal day count and then back to a Revised Julian date — if the final date differs from the given date then the given date is invalid. This method should also be used to validate any implementation of calendrical calculations, by iteratively checking thousands of random and sequential dates for such errors.

To convert a Revised Julian date to any other calendar, first convert it to an ordinal day number, and then all that is needed is a function to convert the ordinal day number to that calendar. To convert a date from any other calendar to a Revised Julian date, first convert that calendar date to an ordinal day number, then convert the ordinal number to the Revised Julian date.

The following constant defines midnight at the start of (proleptic) Revised Julian date Monday, 1 January 1 AD as the beginning of the first ordinal day. This moment was Julian day number 1721425.5:

`CONSTANT `*RJepoch* = 1

CC4 outlines functions for Gregorian and Julian calendar conversions, as well as many other calendars, always calculating in terms of the ordinal day number, which they call the fixed date

or *rata die* (RD), assigning the number 1 to the Gregorian calendar epoch. The arithmetic herein, by using the same ordinal day numbering epoch, is fully compatible with all CC4 functions for calendrical calculations and date inter-conversions.

One can assign a different integer to the Revised Julian epoch, for the purpose of numbering ordinal days relative to some other epoch, but if you do so then you must always take the epoch difference into account when using any CC4 calendar functions and when converting an ordinal day number to a weekday number.

Optionally the ordinal day number can include a fractional component to represent the time as the elapsed fraction of a day. For example, the ordinal day number of the J2000.0 moment (1 January 2000 AD at Noon) was 730120.5.

`FUNCTION`

*isLeapYear*(*year*) ' this logic avoids a nested IF`IF`

*year*MOD 100 = 0 THEN ' check for centurial year*Century*= (*year*/ 100) MOD 9`' century years are common years except for the 2nd and 6th centurial years per cycle`

*isLeap*= (*Century*=2) OR (*Century*=6)

`ELSE ' non-centurial year is leap only if divisible by 4`

*isLeap*= (*year*MOD 4 = 0)

`END IF`

`RETURN`

*isLeap*

`END FUNCTION`

Convert a Revised Julian date { *year*, *month*, *day* } to the corresponding unique fixed day number. Note that *RJepoch* is offset by subtracting one, but we explicitly include it so that *RJepoch* can be assigned a value other than one for an alternate ordinal day numbering scheme:

`FUNCTION`

*RevisedJulianToFixed*(*year*,*month*,*day*)*PriorYear*=*year*− 1*FixedDays*=*RJepoch*+ 365 ×*PriorYear*+ floor(*PriorYear*/ 4) + floor((367 ×*month*− 362) / 12) +*day*− 1`' If`

*month*is after February then subtract 1 day for a leap year or subtract 2 days for a common year:`IF`

*month*> 2 THEN`IF`

*isLeapYear*(*year*) THEN*FixedDays*=*FixedDays*− 1 ELSE*FixedDays*=*FixedDays*− 2

`END IF`

`' Finally subtract a day for each prior century year (most of which are non-leap) and then add back in the number of prior century leap years:`

*PriorCenturies*= floor(*PriorYear*/ 100)*FixedDays*=*FixedDays*−*PriorCenturies*+ floor((2 ×*PriorCenturies*+ 6) / 9)`RETURN`

*FixedDays*

`END FUNCTION`

Convert an ordinal day number to the corresponding Revised Julian { *year*, *month*, *day* }. Note that subtracting *RJepoch* is here offset by adding one, but we explicitly include it so that *RJepoch* can be assigned a value other than one for use with an alternate ordinal day numbering scheme:

`FUNCTION`

*FixedToRevisedJulian*(*FixedDays*)`' start by removing any fractional time-of-day portion:`

*Days*=*floor*(*FixedDays*) −*RJepoch*+ 1*PriorCenturies*=*floor*(*Days*/ 36524)*RemainingDays*=*Days*− 36524 ×*PriorCenturies*−*floor*((2 ×*PriorCenturies*+ 6) / 9)*PriorSubcycles*=*floor*(*RemainingDays*/ 1461)*RemainingDays*=*RemainingDays*MOD 1461*PriorSubcycleYears*=*floor*(*RemainingDays*/ 365)*year*= 100 ×*PriorCenturies*+ 4 ×*PriorSubcycles*+*PriorSubcycleYears**RemainingDays*=*RemainingDays*MOD 365`IF`

*RemainingDays*= 0 THEN`' This is either the 365th day of a common year, or the 365th or 366th day of a leap year.`

`' Either way, we have to decrement the year because we went one year too far:`

*year*=*year*− 1`IF`

*isLeapYear*(*year*) AND*PriorSubcycles*=0 THEN*RemainingDays*=366 ELSE*RemainingDays*=365

`END IF`

*PriorDays*=*RemainingDays*− 1`IF`

*isLeapYear*(*year*) THEN*correction*= 1 ELSE*correction*= 0`IF`

*PriorDays*< (31 + 28 +*correction*) THEN*correction*= 0 ELSE*correction*= 2 −*correction**month*=*floor*((12 × (*PriorDays*+*correction*) + 373) / 367)`' Finally, calculate the day number within the month`

`' by subtracting the Fixed days count for the start of the month from`

`' the originally given Fixed days count and then add one day:`

*day*=*FixedDays*−*RevisedJulianToFixed*(*year*,*month*, 1) + 1`RETURN {`

*year*,*month*,*day*}

`END FUNCTION`

Convert the ordinal number of days since the Revised Julian epoch to a weekday number (Sunday=1 through Saturday = 7):

`FUNCTION`

*WeekdayNumber*(*FixedDays*)`RETURN (`

*floor*(*FixedDays*) −*RJepoch*+ 1 ) MOD 7 + 1

`END FUNCTION`

The calendar epoch is explicitly included here so that alternative ordinal day numbering schemes can be employed. Don't be tempted to omit subtracting the *RJepoch* just because it is offset by adding +1. As written, this expression is robust even if you assign a value other than one to the epoch.

Updated Aug 15, 2024 (Symmetry454) = Aug 13, 2024 (Symmetry010) = Aug 12, 2024 (Revised Julian) = Aug 12, 2024 (Gregorian)