home *** CD-ROM | disk | FTP | other *** search
/ RISCWORLD 5 / RISCWORLD_VOL5.iso / SOFTWARE / Issue3 / FAMILY / Calendar / Docs / ManText < prev   
Encoding:
Text File  |  2003-09-23  |  20.5 KB  |  546 lines

  1. The Calendar Module
  2.  
  3. This module was designed to provide SWIs with which a programmer can easily 
  4. convert dates between different calendars. It's design is aimed at historical 
  5. applications such as Genealogy. Implemented calendars include Gregorian, 
  6. Hebrew, Islam, Julian and French Revolutionary. The implementation as a 
  7. module was chosen rather then a C library  because SWI calls can be used from 
  8. any implementation language, such as BASIC, Assembler and C.
  9.  
  10.  
  11.  
  12. Disclaimer
  13.  
  14. This module is in no way intended to be defining any particular calendar. If 
  15. you find any errors in the results produced by this module please report them 
  16.  to me and an improved version will be made as soon as feasible.
  17.  
  18. In fact, you are invited to test the code as much as possible in order to 
  19. find any possible errors. Please make sure the discrepancy you found is 
  20. indeed due to an error in the module and not, e.g. due to misreading of a 
  21. printed calendar.
  22.  
  23. The implementer of this module uses the Gregorian calendar in daily life, and 
  24. all knowledge of other calendars comes from books and the Internet.
  25.  
  26. 1.      Purpose
  27.  
  28. Why this module
  29.  
  30. This module was originally designed to do calendar calculations and 
  31. conversions for a genealogical application. When investigating your ancestry 
  32. you will quickly have to deal with dates more than a hundred years ago. Not 
  33. only must they be written down (a simple string would suffice), calculations 
  34. are also usefull. For example, you might want to put the children in a family 
  35. in chronological order of birthdate.
  36.  
  37. Most programming languages and computer systems supply some kind of built-in 
  38. date manipulation system. However, they usually don't go very far back in the 
  39. past. Unix and it's derivatives, and as a result the standard C library 
  40. functions, use a counter for the number of seconds since 1970­Jan­1, 00:00 
  41. GMT. Other systems count days from 1900­Jan­1. RISC OS does this.
  42.  
  43. Another problem is that the built-in systems usually only support the 
  44. Gregorian calendar. When dealing with history you will bump into the French 
  45. Revolutionary calendar and the Julian calendar. These will have to be 
  46. converted to and compared with the Gregorian dates.
  47.  
  48. Another application is the simple printing of calendars. Here, lots of 
  49. knowledge other than a simple sequence of dates is usefull: What day of the 
  50. week is Jan­1 in a specific year? How many days in a specific month? What 
  51. weeknumber should you assign to each week. Etcetera.
  52.  
  53. What it does
  54.  
  55. Once the notion is there that different calendars need to be supported, more 
  56. types are quickly added to the list, such as the Hebrew and the Islamic 
  57. calendar. If routines were to be written to convert from each calender type 
  58. to each other type, the number of combinations runs quickly out of hand. 
  59. After N calendars you need to write 2*N routines to add a single extra 
  60. calendar.
  61.  
  62. To solve this, an age­old and obvious solution is used. Number the days in 
  63. history sequentially, starting at a suitable starting point. This makes 
  64. conversion of a date between two calendars an easy, two­step process. Sorting 
  65. dates chronologically becomes trivial.
  66.  
  67. What it does not
  68.  
  69. Because the number of days since, say, 1­Jan­1 is already over 730000, it was 
  70. decided not to include the time of day into the system. As seen above this 
  71. would quickly limit the range of the dates that can be calculated in a 32 bit 
  72. system. This also avoids problems with the different notions of when a day 
  73. begins: at midnight, at noon, at dawn, at dusk? (Don't laugh, these are valid 
  74. methods used on a daily basis.)
  75.  
  76. One thing this module definitely wants to avoid is returning strings for the 
  77. dates. This means keeping a table not only of January, February, etc, but 
  78. also of Jan, Feb, etc, with options for passing either or both. This is 
  79. needed for each calendar type. The problem is compounded by 
  80. internationalisation: each language has it's own names for the months and the 
  81. weekdays. And what about the Hebrew or Islamic calendars. The English words 
  82. for the months are just approximations. Many languages may not even their own 
  83. representation. And pretty soon someone will appreciate a Unicode version 
  84. with Hebrew or Arabic characters.
  85.  
  86. And what about formatting? The user will want to pass a format string 
  87. specifying the layout.
  88.  
  89. A total nightmare would be an attempt to interpret dates in strings. Coding 
  90. for that would be about 100 times more work than only handling numbers.
  91.  
  92. 2.      Different calendars
  93.  
  94. Which ones
  95.  
  96. There are many different calendars in use in the modern day. Predominant in 
  97. the western world is the Gregorian calendar. In many parts of the world the 
  98. Islamic calendar is used. The Hebrew calendar is also current. When dealing 
  99. with historic events you may come across the Julian calendar, which preceded 
  100. the Gregorian calendar, and the French Revolutionary calendar. Today and in 
  101. the past, many other calendars are and were used.
  102.  
  103. The Julian Calendar
  104.  
  105. Based on the antique Roman calendar, this system was introduced by Julius 
  106. Caesar in 46 BC. By that time they were 90 days off with the seasons. In his 
  107. honour the Roman month Quintilis was renamed to Julius. Astronomers had 
  108. determined that the solar year was 365.25 days long. To handle this, the year 
  109. was made to count 365 days and a leap day was added every four years to 
  110. Februarius, which was then the last month of the year.
  111.  
  112. Application of the new calendar was in the beginning rather messy. Emperor 
  113. Augustus sorted things out. He was bestowed the same honour as Julius, and 
  114. month Sextilis was renamed to Augustus. The number of days in each month and 
  115. their names that were then laid down are still in use in the modern Gregorian 
  116. calendar. 
  117.  
  118. The years were usually counted by using the year of rule of a monarch or a 
  119. pope. It was only in the 6th century AD that Dionysius Exiguus established 
  120. the notion of Anno Domini as a result calculations for future dates of Easter 
  121. he made.
  122.  
  123. The Julian calendar is now fully replaced by the Gregorian calendar in the 
  124. Western world. The Greek- and Russian-Orthodox churches still use the Julian 
  125. calendar.
  126.  
  127. The Gregorian calendar
  128.  
  129. This calendar was developed in the 16th century under authority of pope 
  130. Gregory XIII to resolve inaccuracies in the Julian calendar. The difference 
  131. is that no longer every year divisible by four is a leap year. Years 
  132. divisible by 100 are not leap years, except when they are divisible by 400. 
  133. This means that the year 1600 was a leap year, 1700, 1800 and 1900 were not, 
  134. but 2000 was. This calendar is expected to be accurate for at least 30000 
  135. years. 
  136.  
  137. To synchronise the calendar with the seasons, March­21 was desired to fall on 
  138. the equinox. It was known that during the Council of Nicea (AD 325) the 
  139. equinox fell on that day. The number of days neccesary to compensate was 
  140. calculated to be 10. It was therefore decided to introduce the Gregorian 
  141. calendar by skipping from the 4th of October 1582 to the 15th of October. 
  142. This happened in the entire Roman Catholic world.
  143.  
  144. But exactly because this calendar is a Roman Catholic invention, the change 
  145. was not immediately adopted everywhere. Protestant England and it's colonies 
  146. for instance waited until 1752. Russian-orthodox Russia held out until after 
  147. the Russian Revolution (that is why the October Revolution was always 
  148. celebrated in November in the USSR). Greek-orthodox Greece delayed until 
  149. 1923. And allthough the Greek and Russian states changed to the Gregorian 
  150. calendar, the Greek and  Russian Orthodox churches still use the Julian 
  151. calendar, for instance to calculate Easter.
  152.  
  153. In some places, like the fledgeling Republic of the Netherlands, introduction 
  154. was a local matter and spread out over several decades. Often both dates were 
  155. used together in documents or the indication S.V. (stilo veteri, old style) 
  156. or S.N. (stilo novo, new style) was added.
  157.  
  158. Note by the way that there is a lot more to reading dates in old documents. 
  159. For instance, in those days the year was normally taken to begin at Easter, 
  160. not on the 1st of January. So if you read "19 of February 1555" it is very 
  161. well possible that this translates to the modern 19th of February 1556, a 
  162. year later than you might expect at face value.
  163.  
  164. These kinds of problems interpreting old dates however fall outside the scope 
  165. of this manual. You are referred to the literature about this subject.
  166.  
  167. The Islamic calendar
  168.  
  169. (Note: My knowledge of this calendar is limited. No statement in this section 
  170. should be taken as irrefutable fact.) The Islamic calendar is a lunar 
  171. calendar, where each month follows a phase cycle of the moon. Based on the 
  172. fact that the period between two equal phases of the moon is about 29½ days 
  173. (29.53069 to be exact) the months alternatively have 29 and 30 days. The 
  174. calendar has 12 months, adding up to a year of 354 days. Because 12 actual 
  175. moon cycles make 354.36828 days, a leap day is frequently added. In the 
  176. Islamic calendar there are 11 leap years in every 30 years, making the 
  177. average year 354.36666 days long. This misses out only 1 day in about 620 
  178. Islamic years. As we are now in year 1422 the difference is no more than 2 
  179. days. Not bad for a calendar designed 1380 years ago.
  180.  
  181. Note that this lunar calendar has no direct connection to the seasons, which 
  182. are related to the sun. In fact, the Islamic year is about 11 days shorter 
  183. than the Gregorian year. This means that each year the dates in the Islamic 
  184. calendar shift slightly when compared to the Gregorian calendar. It goes 
  185. round once in about every 34 solar years. This also means that 35 Islamic 
  186. years go by in 34 solar years.
  187.  
  188. The Hebrew calendar
  189.  
  190. (Note: My knowledge of this calendar is limited. No statement in this section 
  191. should be taken as irrefutable fact.) The Hebrew calendar as used since 378 
  192. AD is a lunisolar calendar. This means it has months of 29 or 30 days that 
  193. keep in step with the lunar cycle, and the resulting difference of about 11 
  194. days with the solar year is compensated by adding an extra month every 7 out 
  195. of 19 years. Leap days are added for fine tuning.
  196.  
  197. Although this calendar is highly accurate, it is also very complicated. Three 
  198. of the thirteen months can be either 29 or 30 days. The extra (leap) month is 
  199. added in the middle of the year. The calculation of the number of days in a 
  200. specific Hebrew year is lengthy and contortious.
  201.  
  202. The French Revolutionary calendar
  203.  
  204. The French Revolution happened in the middle of the philosophical period 
  205. known as Rationalism. A clean break was made with outdated silly and 
  206. irrational institutions. They were replaced with sensible, rational things. 
  207. One of the great successes is the metric system of measurement, which does 
  208. away with such silly things as having three separate, non-compatible systems 
  209. of measuring weight, and using weight units to measure volume. One of it's 
  210. failures was the Revolutionary calendar.
  211.  
  212. The year was divided into twelve months of 30 days which were given beautiful 
  213. poetic names. This gives 360 days. The remaining 5 or 6 days were added to 
  214. the end of the year as "jours complémentaires" (additional days). While they 
  215. were at it, the weeks and days were decimalised, with each month divided into 
  216. three "décades" of ten days each. A day would consist of 10 hours of 100 
  217. minutes, with 100 seconds to the minute. (Note that this would result in 
  218. 100,000 seconds per day instead of the current 86400. The second would have 
  219. become slightly shorter.)
  220.  
  221. The 10 hour day was never introduced as there were no clocks to show it and 
  222. conversion was too complicated. The months and the 10 day week were 
  223. instituted on the 5th of October 1793. The day the Republic was proclaimed, 
  224. the 22 of September 1792, also the day of the autum equinox, was chosen as 
  225. the starting point of the calendar. Note that like many other calendars the 
  226. year 1 occurs before the calendar is actually introduced.
  227.  
  228. The 10 day week was abolished on the 31 of march 1802, because it hindered 
  229. the celebration of Sunday in the still very Roman Catholic France.
  230.  
  231. The calendar did not last very much longer. Napoleon abolished it on the 11th 
  232. of September 1805, after it had served less than 12 years.
  233.  
  234. Before that happened, France under Napoleon had conquered large parts of 
  235. Europe and introduced their calendar there. So even outside France you may 
  236. find documents dated with French Revolutionary dates.
  237.  
  238. 3.      How it works
  239.  
  240. Julian Day
  241.  
  242. As a basis for the conversion, a unique reference number was needed for every 
  243. day in history.  As days always follow one another in an orderly fashion, it 
  244. is very unlikely that any mistakes were made in the past in counting the 
  245. days. So, as a reference, each day is given a consecutive number. This module 
  246. chooses an existing system, know as the Julian Day number. This was 
  247. introduced by Justus Scaliger in 1583. It's starting point lies in 4713 BC. 
  248. The Julian Day was chosen because it is an existing system and is in current 
  249. use, namely in astronomy.
  250.  
  251. Note: in previous (pre-0.10) versions of the module the starting point was 
  252. the first day in the Gregorian calendar, the 1st of January in the year 1, 
  253. which was taken as day 1.
  254.  
  255. Conversions
  256.  
  257. The module implements three SWIs.
  258.  
  259. JDayToDate
  260.  
  261. The first converts from a Julian Day number to the year, month and day of a 
  262. particular calendar.
  263.  
  264. DateToJDay
  265.  
  266. The second does the opposite conversion. A given triplet of year, month and 
  267. day of the month in a particular calendar is converted to a Julian Day number.
  268.  
  269. WeekToJDay
  270.  
  271. The third is similar to DateToJDay, but uses year, week of the year and day 
  272. of the week as input data and converts them to a Julian Day number.
  273.  
  274. JDayToWeek
  275.  
  276. This is the reverse of WeekToJDay. Given a Julian Day number it calculates 
  277. the year, week of the year and day of the week.
  278.  
  279. Calculations
  280.  
  281. Calculating the Julian Day number from the date is relatively 
  282. straightforward. For example in the Gregorian calendar simply add the day of 
  283. the month to the number of days in the previous months in this year to get 
  284. the days in the given year, and then add 365 days times the number of 
  285. previous years, with corrections for leap years.
  286.  
  287. The reverse is generally more difficult. As a simple solution, the code makes 
  288. an educated guess for the date and then uses the Date-To-Gregorian-Day 
  289. routine described above to see how close the guess is. In more detail it goes 
  290. like this:
  291.  
  292. First a low estimate for the year is calculated by dividing the day number by 
  293. 366 (one day more than the normal number of days in  year). Then the year is 
  294. increased until the first of January of the next year has a day number that 
  295. is bigger than the one given. We now have the year.
  296.  
  297. Next, the months in that year are checked in sequence until the month is 
  298. found of which the last day converts to a day number  which is equal to or 
  299. higher than the given number. We now also have the month.
  300.  
  301. Finally, the day of the month is simply found by subtracting the day number 
  302. for  the first day of that month in the year we found from the given day 
  303. number and adding 1.
  304.  
  305. Input ranges
  306.  
  307. The effect of this method is that every Julian Day converts to exactly one 
  308. date in a specific calendar. On the other hand, conversions from a date to a 
  309. Julian Day accept even the most outrageous values for year, month and day. 
  310. For example if 2002/1/60 (the 60th of January 2002) is given, it is correctly 
  311. converted to day number 730909. Converting back results in 2002/3/1, or the 
  312. first of March in the same year, which is indeed the 60th day in that year. 
  313. This is useful in cases where one is not certain if  a date is valid in a 
  314. specific calendar.
  315.  
  316. 4.      SWI Calls
  317.  
  318. General
  319.  
  320. An effort has been made to keep the assignment of registers the same for all 
  321. SWIs. R0 is always used to pass the calendar type. R1 always holds the Julian 
  322. Day number, either on entry or on exit. Year, month and day values are always 
  323. in R2 upwards. This means that they don't disturb R0  or R1.
  324.  
  325. The result is that converting back and forth between two calenders in 
  326. assembly becomes very easy: First call Calendar_DateToJDay with a given year, 
  327. month and day for one calendar. You then get the Julian Day number in R1. 
  328. Then set the calender type in R0 to the calendar you want to convert to, and 
  329. call the reverse function, Calendar_JDayToDate. The converted date is then in 
  330. R2-R4.
  331.  
  332. Another feature that is common to all Calendar SWIs is that they are not 
  333. fussy about the date values. Silly dates like 2000/13/61 are easily converted 
  334. to the corect Julian Day number.
  335.  
  336. Errors
  337.  
  338. The SWIs can return errors in the following situations:
  339.  
  340. The calendar type is unknown in this module. The value passed in R0 is 
  341. probably wildly out of range.
  342.  
  343. The calendar type is not implemented yet. Note that early versions of the 
  344. module may not support all of the calendar types listed in this manual.
  345.  
  346. A particular SWI is not implemented for a particular calendar type.
  347.  
  348. More errors may be added in future.
  349.  
  350. Calendar types
  351.  
  352. The following codes are available for calendar types:
  353.  
  354. 1       Julian
  355.  
  356. 2       Gregorian
  357.  
  358. 3       Hebrew
  359.  
  360. 4       Islamic
  361.  
  362. 5       Revolutionary (10-day weeks)
  363.  
  364. 6       Revolutionary (7-day weeks)
  365.  
  366. Some remarks:
  367.  
  368. There is no calendar type 0. The list starts at 1.
  369.  
  370. The French Revolutionary calendar is split in two types, depending on the use 
  371. of the decimal or the normal week. For calculations which do not involve 
  372. weekdays (like JDayToDate or DateToJDay) there is no difference between the 
  373. two.
  374.  
  375. Julian Day to date
  376.  
  377. Calendar_JDayToDate (SWI &55F80)
  378.  
  379. Convert a Julian Day number to a date in a specific calendar.
  380.  
  381. On entry
  382.  
  383.         R0 = Type of calendar
  384.  
  385.         R1 = Julian Day number
  386.  
  387. On exit
  388.  
  389.         R0 - R1 = preserved
  390.  
  391.         R2 = Year
  392.  
  393.         R3 = Month
  394.  
  395.         R4 = Day of the month
  396.  
  397. Interrupts
  398.  
  399.         Interrupt status is not altered
  400.  
  401.         Fast interrupts are enabled
  402.  
  403. Processor Mode
  404.  
  405.         Processor is in SVC mode
  406.  
  407. Re-entrancy
  408.  
  409.         SWI is re-entrant
  410.  
  411. Use
  412.  
  413. Calendar_JDayToDate converts a Julian Day number to the year, month and day 
  414. of the month in a specific calendar.
  415.  
  416. Date to Julian Day
  417.  
  418. Calendar_DateToJDay (SWI &55F81)
  419.  
  420. On entry
  421.  
  422.         R0 = Type of calendar
  423.  
  424.         R1 = (unused)
  425.  
  426.         R2 = Year
  427.  
  428.         R3 = Month
  429.  
  430.         R4 = Day of the month
  431.  
  432. On exit
  433.  
  434.         R0 = preserved
  435.  
  436.         R1 = Julian Day number
  437.  
  438.         R2 - R4 = preserved
  439.  
  440. Use
  441.  
  442. Calendar_DateToJDay converts  the year, month and day of the month in a 
  443. specific calendar to the Julian Day number.
  444.  
  445. Julian Day to Week day
  446.  
  447. Calendar_JDayToWeek
  448.  
  449. On entry
  450.  
  451.         R0 = Type of calendar
  452.  
  453.         R1 = Julian Day number
  454.  
  455. On exit
  456.  
  457.         R0 - R1 = preserved
  458.  
  459.         R2 = Year
  460.  
  461.         R3 = Week
  462.  
  463.         R4 = Day of the week
  464.  
  465. Use
  466.  
  467. Calendar_JDayToWeek converts a Julian Day number to the year, week of the 
  468. year and day of the week in a specific calendar. For Julian, Gregorian and 
  469. Revolutionary-7 calendars it follows the ISO 8601. This means that Monday is 
  470. counted as the first day of the week (day 1), and the first week of the year 
  471. is the week in which Jan­4 lies. For the other types of calendar we have not 
  472. enough information at the time to implement this SWI. If you have an accurate 
  473. description of the algorithm or the rules for one of them, please send them 
  474. to us.
  475.  
  476. Week to Julian Day
  477.  
  478. Calendar_WeekToJDay
  479.  
  480. On entry
  481.  
  482.         R0 = Type of calendar
  483.  
  484.         R1 = (unused)
  485.  
  486.         R2 = Year
  487.  
  488.         R3 = Week of the year
  489.  
  490.         R4 = Day of the week
  491.  
  492. On exit
  493.  
  494.         R0 = preserved
  495.  
  496.         R1 = Julian Day number
  497.  
  498.         R2 - R4 = preserved
  499.  
  500. Use
  501.  
  502. Calendar_WeekToJDay converts a the year, week of the year and day of the week 
  503. to Julian Day number in a specific calendar. For Julian, Gregorian and 
  504. Revolutionary-7 calendars it follows the ISO 8601. This means that Monday is 
  505. counted as the first day of the week (day 1), and the first week of the year 
  506. is the week in which Jan­4 lies. For the other types of calendar we have not 
  507. enough information at the time to implement this SWI. If you have an accurate 
  508. description of the algorithm or the rules for one of them, please send them 
  509. to us.
  510.  
  511. CheckDate
  512.  
  513. Calendar_CheckDate
  514.  
  515. On entry
  516.  
  517.         R0 = Type of calendar
  518.  
  519.         R1 = (unused)
  520.  
  521.         R2 = Year
  522.  
  523.         R3 = Month
  524.  
  525.         R4 = Day of the month
  526.  
  527. On exit
  528.  
  529.         R0 - R1 = preserved
  530.  
  531.         R2  >=0 if date is valid, <0 if date is not valid
  532.  
  533. Use
  534.  
  535. The date given is checked to see if it is a valid date for the given 
  536. calendar. This is done by the simple method of first converting the date to a 
  537. Julian Day Number, converting it back again and then checking whether the 
  538. year, month and day of the month calculated are the same as those given. This 
  539. catches things like "April 31" and "1999 Feb 29", and also the more radical 
  540. "2000 Jan 61" or "2001-14-31". These examples are for days of the month or 
  541. months wich have too high a number, but it should also work for days of the 
  542. month or months which are zero or negative. In the Hebrew calendar it will 
  543. also catch out the less trivial case of using of the month Veadar in years 
  544. when it is not present.
  545.  
  546.