Festival Calendars¶
This section will cover the function for generating specific festival calendars:
as well as a generic function that allows you to choose the parameters
to generate any festival calendar, festival_calendar()
.
In addition, it introduces some utility functions:
All the code snippets below assume that you have imported heniautos
under the name ha like so:
>>> import heniautos as ha
The city-specific calendars differ in the times when the years start
and in the names of the months. The generic
festival_calendar()
method allows you to choose these
parameters for any other required Greek calendar (the specific methods
above are simply wrappers around festival_calendar()
).
The examples below will use athenian_festival_calendar()
since this is the one you are probably most interested in. This and
all the city-specific functions take the same parameters and most
parameters are optional. For the simplest use only the year is
required. The year, however, must be an integer according to
Astronomical Year Numbering. Years
BCE are represented as negative numbers but 1 BCE is 0 (not -1), 2 BCE
is -1, and so on, with the years offset by 1 in the positive
direction. To generate a calendar for 400 BCE:
>>> calendar = ha.athenian_festival_calendar(-399)
If you don’t want to work out the astronomical year numbering every time, you can use bce_as_negative()
:
>>> ha.bce_as_negative(400)
-399
So these two invocations are equivalent:
>>> calendar = ha.athenian_festival_calendar(-399)
>>> calendar = ha.athenian_festival_calendar(ha.bce_as_negative(400))
bce_as_negative()
is its own inverse but, so you don’t have to remember that (and because it could lead to some obscure code), there is an explicit inverse function negative_as_bce()
:
>>> ha.bce_as_negative(400)
-399
>>> ha.bce_as_negative(-399)
400
>>> ha.negative_as_bce(-399)
400
Year Tuples and FestivalDay
Objects¶
The calendar functions return a tuple of FestivalDay
objects (which are instances of namedtuple
), one
FestivalDay
for each day of the year.
>>> calendar = ha.athenian_festival_calendar(-399)
>>> len(calendar)
354
>>> calendar[0]
FestivalDay(jdn=1575526, month_name='Hekatombaiṓn', month_index=1, month=<AthenianMonths.HEK: 1>, month_length=29, day=1, doy=1, year='BCE 400/399', year_length=354, astronomical_year=-399)
The first item in the tuple in the example above would have these properties and values:
Property |
Value |
Meaning |
---|---|---|
jdn |
1575526 |
Corresponding Julian Day Number |
month_name |
‘Hekatombaiṓn’ |
Name of Athenian month |
month_index |
1 |
Order of month in the year |
month |
Constant representing the month |
|
month_length |
29 |
Length of this month |
day |
1 |
Day of the month |
doy |
1 |
Day of the year |
year |
‘BCE 400/399’ |
Julian year(s) corresponding to the Athenian year |
year_length |
354 |
Length of this year |
astronomical_year |
-399 |
Astronomical year |
Altogether, this means that this is the first day (doy
= 1)
of the Athenian year 400/399 BCE. This year (or actually the beginning
of the year) corresponds to the astronomical year -399 (that is, 400
BCE) and the year is calculated to be 354 days long. It is also the
first day (day
= 1) of the first month
(month_index
= 1). The month’s name is Hekatombaiṓn, and it
has 29 days.
Grouping by Month¶
The tuples returned by the festival calendar function contain one
object per day. For convenience, there is a by_months()
function that will group this into a tuple of tuples. Each member of
the outer tuple represents a month and contains a tuple of
FestivalDay
objects for the days in that month.
>>> year = ha.athenian_festival_calendar(ha.bce_as_negative(400))
>>> len(year)
354
>>> (year[0].month_name, year[0].day)
('Hekatombaiṓn', 1)
>>> (year[1].month_name, year[1].day)
('Hekatombaiṓn', 2)
>>>
>>> months = ha.by_months(year)
>>> len(months)
12
>>> len(months[0])
29
>>> (months[0][0].month_name, months[0][0].day)
('Hekatombaiṓn', 1)
>>> (months[1][0].month_name, months[1][0].day)
('Metageitniṓn', 1)
Julian Day Numbers¶
No modern (that is, Gregorian or Julian) calendar date is included in
FestivalDay
objects, but this can be calculated
jdn
property. The Julian Day Number is the number of the day
counting from January 1, 4713 BCE, a system devised by Joseph
Scaliger, a
classical scholar, in 1583 and still used by astronomers and
chronologists today. For modern (or modern-like) versions of ancient
dates, historians usually employ the Proleptic Julian Calendar, so you
will probably want to use as_julian()
to convert the JDN into
a string equivalent of a Julian calendar date:
>>> ha.as_julian(1575526)
'BCE 0400-Jul-22'
For a Proleptic Gregorian Calendar date,
use as_gregorian()
:
>>> ha.as_gregorian(1575526)
'BCE 0400-Jul-17'
Heniautos uses the juliandate
package for these
conversations. For more detail refer to that documentation.
Attention
Note that there is no conversion to a Python date or datetime available because the datetime library does not handle BCE dates.
Julian and Gregorian Dates¶
as_julian()
and as_gregorian()
have some further
options. With full=True
the output includes the time (HH:MM:SS)
and timezone (GMT by default). Note that Julian Days start at noon, so
any decimal part indicates the fraction of 24 hours following noon and
therefore anything past .5 (midnight) actually falls into the next
(Julio-Gregorian) day
>>> ha.as_julian(1575526, full=True)
'BCE 0400-Jul-22 12:00:00 GMT'
>>> ha.as_julian(1575526.78, full=True)
'BCE 0400-Jul-23 06:43:12 GMT'
>>> ha.as_gregorian(1575526, full=True)
'BCE 0400-Jul-17 12:00:00 GMT'
>>> ha.as_gregorian(1575526.78, full=True)
'BCE 0400-Jul-18 06:43:12 GMT'
Time Zones¶
The tz
parameter takes one of two options:
TZOptions.GMT
(The default) or
TZOptions.ALT
. Since there were no time zones and no
daylight savings time in the ancient world, ALT is an invented
“timezone” that advances the time about 1 hour 35 minutes to reflect
the fact that Athens is about 23.73 degrees east of the meridian. That
is, if you were measuring time exactly by the sun, by the time it
reaches noon in Greenwich, it is already almost 1:35 PM in Athens.
>>> ha.as_julian(1575526.78, full=True, tz=ha.TZOptions.ALT)
'BCE 0400-Jul-23 08:18:06 ALT'
>>> ha.as_gregorian(1575526.78, full=True, tz=ha.TZOptions.ALT)
'BCE 0400-Jul-18 08:18:06 ALT'
Month Names¶
The optional name_as
parameter controls the form of the
month_name
property of the FestivalDay
objects. The
choices are: transliteration (default), abbreviation, and Greek. It
takes one of the MonthNameOptions
values.
The default is transliteration, which you can choose explicitly with
MonthNameOptions.TRANSLITERATION
:
>>> ha.athenian_festival_calendar(-399)[0].month_name
'Hekatombaiṓn'
>>> ha.athenian_festival_calendar(-399, name_as=ha.MonthNameOptions.TRANSLITERATION)[0].month_name
'Hekatombaiṓn'
For abbreviations use ha.MonthNameOptions.ABBREV
:
>>> ha.athenian_festival_calendar(-399, name_as=ha.MonthNameOptions.ABBREV)[0].month_name
'Hek'
And to get the month names in Greek, use ha.MonthNameOptions.GREEK
:
>>> ha.athenian_festival_calendar(-399, name_as=ha.MonthNameOptions.GREEK)[0].month_name
'Ἑκατομβαιών'
Intercalated Month¶
When intercalations are required (see Festival Calendar Basics)
Heniautos intercalates some default month (usually the sixth), but
this can be controlled with the intercalate
parameter.
For example, 211/210 BCE should be an intercalary year. By default the intercalated month will be a second Posideiṓn, Posideiṓn hústeros.
>>> year = ha.athenian_festival_calendar(-210)
>>> months = ha.by_months(year)
>>> month_names = [(ha.as_julian(m[0].jdn), m[0].month_name) for m in months]
>>> for m in month_names:
... print(m)
...
('BCE 0211-Jul-04', 'Hekatombaiṓn')
('BCE 0211-Aug-02', 'Metageitniṓn')
('BCE 0211-Aug-31', 'Boēdromiṓn')
('BCE 0211-Sep-30', 'Puanopsiṓn')
('BCE 0211-Oct-29', 'Maimaktēriṓn')
('BCE 0211-Nov-28', 'Posideiṓn')
('BCE 0211-Dec-27', 'Posideiṓn hústeros')
('BCE 0210-Jan-26', 'Gamēliṓn')
('BCE 0210-Feb-24', 'Anthestēriṓn')
('BCE 0210-Mar-26', 'Elaphēboliṓn')
('BCE 0210-Apr-25', 'Mounukhiṓn')
('BCE 0210-May-24', 'Thargēliṓn')
('BCE 0210-Jun-23', 'Skirophoriṓn')
However we know from an inscription, IG II³,1 1137, not only that
211/210 was an interalary year but also that Anthestēriṓn was the
intercalated month. We can recreate this by passing the right month
constant (see Month Constants below), in this case
AthenianMonths.ANT
:
>>> year = ha.athenian_festival_calendar(-210, intercalate=ha.AthenianMonths.ANT)
>>> months = ha.by_months(year)
>>> month_names = [(ha.as_julian(m[0].jdn), m[0].month_name) for m in months]
>>> for m in month_names:
... print(m)
...
('BCE 0211-Jul-04', 'Hekatombaiṓn')
('BCE 0211-Aug-02', 'Metageitniṓn')
('BCE 0211-Aug-31', 'Boēdromiṓn')
('BCE 0211-Sep-30', 'Puanopsiṓn')
('BCE 0211-Oct-29', 'Maimaktēriṓn')
('BCE 0211-Nov-28', 'Posideiṓn')
('BCE 0211-Dec-27', 'Gamēliṓn')
('BCE 0210-Jan-26', 'Anthestēriṓn')
('BCE 0210-Feb-24', 'Anthestēriṓn hústeros')
('BCE 0210-Mar-26', 'Elaphēboliṓn')
('BCE 0210-Apr-25', 'Mounukhiṓn')
('BCE 0210-May-24', 'Thargēliṓn')
('BCE 0210-Jun-23', 'Skirophoriṓn')
First Day of the Month¶
To the Greeks, “new moon” (νουμηνία) meant the first night that the
first sliver of the waxing crescent was visible (see Festival Calendar
Basics). We can’t say exactly when this occured for any given month
since there are many variables involved, nor do we know how much the
Greeks cared about actually sighting this moon over calculating or
even just guestimating when it should be visible. Heniautos uses an
approximation, defining the day of the visible new moon as some N
days
after the date of the conjunction, by default 1.
This can be changed with the v_off
(for “visibility offset”)
parameter. Again, the default is 1, so these are equivalent:
>>> ha.as_julian(ha.athenian_festival_calendar(-399)[0].jdn)
'BCE 0400-Jul-22'
>>> ha.as_julian(ha.athenian_festival_calendar(-399, v_off=1)[0].jdn)
'BCE 0400-Jul-22'
If you wanted to treat the new moon as visible on the day of the
conjunction you would pass v_off=0
. The effect would be shifting all
the dates up one day (which might have an effect on which years all
intercalary).
>>> ha.as_julian(ha.athenian_festival_calendar(-399, v_off=0)[0].jdn)
'BCE 0400-Jul-21'
Or you could use v_off=2
to make the new visible two days after the day of the conjunction.
>>> ha.as_julian(ha.athenian_festival_calendar(-399, v_off=2)[0].jdn)
'BCE 0400-Jul-23'
Day of the Solstice¶
Just as we can’t be sure when (even if) the Ancient Greeks literally
sighted the new moon, we can’t be sure when they observed a solstice
or equinox. By default, Heniautos treats the solstices and equinoxes
as observed on the days which they actually occurred but, to handle
the uncertainty, you can adjust this by supplying an integer with the
s_off
parameter.
This will only be obvious (at least with reasonable values) in the case of intercalations. For instance, from strictly judging by astronomical phenomena, they year 422/421 BCE should begin on July 26, following an intercalary 423/421
>>> ha.as_julian(ha.athenian_festival_calendar(-421)[0].jdn)
'BCE 0422-Jul-26'
However, the previous new moon, on June 26 would have been very close to the solstice that year (June 28). If the solstice was observed just two days early, that would put it on the same day as the June 26 new moon and the year (at least as Heniautos calculates it) would begin the next day and in June rather than July, with the intercalation moved from 423 to 422:
>>> ha.as_julian(ha.athenian_festival_calendar(-421, s_off=-2)[0].jdn)
'BCE 0422-Jun-27'
Something similar can be achieved by combining v_off
and s_off
. In
this case using s_off=-1
to indicate a solstice observed one day
before the true solstice and v_off=2
to indicate a new moon observed
two days after the conjunction (rather than 1) you get:
>>> ha.as_julian(ha.athenian_festival_calendar(-421, s_off=-1, v_off=2)[0].jdn)
'BCE 0422-Jun-28'
In general, the default values will be good enough. There are times,
though, that you may want to explore other options. For example,
though the details are not important here, there is some reason to
believe that 422/421 BCE was intercalary and may have begun just
before summer solstice. If this is not of vital interest to you, you
probably never need to worry about v_off
and s_off
.
Other Calendars¶
The various calendars of different Greek cities had different month names and began relative to different solstices or equinoxes. They might also differ in whether the first month followed the solstice or equinox or the the month in which the solstice or equinox occured.
For instance, in Delphi, the year began, as in Athens, after the summer solstice so the twelve months have the same dates as the in Athenian year, but different names:
>>> year = ha.delphian_festival_calendar(-399)
>>> months = ha.by_months(year)
>>> month_names = month_names = [(ha.as_julian(m[0].jdn), m[0].month_name) for m in months]
>>> for m in month_names:
... print(m)
...
('BCE 0400-Jul-22', 'Apellaîos')
('BCE 0400-Aug-20', 'Boukátios')
('BCE 0400-Sep-19', 'Boathóos')
('BCE 0400-Oct-18', 'Heraîos')
('BCE 0400-Nov-17', 'Dadaphórios')
('BCE 0400-Dec-17', 'Poitrópios')
('BCE 0399-Jan-16', 'Amálios')
('BCE 0399-Feb-15', 'Búsios')
('BCE 0399-Mar-16', 'Theoxénios')
('BCE 0399-Apr-14', 'Enduspoitrópios')
('BCE 0399-May-14', 'Herákleios')
('BCE 0399-Jun-12', 'Ilaîos')
On Delos, some of the month names were the same as the Athenian, but the year began after the winter solstice.
>>> year = ha.delian_festival_calendar(-399)
>>> months = ha.by_months(year)
>>> month_names = month_names = [(ha.as_julian(m[0].jdn), m[0].month_name) for m in months]
>>> for m in month_names:
... print(m)
...
('BCE 0399-Jan-16', 'Lēnaiṓn')
('BCE 0399-Feb-15', 'Hierós')
('BCE 0399-Mar-16', 'Galaxiṓn')
('BCE 0399-Apr-14', 'Artemisiṓn')
('BCE 0399-May-14', 'Thargēliṓn')
('BCE 0399-Jun-12', 'Pánēmos')
('BCE 0399-Jul-11', 'Hekatombaiṓn')
('BCE 0399-Aug-10', 'Metageitniṓn')
('BCE 0399-Sep-08', 'Bouphoniṓn')
('BCE 0399-Oct-08', 'Apatouriṓn')
('BCE 0399-Nov-06', 'Arēsiṓn')
('BCE 0399-Dec-06', 'Posideiṓn')
Attention
Something special to note about this invocation of
delian_festival_calendar()
. Ancient Greek years usually
span two Julian years (the end of one and beginning of the
next). This is why we refer to the Athenian year 400/399: because
it begins in the middle of 400 and ends in the middle of 399. To
get the calendar from athenian_festival_year()
you pass it
the first year of the span, 400 BCE or, in astronomical year
numbering, -399. Think of this as the year of the summer solstice
after which the year begins.
Because the winter solstice falls near the end of December, a
lunisolar year following this solstice will frequently not begin
until the next Julian year. In the example above,
delian_festival_calendar(-399)
asks for the year following the
winter solstice of 400 BCE. This year doesn’t begin until January
16, 399, though, and we would have to call it 399/398.
The Corinthian, Argive, and Spartan calendars probably all begin at the last new moon before the autumn equinox so that the equinox falls in the first month (unlike the Athenian, where the solstice falls in the last month)
>>> year = ha.corinthian_festival_calendar(-399)
>>> months = ha.by_months(year)
>>> month_names = month_names = [(ha.as_julian(m[0].jdn), m[0].month_name) for m in months]
>>> for m in month_names:
... print(m)
...
('BCE 0400-Sep-19', 'Phoinikaîos')
('BCE 0400-Oct-18', 'Kráneios')
('BCE 0400-Nov-17', 'Lanotropíos')
('BCE 0400-Dec-17', 'Makhaneús')
('BCE 0399-Jan-16', 'Dōdekateús')
('BCE 0399-Feb-15', 'Εúkleios')
('BCE 0399-Mar-16', 'Artemísios')
('BCE 0399-Apr-14', 'Psudreús')
('BCE 0399-May-14', 'Gameílios')
('BCE 0399-Jun-12', 'Agriánios')
('BCE 0399-Jul-11', 'Pánamos')
('BCE 0399-Aug-10', 'Apellaîos')
We don’t know all the names of the Spartan months or their order, so
spartan_festival_calendar()
returns a generic calendar (see
Generic Calendar below) in which the months are simply numbered:
>>> year = ha.spartan_festival_calendar(-399)
>>> months = ha.by_months(year)
>>> month_names = month_names = [(ha.as_julian(m[0].jdn), m[0].month_name) for m in months]
>>> for m in month_names:
... print(m)
...
('BCE 0400-Sep-19', '1')
('BCE 0400-Oct-18', '2')
('BCE 0400-Nov-17', '3')
('BCE 0400-Dec-17', '4')
('BCE 0399-Jan-16', '5')
('BCE 0399-Feb-15', '6')
('BCE 0399-Mar-16', '7')
('BCE 0399-Apr-14', '8')
('BCE 0399-May-14', '9')
('BCE 0399-Jun-12', '10')
('BCE 0399-Jul-11', '11')
('BCE 0399-Aug-10', '12')
The months of fully generic calendar (see Generic Calendar, below) have ordinal numbers as Greek names: Πρῶτος, Δεύτερος, etc. So that a Spartan calendar cannot be confused with a truly generic calendar, the Greek names of Spartan months are δεῖνα αʹ, δεῖνα βʹ, etc. (which you can interpret as “Unknown 1”, “Unknown 2”):
>>> year = ha.spartan_festival_calendar(-399, name_as=ha.MonthNameOptions.GREEK)
>>> months = ha.by_months(year)
>>> month_names = month_names = [(ha.as_julian(m[0].jdn), m[0].month_name) for m in months]
>>> for m in month_names:
... print(m)
...
('BCE 0400-Sep-19', 'δεῖνα αʹ')
('BCE 0400-Oct-18', 'δεῖνα βʹ')
('BCE 0400-Nov-17', 'δεῖνα γʹ')
('BCE 0400-Dec-17', 'δεῖνα δʹ')
('BCE 0399-Jan-16', 'δεῖνα εʹ')
('BCE 0399-Feb-15', 'δεῖνα ϛʹ')
('BCE 0399-Mar-16', 'δεῖνα ζʹ')
('BCE 0399-Apr-14', 'δεῖνα ηʹ')
('BCE 0399-May-14', 'δεῖνα θʹ')
('BCE 0399-Jun-12', 'δεῖνα ιʹ')
('BCE 0399-Jul-11', 'δεῖνα ιαʹ')
('BCE 0399-Aug-10', 'δεῖνα ιβʹ')
Generic Calendar¶
The a function for creating a generic calendar (the calendar-specific
functions are simply wrappers around this) is festival_calendar()
.
With the default values it returns a calendar that begins after the summer solstice with months that are simply numbered:
>>> year = ha.festival_calendar(-399)
>>> months = ha.by_months(year)
>>> month_names = [(ha.as_julian(m[0].jdn), m[0].month_name) for m in months]
>>> for m in month_names:
... print(m)
...
('BCE 0400-Jul-22', '1')
('BCE 0400-Aug-20', '2')
('BCE 0400-Sep-19', '3')
('BCE 0400-Oct-18', '4')
('BCE 0400-Nov-17', '5')
('BCE 0400-Dec-17', '6')
('BCE 0399-Jan-16', '7')
('BCE 0399-Feb-15', '8')
('BCE 0399-Mar-16', '9')
('BCE 0399-Apr-14', '10')
('BCE 0399-May-14', '11')
('BCE 0399-Jun-12', '12')
The Greek option gives the months named by Greek numerals. Some calendars were actually this generic. For instance, the Achaean calendar began after the autumn equinox, and the months were simply numbered. With the corresponding options, we can generate this:
>>> year = ha.festival_calendar(-399, event=ha.Seasons.AUTUMN_EQUINOX, name_as=ha.MonthNameOptions.GREEK)
>>> months = ha.by_months(year)
>>> month_names = [(ha.as_julian(m[0].jdn), m[0].month_name) for m in months]
>>> for m in month_names:
... print(m)
...
('BCE 0400-Oct-18', 'Πρῶτος')
('BCE 0400-Nov-17', 'Δεύτερος')
('BCE 0400-Dec-17', 'Τρίτος')
('BCE 0399-Jan-16', 'Τέταρτος')
('BCE 0399-Feb-15', 'Πέμπτος')
('BCE 0399-Mar-16', 'Ἕκτος')
('BCE 0399-Apr-14', 'Ἕβδομος')
('BCE 0399-May-14', 'Ὄγδοος')
('BCE 0399-Jun-12', 'Ἔνατος')
('BCE 0399-Jul-11', 'Δέκατος')
('BCE 0399-Aug-10', 'Ἑνδέκατος')
('BCE 0399-Sep-08', 'Δωδέκατος')
The data
Parameter¶
This parameter is used to supply your own astronomical (solstice, equinox, and new moon data). See “Ephimerides and Custom Data” below.
Constants for Months and Seasons¶
This section will cover constants used to identify various calendar
months (AthenianMonths
, ArgiveMonths
,
CorinthianMonths
, DelianMonths
,
DelphianMonths
, and GenericMonths
) and those
used to identify seasons (that is solstices and equinoxes)
Seasons
It also introduces functions that use these constants to retrieve month names and dates for solstices, equinoxes, and new moons.
Months¶
Months are represented by one set of constants for each calendar
available in Heniautos. Each constant has an integer value that is the
normal position of the month in the given calendar. For instance, for
the Athenian calendar the constants come from
AthenianMonths
:
>>> for m in tuple(ha.AthenianMonths):
... m
...
<AthenianMonths.HEK: 1>
<AthenianMonths.MET: 2>
<AthenianMonths.BOE: 3>
<AthenianMonths.PUA: 4>
<AthenianMonths.MAI: 5>
<AthenianMonths.POS: 6>
<AthenianMonths.GAM: 7>
<AthenianMonths.ANT: 8>
<AthenianMonths.ELA: 9>
<AthenianMonths.MOU: 10>
<AthenianMonths.THA: 11>
<AthenianMonths.SKI: 12>
The integer values can be used:
>>> int(ha.AthenianMonths.SKI)
12
>>> ha.AthenianMonths.SKI > ha.AthenianMonths.HEK
True
The month property of a FestivalDay
contains the month
constant. Due to intercalation, this value may not be the same as the
position of the given month in a given year. The position of the month
in a year should always be determined by the month_index
property
of a FestivalDay
. In an ordinary year, like 426 BCE, the
constant values will correspond to the month indices. If we examine
Elaphēboliṓn (normally the 9th month) 426, for instance:
>>> m = ha.by_months(ha.athenian_festival_calendar(-425))
>>> (m[8][0].month_index, m[8][0].month)
(9, <AthenianMonths.ELA: 9>)
If 425 BCE is intercalary though, and the intercalary month is the 6th, Posideiṓn, Elaphēboliṓn, will be the tenth month:
>>> m = ha.by_months(ha.athenian_festival_calendar(-424))
>>> (m[5][0].month_index, m[5][0].month)
(6, <AthenianMonths.POS: 6>)
>>> (m[6][0].month_index, m[6][0].month)
(7, <Months.INT: 13>)
>>> (m[9][0].month_index, m[9][0].month)
(10, <AthenianMonths.ELA: 9>)
Attention
Note that the intercalary month is always assigned the month
constant Months.INT
(regardless of the specific
calendar).
The other month constants are ArgiveMonths
,
CorinthianMonths
, DelianMonths
,
DelphianMonths
, and GenericMonths
. Some months
on different calendars have the same names but they are represented by
different constants. For instance, Hekatombaiṓn occurs both on the
Athenian calendar, as the first month, and the Delian calendar, as the
seventh (though they usually occur at the same time since the Delian
year begins six months before the Athenian). These are represented by
two different constants:
>>> ha.AthenianMonths.HEK
<AthenianMonths.HEK: 1>
>>> ha.DelianMonths.HEK
<DelianMonths.HEK: 7>
>>> ha.AthenianMonths.HEK == ha.DelianMonths.HEK
False
spartan_festival_calendar()
returns GenericMonths
because we do not know the actual months:
>>> ha.spartan_festival_calendar(-399)[0].month
<GenericMonths.M01: 1>
Use the month_name()
function to convert a constant to its
transliterated name (default), abbreviation, or Greek name.
>>> ha.month_name(ha.AthenianMonths.HEK)
'Hekatombaiṓn'
>>> ha.month_name(ha.AthenianMonths.HEK, name_as=ha.MonthNameOptions.ABBREV)
'Hek'
>>> ha.month_name(ha.AthenianMonths.HEK, name_as=ha.MonthNameOptions.GREEK)
'Ἑκατομβαιών'
Seasons¶
We saw the Seasons
constants above under the
Generic Calendar. These identify the solstices and equinoxes
that are important to Greek calendars:
>>> for s in ha.Seasons:
... s
...
<Seasons.SPRING_EQUINOX: 0>
<Seasons.SUMMER_SOLSTICE: 1>
<Seasons.AUTUMN_EQUINOX: 2>
<Seasons.WINTER_SOLSTICE: 3>
To find the date of a historical solstice or equinox, use
solar_event()
or observed_solar_event()
with one
of these constants. The difference between the two is that
solar_event()
returns the exact Julian Date of the event
(that is, the astronomical truth):
>>> ha.solar_event(-399, ha.Seasons.SUMMER_SOLSTICE)
1575501.7962411924
>>> ha.as_julian(ha.solar_event(-399, ha.Seasons.SUMMER_SOLSTICE), full=True)
'BCE 0400-Jun-28 07:06:35 GMT'
observed_solar_event()
returns the event rounded to the
nearest Julian Day Number, optionally adjusted by the offset s_off
(discussed under Day of the Solstice)
>>> ha.observed_solar_event(-399, ha.Seasons.SUMMER_SOLSTICE)
1575502
>>> ha.as_julian(ha.observed_solar_event(-399, ha.Seasons.SUMMER_SOLSTICE), full=True)
'BCE 0400-Jun-28 12:00:00 GMT'
>>> ha.as_julian(ha.observed_solar_event(-399, ha.Seasons.SUMMER_SOLSTICE, s_off=-1), full=True)
'BCE 0400-Jun-27 12:00:00 GMT'
Like solar events, there are functions for new moons and visible new
moons. new_moons()
returns exact Julian Dates, while
visible_new_moons()
are rounded to the nearest Julian Day
Number with an offset. As with v_off
(see First Day of the Month)
the default offset is 1 day. They also return tuples containing the
dates of all the new moons in the calendar (not the Greek) year
>>> ha.new_moons(-399)
(1575348.655074811, 1575378.1413952103, 1575407.517358738, 1575436.8253117797, 1575466.1110969426, 1575495.4158226792, 1575524.7752166032, 1575554.222185349, 1575583.7858906111, 1575613.4801067342, 1575643.281607354, 1575673.119159554)
>>> ha.visible_new_moons(-399)
(1575350, 1575379, 1575409, 1575438, 1575467, 1575496, 1575526, 1575555, 1575585, 1575614, 1575644, 1575674)
>>> ha.visible_new_moons(-399, v_off=2)
(1575351, 1575380, 1575410, 1575439, 1575468, 1575497, 1575527, 1575556, 1575586, 1575615, 1575645, 1575675)
Internally, these functions are used to determine the dates of months in the Greek year, and most importantly, when the year starts. If the observed summer solstice of 400 BCE is on JDN 1575502 (June 28), then the next year begins at the first visible new moon after, which falls on JDN 1575526 (July 22) and the following months begin on each following visible new moon.
Finding Festival Calendar Dates¶
You can find a festival calendar date from a Julian Day Number with
jdn_to_festival_day()
:
>>> fest_day = ha.jdn_to_festival_day(1575526)
>>> fest_day
FestivalDay(jdn=1575526, month_name='Hekatombaiṓn', month_index=1, month=<AthenianMonths.HEK: 1>, month_length=29, day=1, doy=1, year='BCE 400/399', year_length=354, astronomical_year=-399)
>>> ha.as_julian(fest_day)
'BCE 0400-Jul-22'
With julian_to_festival_day()
you can find a festival
calendar date with a Julian year, month, and day. As usual, the year
must be given in Astronomical Year Numbering, the
month and day must be integers:
>>> julian_day = ha.julian_to_festival_day(-399, 7, 22)
>>> julian_day
FestivalDay(jdn=1575526, month_name='Hekatombaiṓn', month_index=1, month=<AthenianMonths.HEK: 1>, month_length=29, day=1, doy=1, year='BCE 400/399', year_length=354, astronomical_year=-399)
>>> ha.as_julian(julian_day)
'BCE 0400-Jul-22'
>>> ha.as_gregorian(julian_day)
'BCE 0400-Jul-17'
gregorian_to_festival_day()
works similarly:
>>> gregorian_day = ha.gregorian_to_festival_day(-399, 7, 22)
>>> gregorian_day
FestivalDay(jdn=1575531, month_name='Hekatombaiṓn', month_index=1, month=<AthenianMonths.HEK: 1>, month_length=29, day=6, doy=6, year='BCE 400/399', year_length=354, astronomical_year=-399)
>>> ha.as_julian(gregorian_day)
'BCE 0400-Jul-27'
>>> ha.as_gregorian(gregorian_day)
'BCE 0400-Jul-22'
Ephimerides and Custom Data¶
Heniautos comes with solstice/equinox and new moon data from 633 to 1 BCE and 1899 to 2150 CE. This range should allow generating calendars for most of the interesting years in the time of the Greeks as well as decent coverage for hypothetical modern day calendars. This data has been derived from the DE431 ephemeris published by the Jet Propulsion Laboratory.
If you want to use a different data source or data for different years there are two ways to do it
data Parameter¶
All the functions that rely on solar and lunar data for calculations have an optional data parameter. The data provided should be a dict with a solstices and new_moons keys. Each values should be tuple containg more tuples of Julian Dates and codes for the kind of date. For lunar data the only code is 0 for the new moon. For solar data, the values are 0 = spring equinox, 1 = summer solstice, 2 = autumn equinox, 3 = winter solstice. For instance:
>>> custom_data = {
"solstices": (
(1685074.3287422964, 1),
(1685439.5648092534, 1),
),
"new_moons": (
(1684907.0310656228, 0),
(1684936.490878384, 0),
(1684965.8702085295, 0),
(1685291.0009266976, 0),
(1685320.5018709311, 0),
(1685349.9050228074, 0),
(1685704.4562648418, 0),
(1685733.8966757061, 0),
),
}
You can also provide a function that will return data in the proper format. This is how Heniautos works internally. The default value of the data parameter is a private function that returns the default data.
Use Ephemeris¶
You can use an ephemeris like DE431 directly for any date supported by the ephemeris. You must first have the optional dependency Skyfield installed as well as an ephemeris file downloaded.
To access this ephemeris data, import heniautos.ephemeris
module, initialize the ephemeris, and use
heniautos.ephemeris.get_ephemeris_data()
to extract a data
structure in the proper format. For example, if a copy of de431.bsp is
in your current working directory:
>>> import heniautos.ephemeris as heph
>>> e = heph.init_ephemeris(eph="de431.bsp")
>>> data = heph.get_ephemeris_data(-999, -949, e)
>>> ha.athenian_festival_calendar(-999, data=data)