Additional Documentation

Julian Period Days

The most commonly used algorithm to convert to-and-from different Calendars is the JD (Julian period Day). You take your date from some calendar feed it into a function then out pops a JD. Then take that JD and feed it into the reverse function for a different calendar and out pops the date that is equivalent to the date of the first calendar. Essentially the JD is a continuous count of days from the Gregorian/Julian calendar year -4712:01:01 at noon. Jean Meeus in his book “Astronomical Algorithms” has a formula for doing this conversion. This formula is historically correct meaning that all historical Astronomical calculations for-the-most-part use it. The USNO has an online calculator for this formula.

Now I said “for-the-most-part” above because the formula mentioned above is astronomically inaccurate for all dates before Gregorian year 1582 October 15 the date that Pope Gregory introduced the Gregorian calendar. The results are that the Vernal Equinox gets earlier and earlier in the year the farther you go back in time because the leap years were wrong. There is another problem with this formula in that Pope Gregory only compensated for 10 days when in reality he should have compensated for 12 days so even this formula is still off by two days to this day.

Since the API that I have written is for the Badí’ calendar the Vernal Equinox calculations needed to be correct. This presented a few problems. I needed to find an algorithm that was Astronomically correct or write one myself. I know that both NASA and the USNO have an Astronomically correct formula, because they both have tables of the correct Vernal Equinox, but I was not able to find them. Even if I had found at least one of them, it would only have been for the Gregorian calendar. So as such I had to write my own formulas for both the Gregorian and Badí’ calendars. This required both to-and-from formulas or four formulas in total.

As mentioned elsewhere the Gregorian calendar uses a guestimation formula to determine the leap years so figuring out the leap years is rather easy. It is both consistent and regular. The Badí’ calendar, on the other hand, uses the sunset before the Vernal Equinox to determine the start of the year. There is little regularity in this, so determining leap years was a much bigger task, therefore the formula for the Badí’ calendar needed coefficients to get it in line with a proper representation of the JD when checking against the Gregorian calendar. In my code the Astronomically formula is used by passing either True or False to the keyword exact.

Gregorian Reform Dates

In year 1582 the next day after October 4 was October 15. Pope Gregory eliminated 10 days. As mentioned above my code supports two sets of formulas for deriving a Julian Period day for each calendar. That’s eight formulas in total four for each of the two calendars supported. The 10 days in the Gregorian calendar are just non-existent and Meeus’ historical formulas just jump over the 10 days. In my astronomical formulas the ten days do exist both in the Gregorian and the Badí’ calendars. However, there is a problem with this. I need to get the sunset for all days and only Meeus’ formula can do this. So although the ten reform days exist in my code, some information for them cannot be derived, i.e. sunsets. As of now this is how my code works for those ten days only. How to solve this? The only correct way is to rewrite all the astronomical code to work with a proleptic count of days such as the formulas I have written, but I am no astronomer, so I cannot do this. So it is what it is.

Origin Point of the Badí’ Calendar

There are two years starting on 0183-01-01 (2026-03-20) and 0216-01-01 (2059-03-19) that have a very a narrow overlap where the sunsets (Naw-Rúz) are correct as per the dates provided by the House of Justice. The remaining 50 dates were less of an issue. The calculations for latitude and longitude were originally derived completely by hand. Since my original calculations I have written a script that can automatically derive the best fit longitude for the two date mentioned above. Since the latitude has a much less affect on deriving sunsets I chose a latitude midway between the northern and southern limits of Tehran. All the code in the badidatetime/badi_calendar.py module is dependent on these values.

To get the longitudinal midway point, run the script below. It calculates the best fit longitude for the two years mentioned above. It runs for about 9 minutes.

$ ./contrib/misc/determine_lat_lon.py -oL

There is also a -F argument which can be added to the above script, it calculates the full 50 years, however, it will take up to 4 or 5 hours to run, so beware. The final midway point should be the same in either case, so running the script for the full 50 years would not give a better result.

Strftime and Strptime Methods

This API supports many more conversion formats than the standard Python library. Partially because The Badí’ Calendar has calendar designators that don’t exist in the Gregorian Calendar and there are a lot of formats in general that the standard library doesn’t support.

