home *** CD-ROM | disk | FTP | other *** search
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
- <HTML>
- <!-- Generated by TechWriter Professional+ 7.11 (10-Jun-00) -->
- <HEAD><TITLE>ADFS::Csite.$.C.User.!Calendar.Docs.Manual</TITLE></HEAD>
- <BODY TEXT="#000000" BGCOLOR="#FFFFFF">
- <H1 ALIGN=CENTER>The Calendar Module</H1>
-
- <P ALIGN=CENTER>
- <I>This module was designed to provide SWIs with which a programmer can
- easily convert dates between different calendars. It's design is aimed at
- historical applications such as Genealogy. Implemented calendars include
- Gregorian, Hebrew, Islam, Julian and French Revolutionary. The implementation
- as a module was chosen rather then a C library because SWI calls can be used
- from any implementation language, such as BASIC, Assembler and C.</I>
-
-
-
- <P ALIGN=CENTER>
- <B>Disclaimer</B>
-
- <P ALIGN=CENTER>
- This module is in no way intended to be defining any particular calendar. If
- you find any errors in the results produced by this module please report them
- to me and an improved version will be made as soon as feasible.
-
- <P ALIGN=CENTER>
- In fact, you are invited to test the code as much as possible in order to
- find any possible errors. Please make sure the discrepancy you found is
- indeed due to an error in the module and not, e.g. due to misreading of a
- printed calendar.
-
- <P ALIGN=CENTER>
- The implementer of this module uses the Gregorian calendar in daily life, and
- all knowledge of other calendars comes from books and the Internet.
-
- <H1 ALIGN=CENTER>1. Purpose</H1>
-
- <H2 ALIGN=RIGHT>Why this module</H2>
-
- <P>
- This module was originally designed to do calendar calculations and
- conversions for a genealogical application. When investigating your ancestry
- you will quickly have to deal with dates more than a hundred years ago. Not
- only must they be written down (a simple string would suffice), calculations
- are also usefull. For example, you might want to put the children in a family
- in chronological order of birthdate.
-
- <P>
- Most programming languages and computer systems supply some kind of built-in
- date manipulation system. However, they usually don't go very far back in the
- past. Unix and it's derivatives, and as a result the standard C library
- functions, use a counter for the number of seconds since 1970Jan1,
- 00:00 GMT. Other systems count days from 1900Jan1. RISC OS
- does this.
-
- <P>
- Another problem is that the built-in systems usually only support the
- Gregorian calendar. When dealing with history you will bump into the French
- Revolutionary calendar and the Julian calendar. These will have to be
- converted to and compared with the Gregorian dates.
-
- <P>
- Another application is the simple printing of calendars. Here, lots of
- knowledge other than a simple sequence of dates is usefull: What day of the
- week is Jan1 in a specific year? How many days in a specific month? What
- weeknumber should you assign to each week. Etcetera.
-
- <H2 ALIGN=RIGHT>What it does</H2>
-
- <P>
- Once the notion is there that different calendars need to be supported, more
- types are quickly added to the list, such as the Hebrew and the Islamic
- calendar. If routines were to be written to convert from each calender type
- to each other type, the number of combinations runs quickly out of hand.
- After N calendars you need to write 2*N routines to add a single extra
- calendar.
-
- <P>
- To solve this, an ageold and obvious solution is used. Number the days
- in history sequentially, starting at a suitable starting point. This makes
- conversion of a date between two calendars an easy, twostep process.
- Sorting dates chronologically becomes trivial.
-
- <H2 ALIGN=RIGHT>What it does not</H2>
-
- <P>
- Because the number of days since, say, 1Jan1 is already over
- 730000, it was decided not to include the time of day into the system. As
- seen above this would quickly limit the range of the dates that can be
- calculated in a 32 bit system. This also avoids problems with the different
- notions of when a day begins: at midnight, at noon, at dawn, at dusk? (Don't
- laugh, these are valid methods used on a daily basis.)
-
- <P>
- One thing this module definitely wants to avoid is returning strings for the
- dates. This means keeping a table not only of January, February, etc, but
- also of Jan, Feb, etc, with options for passing either or both. This is
- needed for each calendar type. The problem is compounded by
- internationalisation: each language has it's own names for the months and the
- weekdays. And what about the Hebrew or Islamic calendars. The English words
- for the months are just approximations. Many languages may not even their own
- representation. And pretty soon someone will appreciate a Unicode version
- with Hebrew or Arabic characters.
-
- <P>
- And what about formatting? The user will want to pass a format string
- specifying the layout.
-
- <P>
- A total nightmare would be an attempt to interpret dates in strings. Coding
- for that would be about 100 times more work than only handling numbers.
-
- <H1 ALIGN=CENTER>2. Different calendars</H1>
-
- <H2 ALIGN=RIGHT>Which ones</H2>
-
- <P>
- There are many different calendars in use in the modern day. Predominant in
- the western world is the Gregorian calendar. In many parts of the world the
- Islamic calendar is used. The Hebrew calendar is also current. When dealing
- with historic events you may come across the Julian calendar, which preceded
- the Gregorian calendar, and the French Revolutionary calendar. Today and in
- the past, many other calendars are and were used.
-
- <H2 ALIGN=RIGHT>The Julian Calendar</H2>
-
- <P>
- Based on the antique Roman calendar, this system was introduced by Julius
- Caesar in 46 BC. By that time they were 90 days off with the seasons. In his
- honour the Roman month Quintilis was renamed to Julius. Astronomers had
- determined that the solar year was 365.25 days long. To handle this, the year
- was made to count 365 days and a leap day was added every four years to
- Februarius, which was then the last month of the year.
-
- <P>
- Application of the new calendar was in the beginning rather messy. Emperor
- Augustus sorted things out. He was bestowed the same honour as Julius, and
- month Sextilis was renamed to Augustus. The number of days in each month and
- their names that were then laid down are still in use in the modern Gregorian
- calendar.
-
- <P>
- The years were usually counted by using the year of rule of a monarch or a
- pope. It was only in the 6th century AD that Dionysius Exiguus established
- the notion of Anno Domini as a result calculations for future dates of Easter
- he made.
-
- <P>
- The Julian calendar is now fully replaced by the Gregorian calendar in the
- Western world. The Greek- and Russian-Orthodox churches still use the Julian
- calendar.
-
- <H2 ALIGN=RIGHT>The Gregorian calendar</H2>
-
- <P>
- This calendar was developed in the 16th century under authority of pope
- Gregory XIII to resolve inaccuracies in the Julian calendar. The difference
- is that no longer every year divisible by four is a leap year. Years
- divisible by 100 are not leap years, except when they are divisible by 400.
- This means that the year 1600 was a leap year, 1700, 1800 and 1900 were not,
- but 2000 was. This calendar is expected to be accurate for at least 30000
- years.
-
- <P>
- To synchronise the calendar with the seasons, March21 was desired to
- fall on the equinox. It was known that during the Council of Nicea (AD 325)
- the equinox fell on that day. The number of days neccesary to compensate was
- calculated to be 10. It was therefore decided to introduce the Gregorian
- calendar by skipping from the 4th of October 1582 to the 15th of October.
- This happened in the entire Roman Catholic world.
-
- <P>
- But exactly because this calendar is a Roman Catholic invention, the change
- was not immediately adopted everywhere. Protestant England and it's colonies
- for instance waited until 1752. Russian-orthodox Russia held out until after
- the Russian Revolution (that is why the October Revolution was always
- celebrated in November in the USSR). Greek-orthodox Greece delayed until
- 1923. And allthough the Greek and Russian states changed to the Gregorian
- calendar, the Greek and Russian Orthodox churches still use the Julian
- calendar, for instance to calculate Easter.
-
- <P>
- In some places, like the fledgeling Republic of the Netherlands, introduction
- was a local matter and spread out over several decades. Often both dates were
- used together in documents or the indication S.V. (stilo veteri, old style)
- or S.N. (stilo novo, new style) was added.
-
- <P>
- Note by the way that there is a lot more to reading dates in old documents.
- For instance, in those days the year was normally taken to begin at Easter,
- not on the 1st of January. So if you read "19 of February 1555" it is very
- well possible that this translates to the modern 19th of February 1556, a
- year later than you might expect at face value.
-
- <P>
- These kinds of problems interpreting old dates however fall outside the scope
- of this manual. You are referred to the literature about this subject.
-
- <H2 ALIGN=RIGHT>The Islamic calendar</H2>
-
- <P>
- (Note: My knowledge of this calendar is limited. No statement in this section
- should be taken as irrefutable fact.) The Islamic calendar is a lunar
- calendar, where each month follows a phase cycle of the moon. Based on the
- fact that the period between two equal phases of the moon is about 29½
- days (29.53069 to be exact) the months alternatively have 29 and 30 days. The
- calendar has 12 months, adding up to a year of 354 days. Because 12 actual
- moon cycles make 354.36828 days, a leap day is frequently added. In the
- Islamic calendar there are 11 leap years in every 30 years, making the
- average year 354.36666 days long. This misses out only 1 day in about 620
- Islamic years. As we are now in year 1422 the difference is no more than 2
- days. Not bad for a calendar designed 1380 years ago.
-
- <P>
- Note that this lunar calendar has no direct connection to the seasons, which
- are related to the sun. In fact, the Islamic year is about 11 days shorter
- than the Gregorian year. This means that each year the dates in the Islamic
- calendar shift slightly when compared to the Gregorian calendar. It goes
- round once in about every 34 solar years. This also means that 35 Islamic
- years go by in 34 solar years.
-
- <H2 ALIGN=RIGHT>The Hebrew calendar</H2>
-
- <P>
- (Note: My knowledge of this calendar is limited. No statement in this section
- should be taken as irrefutable fact.) The Hebrew calendar as used since 378
- AD is a lunisolar calendar. This means it has months of 29 or 30 days that
- keep in step with the lunar cycle, and the resulting difference of about 11
- days with the solar year is compensated by adding an extra month every 7 out
- of 19 years. Leap days are added for fine tuning.
-
- <P>
- Although this calendar is highly accurate, it is also very complicated. Three
- of the thirteen months can be either 29 or 30 days. The extra (leap) month is
- added in the middle of the year. The calculation of the number of days in a
- specific Hebrew year is lengthy and contortious.
-
- <H2 ALIGN=RIGHT>The French Revolutionary calendar</H2>
-
- <P>
- The French Revolution happened in the middle of the philosophical period
- known as Rationalism. A clean break was made with outdated silly and
- irrational institutions. They were replaced with sensible, rational things.
- One of the great successes is the metric system of measurement, which does
- away with such silly things as having three separate, non-compatible systems
- of measuring weight, and using weight units to measure volume. One of it's
- failures was the Revolutionary calendar.
-
- <P>
- The year was divided into twelve months of 30 days which were given beautiful
- poetic names. This gives 360 days. The remaining 5 or 6 days were added to
- the end of the year as "jours complémentaires" (additional days).
- While they were at it, the weeks and days were decimalised, with each month
- divided into three "décades" of ten days each. A day would consist of
- 10 hours of 100 minutes, with 100 seconds to the minute. (Note that this
- would result in 100,000 seconds per day instead of the current 86400. The
- second would have become slightly shorter.)
-
- <P>
- The 10 hour day was never introduced as there were no clocks to show it and
- conversion was too complicated. The months and the 10 day week were
- instituted on the 5th of October 1793. The day the Republic was proclaimed,
- the 22 of September 1792, also the day of the autum equinox, was chosen as
- the starting point of the calendar. Note that like many other calendars the
- year 1 occurs before the calendar is actually introduced.
-
- <P>
- The 10 day week was abolished on the 31 of march 1802, because it hindered
- the celebration of Sunday in the still very Roman Catholic France.
-
- <P>
- The calendar did not last very much longer. Napoleon abolished it on the 11th
- of September 1805, after it had served less than 12 years.
-
- <P>
- Before that happened, France under Napoleon had conquered large parts of
- Europe and introduced their calendar there. So even outside France you may
- find documents dated with French Revolutionary dates.
-
- <H1 ALIGN=CENTER>3. How it works</H1>
-
- <H2 ALIGN=RIGHT>Julian Day</H2>
-
- <P>
- As a basis for the conversion, a unique reference number was needed for every
- day in history. As days always follow one another in an orderly fashion, it
- is very unlikely that any mistakes were made in the past in counting the
- days. So, as a reference, each day is given a consecutive number. This module
- chooses an existing system, know as the Julian Day number. This was
- introduced by Justus Scaliger in 1583. It's starting point lies in 4713 BC.
- The Julian Day was chosen because it is an existing system and is in current
- use, namely in astronomy.
-
- <P>
- Note: in previous (pre-0.10) versions of the module the starting point was
- the first day in the Gregorian calendar, the 1st of January in the year 1,
- which was taken as day 1.
-
- <H2 ALIGN=RIGHT>Conversions</H2>
-
- <P>
- The module implements three SWIs.
-
- <H2 ALIGN=RIGHT>JDayToDate</H2>
-
- <P>
- The first converts from a Julian Day number to the year, month and day of a
- particular calendar.
-
- <H2 ALIGN=RIGHT>DateToJDay</H2>
-
- <P>
- The second does the opposite conversion. A given triplet of year, month and
- day of the month in a particular calendar is converted to a Julian Day number.
-
- <H2 ALIGN=RIGHT>WeekToJDay</H2>
-
- <P>
- The third is similar to DateToJDay, but uses year, week of the year and day
- of the week as input data and converts them to a Julian Day number.
-
- <H2 ALIGN=RIGHT>JDayToWeek</H2>
-
- <P>
- This is the reverse of WeekToJDay. Given a Julian Day number it calculates
- the year, week of the year and day of the week.
-
- <H2 ALIGN=RIGHT>Calculations</H2>
-
- <P>
- Calculating the Julian Day number from the date is relatively
- straightforward. For example in the Gregorian calendar simply add the day of
- the month to the number of days in the previous months in this year to get
- the days in the given year, and then add 365 days times the number of
- previous years, with corrections for leap years.
-
- <P>
- The reverse is generally more difficult. As a simple solution, the code makes
- an educated guess for the date and then uses the Date-To-Gregorian-Day
- routine described above to see how close the guess is. In more detail it goes
- like this:
-
- <P>
- First a low estimate for the year is calculated by dividing the day number by
- 366 (one day more than the normal number of days in year). Then the year is
- increased until the first of January of the next year has a day number that
- is bigger than the one given. We now have the year.
-
- <P>
- Next, the months in that year are checked in sequence until the month is
- found of which the last day converts to a day number which is equal to or
- higher than the given number. We now also have the month.
-
- <P>
- Finally, the day of the month is simply found by subtracting the day number
- for the first day of that month in the year we found from the given day
- number and adding 1.
-
- <H2 ALIGN=RIGHT>Input ranges</H2>
-
- <P>
- The effect of this method is that every Julian Day converts to exactly one
- date in a specific calendar. On the other hand, conversions from a date to a
- Julian Day accept even the most outrageous values for year, month and day.
- For example if 2002/1/60 (the 60th of January 2002) is given, it is correctly
- converted to day number 730909. Converting back results in 2002/3/1, or the
- first of March in the same year, which is indeed the 60th day in that year.
- This is useful in cases where one is not certain if a date is valid in a
- specific calendar.
-
- <H1 ALIGN=CENTER>4. SWI Calls</H1>
-
- <H2 ALIGN=RIGHT>General</H2>
-
- <P>
- An effort has been made to keep the assignment of registers the same for all
- SWIs. R0 is always used to pass the calendar type. R1 always holds the Julian
- Day number, either on entry or on exit. Year, month and day values are always
- in R2 upwards. This means that they don't disturb R0 or R1.
-
- <P>
- The result is that converting back and forth between two calenders in
- assembly becomes very easy: First call Calendar_DateToJDay with a given year,
- month and day for one calendar. You then get the Julian Day number in R1.
- Then set the calender type in R0 to the calendar you want to convert to, and
- call the reverse function, Calendar_JDayToDate. The converted date is then in
- R2-R4.
-
- <P>
- Another feature that is common to all Calendar SWIs is that they are not
- fussy about the date values. Silly dates like 2000/13/61 are easily converted
- to the corect Julian Day number.
-
- <H2 ALIGN=RIGHT>Errors</H2>
-
- <P>
- The SWIs can return errors in the following situations:
-
- <UL>
-
- <LI>The calendar type is unknown in this module. The value passed in R0 is
- probably wildly out of range.
-
- <LI>The calendar type is not implemented yet. Note that early versions of the
- module may not support all of the calendar types listed in this manual.
-
- <LI>A particular SWI is not implemented for a particular calendar type.
-
- </UL>
- <P>
- More errors may be added in future.
-
- <H2 ALIGN=RIGHT>Calendar types</H2>
-
- <P>
- The following codes are available for calendar types:
-
- <DIV ALIGN=CENTER>
- <TABLE WIDTH="100%" CELLPADDING=2>
- <TR><TD>1
-
- <TD>Julian
-
- <TR><TD>2
-
- <TD>Gregorian
-
- <TR><TD>3
-
- <TD>Hebrew
-
- <TR><TD>4
-
- <TD>Islamic
-
- <TR><TD>5
-
- <TD>Revolutionary (10-day weeks)
-
- <TR><TD>6
-
- <TD>Revolutionary (7-day weeks)
-
- </TABLE>
- </DIV>
- <P>
- Some remarks:
-
- <UL>
-
- <LI>There is no calendar type 0. The list starts at 1.
-
- <LI>The French Revolutionary calendar is split in two types, depending on the
- use of the decimal or the normal week. For calculations which do not involve
- weekdays (like JDayToDate or DateToJDay) there is no difference between the
- two.
-
- </UL>
- <H2 ALIGN=RIGHT>Julian Day to date</H2>
-
- <P>
- <B><FONT SIZE="+2">Calendar_JDayToDate (SWI &55F80)</FONT></B>
-
- <P>
- Convert a Julian Day number to a date in a specific calendar.
-
- <P>
- On entry
-
- <P>
- R0 = Type of calendar
-
- <P>
- R1 = Julian Day number
-
- <P>
- On exit
-
- <P>
- R0 - R1 = preserved
-
- <P>
- R2 = Year
-
- <P>
- R3 = Month
-
- <P>
- R4 = Day of the month
-
- <P>
- Interrupts
-
- <P>
- Interrupt status is not altered
-
- <P>
- Fast interrupts are enabled
-
- <P>
- Processor Mode
-
- <P>
- Processor is in SVC mode
-
- <P>
- Re-entrancy
-
- <P>
- SWI is re-entrant
-
- <H2 ALIGN=RIGHT>Use</H2>
-
- <P>
- Calendar_JDayToDate converts a Julian Day number to the year, month and day
- of the month in a specific calendar.
-
- <H2 ALIGN=RIGHT>Date to Julian Day</H2>
-
- <P>
- <B><FONT SIZE="+2">Calendar_DateToJDay (SWI &55F81)</FONT></B>
-
- <P>
- On entry
-
- <P>
- R0 = Type of calendar
-
- <P>
- R1 = (unused)
-
- <P>
- R2 = Year
-
- <P>
- R3 = Month
-
- <P>
- R4 = Day of the month
-
- <P>
- On exit
-
- <P>
- R0 = preserved
-
- <P>
- R1 = Julian Day number
-
- <P>
- R2 - R4 = preserved
-
- <H2 ALIGN=RIGHT>Use</H2>
-
- <P>
- Calendar_DateToJDay converts the year, month and day of the month in a
- specific calendar to the Julian Day number.
-
- <H2 ALIGN=RIGHT>Julian Day to Week day</H2>
-
- <P>
- <B><FONT SIZE="+2">Calendar_JDayToWeek</FONT></B>
-
- <P>
- On entry
-
- <P>
- R0 = Type of calendar
-
- <P>
- R1 = Julian Day number
-
- <P>
- On exit
-
- <P>
- R0 - R1 = preserved
-
- <P>
- R2 = Year
-
- <P>
- R3 = Week
-
- <P>
- R4 = Day of the week
-
- <H2 ALIGN=RIGHT>Use</H2>
-
- <P>
- Calendar_JDayToWeek converts a Julian Day number to the year, week of the
- year and day of the week in a specific calendar. For Julian, Gregorian and
- Revolutionary-7 calendars it follows the ISO 8601. This means that Monday is
- counted as the first day of the week (day 1), and the first week of the year
- is the week in which Jan4 lies. For the other types of calendar we have
- not enough information at the time to implement this SWI. If you have an
- accurate description of the algorithm or the rules for one of them, please
- send them to us.
-
- <H2 ALIGN=RIGHT>Week to Julian Day</H2>
-
- <P>
- <B><FONT SIZE="+2">Calendar_WeekToJDay</FONT></B>
-
- <P>
- On entry
-
- <P>
- R0 = Type of calendar
-
- <P>
- R1 = (unused)
-
- <P>
- R2 = Year
-
- <P>
- R3 = Week of the year
-
- <P>
- R4 = Day of the week
-
- <P>
- On exit
-
- <P>
- R0 = preserved
-
- <P>
- R1 = Julian Day number
-
- <P>
- R2 - R4 = preserved
-
- <H2 ALIGN=RIGHT>Use</H2>
-
- <P>
- Calendar_WeekToJDay converts a the year, week of the year and day of the week
- to Julian Day number in a specific calendar. For Julian, Gregorian and
- Revolutionary-7 calendars it follows the ISO 8601. This means that Monday is
- counted as the first day of the week (day 1), and the first week of the year
- is the week in which Jan4 lies. For the other types of calendar we have
- not enough information at the time to implement this SWI. If you have an
- accurate description of the algorithm or the rules for one of them, please
- send them to us.
-
- <H2 ALIGN=RIGHT>CheckDate</H2>
-
- <P>
- <B><FONT SIZE="+2">Calendar_CheckDate</FONT></B>
-
- <P>
- On entry
-
- <P>
- R0 = Type of calendar
-
- <P>
- R1 = (unused)
-
- <P>
- R2 = Year
-
- <P>
- R3 = Month
-
- <P>
- R4 = Day of the month
-
- <P>
- On exit
-
- <P>
- R0 - R1 = preserved
-
- <P>
- R2 >=0 if date is valid, <0 if date is not valid
-
- <H2 ALIGN=RIGHT>Use</H2>
-
- <P>
- The date given is checked to see if it is a valid date for the given
- calendar. This is done by the simple method of first converting the date to a
- Julian Day Number, converting it back again and then checking whether the
- year, month and day of the month calculated are the same as those given. This
- catches things like "April 31" and "1999 Feb 29", and also the more radical
- "2000 Jan 61" or "2001-14-31". These examples are for days of the month or
- months wich have too high a number, but it should also work for days of the
- month or months which are zero or negative. In the Hebrew calendar it will
- also catch out the less trivial case of using of the month Veadar in years
- when it is not present.
-
- </BODY>
- </HTML>
-