/* Islamic calendar utility functions * * Copyright (C) 1999 Ali Abdin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include static int last_day_of_gregorian_month (int month, int year) { int monthdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; /* Last day of gregorian month during year */ if ((month == 2) && ((year % 4) == 0) && ((year % 400) != 100) && ((year % 400) != 200) && ((year % 400) != 300)) return 29; else return monthdays[month-1]; } #if 1 glong absolute_from_gregorian (int month, int day, int year) { /* WARNING: This uses 1/1/1 == '1' as the absolute date */ /* Absolute date given gregorian */ long absolutedays, monthdays; int m; long dayyears; div_t tmpdiv; absolutedays = day; /* Days so far this month */ monthdays = 0; for (m = 1; m < month; m++) monthdays = monthdays + last_day_of_gregorian_month (m, year); /* Days in prior months /this/ year */ dayyears = 365.0 * (year-1); /* days in prior years */ /* g_print ("dayyears is: %d\n", dayyears); */ tmpdiv = div (year-1, 4); dayyears = dayyears + tmpdiv.quot; /* g_print ("dayyears is: %d\n", dayyears); */ /* add julian leap days in prior years */ tmpdiv = div(year-1, 100); dayyears = dayyears - (tmpdiv.quot); /* minus prior century years */ tmpdiv = div(year-1, 400); dayyears = dayyears + (tmpdiv.quot); /* Add back the years divisible by 400 */ /* g_print ("days is: %d\ndayyears is: %d\n",absolutedays,dayyears); */ return (absolutedays + dayyears + monthdays); } #endif static gboolean islamic_leap_year (gint year) { /* Given Islamic year return TRUE if it is a leap year */ if ((((year * 11) + 14) % 30) < 11) return TRUE; else return FALSE; } static gint last_day_of_islamic_month (gint month, gint year) { /* Given the islamic month/year it returns the size of the month */ if (((month % 2) == 1) || ((month == 12) && islamic_leap_year (year))) return 30; /* Odd months and 12th month of a leap year are both 30 days */ else return 29; } static glong absolute_from_islamic (gint month, gint day, gint year) { glong absolutedays; div_t tmpdiv; /* Add days so far this month + days so far this year excluding leap * years */ absolutedays = day + (29 * (month-1)); tmpdiv = div (month,2); absolutedays = absolutedays + tmpdiv.quot; /* Number of days this year */ absolutedays = absolutedays + ((year-1) * 354); /* non-leap days in prior years */ tmpdiv = div(((11 * year) + 3), 30); absolutedays = absolutedays + tmpdiv.quot; /* leap days in prior years */ // g_print ("absolutedays is %d\n",absolutedays); /* you have to subtract an extra '1' since you pass over '0' */ absolutedays = absolutedays + (-492148) - 1; /* The above is the 'magic' number since '0' is the epoch (1/1/1970) * and 7/19/622 is the first day of the Islamic calendar (-492148 or * 492,148 days before the epoch) */ return absolutedays; } static void islamic_from_absolute (glong absolute, gint *month, gint *day, gint *year) { if (absolute < -492148) { /* This is before Islam */ *month = 0; *day = 0; *year = 0; } else { gint y,m; gint tmpsum = 0; div_t tmpdiv; glong tmplong; /* We need a temp 'long' value for the day */ /* Approximate the islamic year from the absolute date */ tmpdiv = div ( absolute - (-492148), 355); *year = tmpdiv.quot; for (y = tmpdiv.quot; absolute >= absolute_from_islamic (1, 1, y+1); y++) { tmpsum = tmpsum++; } /* Forward search for the exact islamic year */ *year = *year + tmpsum; tmpsum = 0; for (m = 1; absolute > absolute_from_islamic (m, last_day_of_islamic_month (m, *year), *year); m++) { tmpsum = tmpsum++; } *month = 1 + tmpsum; /* Calculate the days by subtraction */ tmplong = absolute - (1 - (absolute_from_islamic (*month, 1, *year))); *day = absolute + (1 - (absolute_from_islamic (*month, 1, *year))); } } time_t time_from_islamic_date (int imonth, int iday, int iyear) { struct tm tm; glong totaldays; gint addyears, month, day; gint y; memset (&tm, 0, sizeof (tm)); totaldays = absolute_from_islamic (imonth, iday, iyear); // if (totaldays > 0) { addyears = (gint) totaldays / 366; g_print ("addyears is: %d\n",addyears); for (y = addyears; totaldays >= absolute_from_gregorian (1,1, 1970 + y) ;y++); addyears = y; /* Number of years to add to 1970 */ for (month = 1; totaldays > (absolute_from_gregorian (month, last_day_of_gregorian_month (month, addyears + 1970), addyears + 1970)) - absolute_from_gregorian (1,1,1970); month++); g_print ("totaldays = %d - %d - %d;\n",totaldays, absolute_from_gregorian (month,1, 1970 + addyears), absolute_from_gregorian (1,1,1970)); day = totaldays + (1 - (absolute_from_gregorian (month, 1, 1970 + addyears) - absolute_from_gregorian (1,2,1970))); g_print ("addyears is %d\nmonth is %d\nday is %d\n",addyears, month, day); tm.tm_year = 70 + addyears; tm.tm_mon = month-1; tm.tm_mday = day; // } return mktime (&tm); } void islamic_from_time (time_t time, gint *month, gint *day, gint *year) { glong absolute; absolute = (gint) time / (60*60*24); /* Turn from seconds into days */ islamic_from_absolute (absolute, month, day, year); } int main (int argc, char **argv) { gint month,day,year,x; gboolean failed = FALSE; time_t temptime; g_print ("1/1/1970 is %d and it is a %d\n", absolute_from_gregorian (1,1,1970), absolute_from_gregorian (1,1,1970) % 7); g_print ("07/19/622 is %d it is a %d\n", absolute_from_gregorian (7,19,622), absolute_from_gregorian (7,19,622) % 7); g_print ("4/6/2000 is %d\n", absolute_from_gregorian (4,6,2000)); g_print ("4/13/2000 is %d\n", absolute_from_gregorian (4,13,2000)); g_print ("Islamic date 1/1/1 is %d in absolute time_t\n", absolute_from_islamic (1,1,1)); g_print ("Islamic date 1/2/1 is %d in absolute time_t\n", absolute_from_islamic (1,2,1)); g_print ("Islamic date 1/1/1421 is %d in absolute time_t\n", absolute_from_islamic (1,1,1421)); islamic_from_absolute (-492148,&month,&day,&year); g_print ("Given absolute -492148 the islam stuff is: %d %d %d\n",month,day,year); islamic_from_absolute(11053,&month,&day,&year); g_print ("Given absolute 11053 the islam stuff is: %d %d %d\n",month,day,year); islamic_from_absolute (-492147,&month,&day,&year); g_print ("Given absolute -492147 the islam stuff is: %d %d %d\n",month,day,year); islamic_from_absolute (11060,&month,&day,&year); g_print ("Given absolute 11060 the islam stuff is: %d %d %d\n",month,day,year); islamic_from_absolute (-492149,&month,&day,&year); g_print ("Given absolute -492149 the islam stuff is: %d %d %d\n",month,day,year); temptime = time_from_islamic_date (1,1,1421); g_print ("time_from_islamic_date(1,1,1421) is %d\n", temptime); islamic_from_time (temptime, &month,&day, &year); g_print ("time_t %d in islamic is: %d %d %d\n",temptime,month,day,year); temptime = time_from_islamic_date (1,8,1421); g_print ("time_from_islamic_date(1,8,1421) is %d\n", temptime); islamic_from_time (temptime, &month,&day, &year); g_print ("time_t %d in islamic is: %d %d %d\n",temptime,month,day,year); islamic_from_time (time (NULL), &month,&day,&year); g_print ("time_t %d (RIGHT NOW!) in islamic is: %d %d %d\n",time(NULL),month,day,year); /* g_print ("Running Islamic Stress Test: "); for (x = -492148; x <= 492148; x++) { islamic_from_absolute(x, &month, &day, &year); if ((absolute_from_islamic (month,day,year)) != x) failed = TRUE; } if (failed) g_print ("FAILED"); else g_print ("PASSED"); */ return 0; }