%a  Abbreviated weekday name                     Jal
%A  Full weekday name                            Jalál
%b  Abbreviated month name                       Bah
%B  Full month name                              Bahá
%c  Locale specific date and time. Equivalent
    to "%a %b %d %H:%M:%S %Y"                    Jal Bah 01 22:30:45 181
%C  Century as a space-padded decimal number.
    (The year divided by 100 then truncated
    to an integer.)                              15 or ' 1'
%d  Day of month as a zero-padded decimal
    number.                                      09
%-d Day of month as a decimal number.            9
%D  Date where year is without century.
    Equivalent to a localized %m/%d/%y.          19/01/81
%e  Day of the month as a space-padded decimal
    number.                                      15 or ' 1'
%f  Microseconds as a decimal number.            000000 - 999999
%G  ISO 8601 year with century as a zero-padded
    decimal number.                              0181
%h  Abbreviated month name (Same as %b).         Bah
%H  Hour (24-hour clock) as a zero-padded
    decimal number.                              00, 01, ..., 23
%-H Hour (24-hour clock) as a decimal number.    0, 1, ..., 23
%I  Hour (12-hour clock) as a zero-padded
    decimal number.                              01, 02, ..., 12
%j  Day of the year as a zero-padded decimal
    number.                                      001, 002, ..., 366
%-j Day of the year as a decimal number.         1, 2, ..., 366
%k  Hour (24-hour clock) as a space-padded
    decimal number.                              0 to 23
%:K Kull-i-Shay as a negative or positive
    decimal number.                              -5 to 4
%l  Hour (12-hour clock) as a space-padded
    decimal number.                              ' 1' to 12
%-l Hour (12-hour clock) as a decimal number.    1 to 12
%m  Month as a zero-padded decimal number.       01 - 19
%-m Month as a decimal number.                   1 - 19
%M  Minute as a zero-padded decimal number.      00, 01, ..., 59
%-M Minute as a decimal number.                  0, 1, ..., 59
%n  Newline character.                           \n
%p  Locale defined AM and PM.                    am or pm
%r  Locale defined 12-hour clock time (am/pm).   3:30:45 PM
%S  Second as a zero-padded decimal number.      00, 01, ..., 59
%-S Second as a decimal number.                  0, 1, ..., 59
%T  Locale defined 24-hour clock time.           15:30:45
%u  Weekday as a decimal number. [1(Jalál), 7]   1 - 7
%U  Week number of the year (Jalál as the first
    day of the week) as a zero-padded decimal
    number. All days in a new year preceding
    the first `Idāl are considered to be in
    week 0.                                      00, 01, ..., 52
%V  ISO 8601 week as a zero-padded decimal
    number with Jalál as the first day of the
    week. Week 01 is the week containing the
    4th of Bahá.                                 01, 02, ..., 52
%:V Váḥid as a zero-padded decimal number.       01 - 19
%w  Weekday as a decimal number. [0(Jalál), 6]   0 - 6
%W  Week number of the year (Jalál as the first
    day of the week) as a zero-padded decimal
    number. All days in a new year preceding
    the first Jalál are considered to be in
    week 0. It make no sense to start a week
    on different day in the Badí' Calendar. So
    this format is the same as %U.               00, 01, ..., 52
%x  Locale defined date representation.          08/16/81 (None);
                                                 08/16/181 (en_US);
                                                 16.08.181 (de_DE)
%X  Locale defined time representation.          21:30:00 (en_US);
                                                 21:30:00 (de_DE)
%y  Year without century as a zero-padded
    decimal number.                              00, 01, ..., 99
%-y Year without century as a decimal number.    0, 1, ..., 99
%Y  Year with century as a zero-padded decimal
    number.                                      0001, 0002, ..., 1161
%z  UTC offset in the form ±HHMM[SS[.ffffff]]
    (empty string if the object is naive).       (empty), +0000, -0400,
                                                 +1030, +063415,
                                                 -030712.345216
%:z UTC offset in the form ±HH:MM[:SS[.ffffff]]  (empty string if the
                                                  object is naive).
%Z  Time zone name (empty string if the object
    is naive).                                   (empty), UTC, GMT
%%  A literal '%' character.                     %