[Sorry for my english, it's not very good. I hope, this will be 
understandable enough, thought.]


INTRODUCTION

The 'libkal' library provides support for converting dates between various 
calendary systems (currently only julianic, gregorianic, arabic and jewish 
ones) and some more related stuff.

The basic idea of this library is, that any date in any calendar system can
be converted to a single number, which express the number of days since some 
fixed date in the past. I use here so-called 'julianic date'(jd), that is used 
in Astronomy (not exactly). 

Therefore it's easy to compute for example 'how many days are there 
between x and y' - just compute the jd's of x and y, and substract them:

difference=kal_conv_gre_jd(y_day,y_month,y_year)-
           kal_conv_gre_jd(x_day,x_month,x_year);

Also evaluating the day of week of given date is quite easy - just divide 
the jd by 7 and the reminder is what you seek. (not exactly)


LIBRARY OVERVIEW

1. Basic conversions
--------------------

Each calendary system has two basic functions, which convert the date to and 
from the jd:

 long	kal_conv_*_jd(int d, int m, int y);
 void	kal_conv_jd_*(long jd, int *d, int *m, int *y);

 ,where * can be one of: jul,gre,ar,jew for julianic, gregorianic, arabic
and jewish calendary system respectively. 
(e.g.: "kal_conv_gre_jd(day,month,year)" computes the jd of day/month/year
 according to the gregorian calendar.)

(See the test.c example.)

2. Checking if date valid
-------------------------

When converting a date into the jd, we would like to know, whether the 
date is valid. This is done in the folowing function:

 int	kal_*_check(long *jd, int d, int m, int y);

 (simillar to the previous). It returns 0 on succes and 1 when the date is
invalid. 
 The check is done in two steps: first checking for 'big nonsenses' such as 
the month number bigger than 13 (jewish calendar has sometimes 13 months) or
lower than 1; second, we convert the date into jd, and then back into d/m/y 
and check, whether the d/m/y are equal. 
 Thus we have here as a parameter the pointer on the jd, as we need not to 
do the same job (converting d/m/y to jd) later again.

(See also the test1.c example.)

3. Computing the day of easter sunday
-------------------------------------

This functions compute the jd of the easter sunday for given year:

 long 	kal_jul_east(int y); 
  respectivelly:
 long 	kal_gre_east(int y);

(Dates of many christian feasts are evaluated from this date).

4. Days of week
---------------

A day of week can be simply obtained from jd by calling:

 int	kal_day_of_week(long jd);

    ,where 0 stands for sunday, 1==monday, 2==tuesday, etc.


Another functions give you the closest (next or previous) 'day of week':

 long 	kal_next_dw(long jd, int dw);
 long 	kal_prev_dw(long jd, int dw);

 For exapmle: "jd1=kal_next_dw(jd,0);" will make the jd1 to be the nearest 
sunday(==0) _after_ the jd, or to be equal to jd, if jd is a sunday. There
exist also two simillar functions, that differs in that the result is never
equal to the inputed jd.

 long 	kal_next_after_dw(long jd, int dw);
 long 	kal_prev_before_dw(long jd, int dw);

 (See also the 'test-dw.c' example.)


5. Names of months
------------------

I suppose that the names of the months are language dependand, so I don't 
cover them in this library. The only exeptions are the "exotic" calendars.
You can get that names by calling:

 char *	kal_jew_months(int m);
 char * kal_ar_months(int m);


6. Some notes on the Jewish calendar
------------------------------------

Jewish calendar is probably the most complicated calendary system ever existed.
It's so-called 'luni-solar' calendar, which means, that it's 'lunar' 
calendar, i.e. that the 'calendar month' equals to the 'lunar month', but
this is adjusted so, that every month remains in it's season.
In order to do that, jews have 7 times in 19 years 13 months per year.
But for historical reasons, this 'leap-month' isn't added at the end of the year, but after the sixth month. (Which was in the past the end of the year.)

This makes it ugly for computing- either would the relation between month
number and month name be not stable (it would be dependand on whether the
year is leap or not), or would the number of the month be not trully it's
number. I choose the second possibility, so that the month no. 7 may be used
in leap years only.

Therefore it might be usefull to know, whether the year is leap, or not. 
You may use 'int kal_jew_leap(int y)' function, which returns 1, if the year
is leap. 

(See functions 'prv' and 'nxt' in gtk-example/example.c)


7. Year adjustments
-------------------

It could happen, that we will do something with the years 'before [Christ |
creation | Hegira ]'. In such a case it's not nice to output to user something
like "Year -2", because it can be very confusing ( year "-2" is the "year 3
before" !). For that case ther are in this library two functions, which 
convert to and from "user friendly" form, having beside the year number 
a boolean variable "a", which tells, whether the year is "before" or not:

 int 	kal_year_code(int y, int a);    /* from 'user friendly' form */
 int 	kal_year_decode(int y, int *a);  /* to 'user friendly' form */

(See also the 'gtk-example'.)

8. Getting current date
-----------------------

The funcion kal_getdate() gets the jd of today's date. (Needs to be rewriten!)


9. More general function interface.
-----------------------------------

It can happen, that you will need general functions, to be independant 
on what calendar is beeing used. I Implemented here a simple table, where
basic routines for each calendar are stored and general functions, that can
call them. These functions are:
	
 long 	kal_conv_xxx_jd(int d, int m, int y, int sys);
 void 	kal_conv_jd_xxx(long &jd, int d, int y, int sys);
 long 	kal_xxx_east(int y, int sys);
 char *	kal_xxx_months(int m, int sys);
 
 ,where sys can be one of the following: KAL_JUL, KAL_GRE, KAL_AR, KAL_JEW for
the julianic, gregorianic .... calendary system.

 Note, that not all of the functions must be defined for all calendars. 
(It is, for example, nonsense to compute the date od Easter Sunday for jewish,
or arabic calendar - but not for gregorian or julian ones - and for example
also not for the coptic one [which is not implemented yet;-)].)
 In order to test if the function is available, call:

 int kal_proc_valid(int proc, int sys); 

 ,where 'proc' can be: KAL_PROCS_XXX_JD, KAL_PROCS_JD_XXX, KAL_PROCS_MONTHS or
KAL_PROCS_EAST. It results 0 on succes, 1 if the function doesn't exist.

 You can also get the abbreviation for the calendar by calling:

 char *	kal_proc_get_name(int sys);


 (For more see the 'gtk-example'.)


TESTING

 The library is not very well tested, althought something was done:
- I checked all the calendars with the 'check' utility for things that
   can be checked without having to have any chronological tables or calendars.
    (For more see check.c)
- I have (randomly) checked the library against some known-to-work programs. 
  (for example the 'xjewcal').
- I have (randomly) checked the 'jul', 'gre' and 'jew' calendars agains
  chronological tables and calendars I've found.

  I've been using this routines for about 2 years (since 1996), so there
is a chance, that they might be correct. Expecially the dates between 1990-
2000 should be o.k.

  Please, if You could test this library in any way, do so. Thanks.


ADDING NEW CALENDARS

If someone has any other calendar to be added to this library, should: 

  * Add the kal_conv_*_jd and kal_conv_jd_*  functions to the 
    (possible) kal_main.c .
  * Add other functions there. 
  * Update the kal_proc.h.
  * Test the library with 'check'.
  * Test it more using chronological tables etc.


AUTHOR

Petr Tomasek <tomasek@etf.cuni.cz>                               July 1998
