-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathREADME
244 lines (195 loc) · 10.8 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
A calendar implementation library
*********************************
`libcalendar' is an experimental C library to provide arithmentic for
several calendars.
Why?
====
Why implement yet another calendaring library? Well, there are plenty of
excellent implementations out there, though it seems there is no free,
GPL-compliant, C implementation. Besides there is no precise implementation of
non-gregorian calendars, most importantly Solar Hijri and Islamic Civil
calendars.
API Design Philosophy
=====================
This library is API-less by design. This means the library is not intended
to be used directly as a standalone API. Instead, it only provides arithmetic
implementations meant to be integrated into existing date-time APIs or utilized
by developers when creating their own APIs for handling date-time
operations.
Key Principles:
* No Custom Data Structures: The library
deliberately avoids introducing structures for representing calendar components
(e.g., `year`, `month`, `day`). Instead, it operates exclusively on Plain Data
Types (PDTs), such as integers or other native types, ensuring simplicity and
compatibility with diverse applications.
* Flexibility: By focusing solely on
the arithmetic logic, the library provides a robust foundation for building or
extending higher-level APIs. This design empowers developers to adapt the
library seamlessly to their specific domain requirements without being
constrained by predefined abstractions.
* Integration-Ready: The library
complements existing date-time APIs by adding precise calendar arithmetic
capabilities without altering their design philosophy. It can also be used to
prototype and implement custom solutions efficiently.
How to use libcalendar?
=======================
Almost all algorithms in libcalendar are implemented using Julian Day
calculations. You can convert any date on supported calendars to JDN and vice
versa. For example:
uint32_t jdn = 0;
sh_to_jdn(&jdn, 1392, 04, 15);
printf("Julian Day for 1392/04/15 AP is: %l\n", jdn);
Which prints:
$ Julian Day for 1392/04/15 AP is: 2456480
You can also use non-jdn broken-down date API. For example you can check if a
year in Solar Hijri calendar is leap or not:
if(sh_is_leap(1395)) /* returns 0 for regular years and 1 for leap years */
printf("Yep\n");
Or convert calendar dates to/from Gregorian calendar:
int16_t y;
uint8_t m;
uint16_t d;
sh_to_gr(1369, 06, 20, &y, &m, &d);
printf("1369/06/20 AP is %04d-%02d-%02d\n", y, m, d);
gr_to_sh(2017, 09, 11, &y, &m, &d);
printf("2017-09-11 is %04d-%02d-%02d AP\n", y, m, d);
which will print:
$ 1369/06/20 AP is 2017-09-11
$ 2017-09-11 is 1369/06/18 AP
Algorithms
==========
This library is imolemented in C programming language, using no external
dependecies. The C standard library used in libcalendar is C11. Though it
should be possible to compile this library with a C99 compiler.
Most of the conversion algorithms for JDN to calendar and vice versa are
implemented based on Dr. Louis Strous's work. (available online on "Astronomy
Page" at `http://aa.quae.nl/en/reken/juliaansedag.html') Namely Gregorian,
Julian, Milankovic and Islamic Civil calendars and their JDN calculations are
adopted from above page.
Solar Hijri (Shamsi) and Jalali calendar calculations are implemented based
on Dr. Mousa Akrami's work on median year length for Persian calendar. (See
notes on Solar Hijri calendar).
Calendars
=========
Following is a list of supported calendars, and a short description (mostly
from wikipedia) about them.
Gregorian
---------
The Gregorian calendar is internationally the most widely used civil
calendar.
It is named after Pope Gregory XIII, who introduced it in October 1582.
The calendar was a refinement to the Julian calendar involving a 0.002%
correction in the length of the year. The motivation for the reform was to stop
the drift of the calendar with respect to the equinoxes and solstices -
particularly the northern vernal equinox, which helps set the date for Easter.
Transition to the Gregorian calendar would restore the holiday to the time of
the year in which it was celebrated when introduced by the early Church. The
reform was adopted initially by the Catholic countries of Europe. Protestants
and Eastern Orthodox countries continued to use the traditional Julian calendar
and adopted the Gregorian reform after a time, at least for civil purposes and
for the sake of convenience in international trade. The last European country
to adopt the reform was Greece, in 1923. Many (but not all) countries that have
traditionally used the Islamic and other religious calendars have come to adopt
this calendar for civil purposes.
Julian
------
The Julian calendar, proposed by Julius Caesar in 46 BC (708 AUC), was a
reform
of the Roman calendar. It took effect on 1 January 45 BC (AUC 709), by edict.
It was the predominant calendar in the Roman world, most of Europe, and in
European settlements in the Americas and elsewhere, until it was refined and
gradually replaced by the Gregorian calendar, promulgated in 1582 by Pope
Gregory XIII. The Julian calendar gains against the mean tropical year at the
rate of one day in 128 years. For the Gregorian the figure is one day in 3,030
years. The difference in the average length of the year between Julian (365.25
days) and Gregorian (365.2425 days) is 0.002%.
Milankovic
----------
The Revised Julian calendar, also known as the Milankovic calendar, or, less
formally, new calendar, is a calendar, developed and proposed by the Serbian
scientist Milutin Milankovic in 1923, which effectively discontinued the 340
years of divergence between the naming of dates sanctioned by those Eastern
Orthodox churches adopting it and the Gregorian calendar that has come to
predominate worldwide. This calendar was intended to replace the ecclesiastical
calendar based on the Julian calendar hitherto in use by all of the Eastern
Orthodox Church. The Revised Julian calendar temporarily aligned its dates with
the Gregorian calendar proclaimed in 1582 by Pope Gregory XIII for adoption by
the Christian world. The calendar has been adopted by the Orthodox churches of
Constantinople, Albania, Alexandria, Antioch, Bulgaria, Cyprus, Greece, Poland,
and Romania.
Solar Hijri
-----------
The Solar Hijri calendar, also called the Solar Hejri calendar or Shamsi
Hijri calendar, and abbreviated as SH, is the official calendar of Iran and
Afghanistan. It begins on the vernal equinox (Nowruz) as determined by
astronomical calculation for the Iran Standard Time meridian (52.5°E or
GMT+3.5h). This determination of starting moment is more accurate than the
Gregorian calendar for predicting the date of the vernal equinox, because it
uses astronomical observations rather than mathematical rules.
Each of the twelve months corresponds with a zodiac sign. The first six
months have 31 days, the next five have 30 days, and the last month has 29 days
in usual years but 30 days in leap years. The New Year's Day always falls on
the March equinox.
Notes on Solar Hijri
--------------------
My implementation of Solar Hijri (Shamsi) calendar is based on median year
calculation obtained from Muousa Akrami's work: `The development of Iranian
calendar: historical and astronomical foundations - 2014` (available online at
`https://arxiv.org/pdf/1111.4926.pdf') This method is more accurate than
33-year algorithm and supports a wider range of dates, both in Solar Hijri <->
Gregorian comversions, and in JDN calculations.
Egyptian
--------
The Egyptian calendar is one of the earliest known timekeeping systems,
developed in ancient Egypt to align with the Nile's annual flood cycles. It
played a vital role in organizing agricultural activities and religious
festivals. This calendar is notable for its remarkable simplicity and its
influence on later timekeeping systems, including the Julian and Gregorian
calendars.
The Egyptian calendar was based on a solar year divided into three
seasons of four months each, reflecting the natural cycles of the Nile:
* Akhet (Inundation): The flood season, when the Nile overflowed,
replenishing the
soil.
* Peret (Emergence): The growing season, when crops were planted and
cultivated.
* Shemu (Harvest): The dry season, when crops were harvested.
Each of the twelve months contained 30 days, making up a total of 360 days in
the year. To reconcile this structure with the solar year of approximately
365.25 days, the Egyptians added five additional days, known as the "epagomenal
days," at the end of the year. These days were considered outside the normal
calendar and were dedicated to the birthdays of key deities, including Osiris,
Isis, and Horus.
The calendar was not leap-adjusted, meaning it gradually drifted out
of sync with the solar year over centuries. However, its consistency made it
highly practical for everyday use and administrative tasks. This robust
simplicity, combined with its cultural significance, helped the Egyptian
calendar endure for millennia and leave a lasting legacy on the history of
timekeeping.
Babylonian
----------
The Babylonian calendar, developed in ancient Mesopotamia, is one of the
earliest recorded lunar calendars. It played a crucial role in the
administrative, agricultural, and religious life of the Babylonians. Rooted in
astronomical observations, this calendar reflects the sophisticated
understanding of celestial movements by Babylonian scholars.
The calendar was a lunisolar system, aligning months with the lunar cycle and
years with the solar cycle. It relied on the Metonic Cycle, which states that
235 synodical months are equal to 19 tropical years. These 19 years alternated
between 12 and 13 months, with long years (13 months) occurring in the 1st,
4th, 7th, 9th, 12th, 15th, and 18th years of the cycle. This structure included
125 months of 30 days and 110 months of 29 days, adding up to 6,940 days in
total. In most long years, the 12th month was doubled, but in the 18th year,
the 6th month was doubled instead. Day 1 of month 1 (Nisannu) of year 1 in the
Era of Seleukos corresponded to 3 April 310 BCE in the Julian Calendar (CJDN
1607558).
The Babylonians determined the beginning of each month by observing the phases
of the moon. Since the calendar was partly based on direct observations, the
length of months and years was not entirely fixed. Factors such as weather
conditions could delay the official start of a month if the moon was obscured
by clouds. This variability meant the distribution of months into years
operated independently from the distribution of days into months.
To reconstruct the Babylonian calendar predictably, we can use a mathematically
derived version that closely approximates the historical system. Such a version
would differ from the original calendar by at most one day, capturing its
structure while avoiding the unpredictability of direct lunar observations.