korganizer Library API Documentation

converter.cpp

00001 /*************************************************************************** 00002 * Copyright (C) 2003 by Jonathan Singer * 00003 * jsinger@leeta.net * 00004 * Calendar routines from Hebrew Calendar by Frank Yellin * 00005 * * 00006 * This program is free software; you can redistribute it and/or modify * 00007 * it under the terms of the GNU General Public License as published by * 00008 * the Free Software Foundation; either version 2 of the License, or * 00009 * (at your option) any later version. * 00010 ***************************************************************************/ 00011 #include "converter.h" 00012 #include <klocale.h> 00013 00014 Converter::Converter() 00015 { 00016 00017 } 00018 00019 Converter::~Converter() 00020 { 00021 } 00022 00023 long Converter::absolute_from_gregorian(int year, int month, int day) 00024 { 00025 int xyear, day_number; 00026 00027 xyear = year - 1; 00028 day_number = day + 31 * (month - 1); 00029 if (month > 2) 00030 { 00031 day_number -= (23 + (4 * month)) / 10; 00032 if (gregorian_leap_year_p(year)) 00033 day_number++; 00034 } 00035 return day_number + /* the day number within the current year */ 00036 365L * xyear + /* days in prior years */ 00037 (xyear / 4) + /* Julian leap years */ 00038 (-(xyear / 100)) + /* deduct century years */ 00039 (xyear / 400); /* add Gregorian leap years */ 00040 } 00041 00042 /* Given a Hebrew date, calculate the number of days since 00043 * January 0, 0001, Gregorian 00044 */ 00045 long Converter::absolute_from_hebrew(int year, int month, int day) 00046 { 00047 long sum = day + hebrew_elapsed_days(year) - 1373429L; 00048 int i; 00049 00050 if (month < 7) 00051 { 00052 int months = hebrew_months_in_year(year); 00053 00054 for (i = 7; i <= months; i++) 00055 sum += hebrew_month_length(year, i); 00056 for (i = 1; i < month; i++) 00057 sum += hebrew_month_length(year, i); 00058 } 00059 else 00060 { 00061 for (i = 7; i < month; i++) 00062 sum += hebrew_month_length(year, i); 00063 } 00064 return sum; 00065 } 00066 00067 /* Given an absolute date, calculate the gregorian date */ 00068 void 00069 Converter::gregorian_from_absolute(long date, int *yearp, 00070 int *monthp, int *dayp) 00071 { 00072 int year, month, day; 00073 00074 for (year = date / 366; 00075 date >= absolute_from_gregorian(year + 1, 1, 1); year++) ; 00076 for (month = 1; 00077 (month <= 11) 00078 && (date >= absolute_from_gregorian(year, 1 + month, 1)); 00079 month++) ; 00080 day = 1 + date - absolute_from_gregorian(year, month, 1); 00081 *yearp = year; 00082 *monthp = month; 00083 *dayp = day; 00084 } 00085 00086 /* Given an absolute date, calculate the Hebrew date */ 00087 void 00088 Converter::hebrew_from_absolute(long date, int *yearp, int *monthp, 00089 int *dayp) 00090 { 00091 int year, month, day, gyear, gmonth, gday, months; 00092 00093 gregorian_from_absolute(date, &gyear, &gmonth, &gday); 00094 year = gyear + 3760; 00095 while (date >= absolute_from_hebrew(1 + year, 7, 1)) 00096 year++; 00097 months = hebrew_months_in_year(year); 00098 for (month = 7; 00099 date > absolute_from_hebrew(year, month, 00100 hebrew_month_length(year, month)); 00101 month = 1 + (month % months)) ; 00102 day = 1 + date - absolute_from_hebrew(year, month, 1); 00103 *yearp = year; 00104 *monthp = month; 00105 *dayp = day; 00106 } 00107 00108 /* Number of months in a Hebrew year */ 00109 int Converter::hebrew_months_in_year(int year) 00110 { 00111 if (hebrew_leap_year_p(year)) 00112 return 13; 00113 else 00114 return 12; 00115 } 00116 00117 enum 00118 { Nissan = 00119 1, Iyar, Sivan, Tamuz, Ab, Elul, Tishrei, Cheshvan, Kislev, Tevet, 00120 Shvat, Adar, AdarII, AdarI = 12 00121 }; 00122 00123 enum 00124 { January = 00125 1, February, March, April, May, June, July, August, September, 00126 October, November, December 00127 }; 00128 00129 /* Number of days in a Hebrew month */ 00130 int Converter::hebrew_month_length(int year, int month) 00131 { 00132 switch (month) 00133 { 00134 case Tishrei: 00135 case Shvat: 00136 case Nissan: 00137 case Sivan: 00138 case Ab: 00139 return 30; 00140 00141 case Tevet: 00142 case Iyar: 00143 case Tamuz: 00144 case Elul: 00145 case AdarII: 00146 return 29; 00147 00148 case Cheshvan: 00149 // 29 days, unless it's a long year. 00150 if ((hebrew_year_length(year) % 10) == 5) 00151 return 30; 00152 else 00153 return 29; 00154 00155 case Kislev: 00156 // 30 days, unless it's a short year. 00157 if ((hebrew_year_length(year) % 10) == 3) 00158 return 29; 00159 else 00160 return 30; 00161 00162 case Adar: 00163 // Adar (non-leap year) has 29 days. Adar I has 30 days. 00164 if (hebrew_leap_year_p(year)) 00165 return 30; 00166 else 00167 return 29; 00168 00169 default: 00170 return 0; 00171 } 00172 } 00173 00174 /* Number of days in a Julian or gregorian month */ 00175 int 00176 Converter::secular_month_length(int year, 00177 int month /*, bool julianp */ ) 00178 { 00179 switch (month) 00180 { 00181 case January: 00182 case March: 00183 case May: 00184 case July: 00185 case August: 00186 case October: 00187 case December: 00188 return 31; 00189 case April: 00190 case June: 00191 case September: 00192 case November: 00193 return 30; 00194 case February: 00195 if (gregorian_leap_year_p(year)) 00196 return 29; 00197 else 00198 return 28; 00199 default: 00200 return 0; 00201 } 00202 } 00203 00204 /* Is it a Leap year in the gregorian calendar */ 00205 bool Converter::gregorian_leap_year_p(int year) 00206 { 00207 if ((year % 4) != 0) 00208 return 0; 00209 if ((year % 400) == 0) 00210 return 1; 00211 if ((year % 100) == 0) 00212 return 0; 00213 return 1; 00214 } 00215 00216 /* Is it a leap year in the Jewish Calendar */ 00217 bool Converter::hebrew_leap_year_p(int year) 00218 { 00219 switch (year % 19) 00220 { 00221 case 0: 00222 case 3: 00223 case 6: 00224 case 8: 00225 case 11: 00226 case 14: 00227 case 17: 00228 return 1; 00229 default: 00230 return 0; 00231 } 00232 } 00233 00234 /* Return the number of days from 1 Tishrei 0001 to the beginning of the given year. 00235 * Since this routine gets called frequently with the same year arguments, we cache 00236 * the most recent values. 00237 */ 00238 #define MEMORY 5 00239 long Converter::hebrew_elapsed_days(int year) 00240 { 00241 static int saved_year[MEMORY] = { -1, -1, -1, -1, -1 }; 00242 static long saved_value[MEMORY]; 00243 int i; 00244 00245 for (i = 0; i < MEMORY; i++) 00246 if (year == saved_year[i]) 00247 return saved_value[i]; 00248 for (i = 0; i < MEMORY; i++) 00249 saved_year[i] = saved_year[1 + i], saved_value[i] = 00250 saved_value[1 + i]; 00251 saved_year[MEMORY - 1] = year; 00252 saved_value[MEMORY - 1] = hebrew_elapsed_days2(year); 00253 return saved_value[MEMORY - 1]; 00254 } 00255 00256 long Converter::hebrew_elapsed_days2(int year) 00257 { 00258 long prev_year = year - 1; 00259 long months_elapsed = 235L * (prev_year / 19) /* months in complete cycles so far */ 00260 + 12L * (prev_year % 19) /* regular months in this cycle */ 00261 + (((prev_year % 19) * 7 + 1) / 19); /* leap months this cycle */ 00262 long parts_elapsed = 5604 + 13753 * months_elapsed; 00263 long day = 1 + 29 * months_elapsed + parts_elapsed / 25920; 00264 long parts = parts_elapsed % 25920; 00265 int weekday = (day % 7); 00266 long alt_day = ((parts >= 19440) 00267 || (weekday == 2 && (parts >= 9924) 00268 && !hebrew_leap_year_p(year)) || (weekday == 1 00269 && (parts >= 00270 16789) 00271 && 00272 hebrew_leap_year_p 00273 (prev_year))) 00274 ? day + 1 : day; 00275 switch (alt_day % 7) 00276 { 00277 case 0: 00278 case 3: 00279 case 5: 00280 return 1 + alt_day; 00281 default: 00282 return alt_day; 00283 } 00284 } 00285 00286 /* Number of days in the given Hebrew year */ 00287 int Converter::hebrew_year_length(int year) 00288 { 00289 return hebrew_elapsed_days(1 + year) - hebrew_elapsed_days(year); 00290 } 00291 00292 /* Fill in the DateResult structure based on the given secular date */ 00293 void 00294 Converter::SecularToHebrewConversion(int syear, int smonth, 00295 int sday, 00296 struct DateResult *result) 00297 { 00298 int hyear, hmonth, hday; 00299 long absolute; 00300 00301 absolute = absolute_from_gregorian(syear, smonth, sday); 00302 00303 hebrew_from_absolute(absolute, &hyear, &hmonth, &hday); 00304 00305 result->year = hyear; 00306 result->month = hmonth; 00307 result->day = hday; 00308 finish_up(absolute, hyear, hmonth, syear, smonth, result); 00309 } 00310 00311 /* Fill in the DateResult structure based on the given Hebrew date */ 00312 void 00313 Converter::HebrewToSecularConversion(int hyear, int hmonth, 00314 int hday, 00315 struct DateResult *result) 00316 { 00317 int syear, smonth, sday; 00318 long absolute; 00319 00320 absolute = absolute_from_hebrew(hyear, hmonth, hday); 00321 gregorian_from_absolute(absolute, &syear, &smonth, &sday); 00322 result->year = hyear; 00323 result->month = hmonth; 00324 result->day = hday; 00325 finish_up(absolute, hyear, hmonth, syear, smonth, result); 00326 } 00327 00328 /* This is common code for filling up the DateResult structure */ 00329 void 00330 Converter::finish_up(long absolute, int hyear, int hmonth, 00331 int syear, int smonth, 00332 struct DateResult *result) 00333 { 00334 result->hebrew_month_length = hebrew_month_length(hyear, hmonth); 00335 result->secular_month_length = secular_month_length(syear, smonth); 00336 result->hebrew_leap_year_p = hebrew_leap_year_p(hyear); 00337 result->secular_leap_year_p = gregorian_leap_year_p(syear); 00338 result->kvia = (hebrew_year_length(hyear) % 10) - 3; 00339 // absolute is -1 on 1/1/0001 Julian 00340 result->day_of_week = (7 + absolute) % 7; 00341 result->hebrew_day_number = 00342 absolute - absolute_from_hebrew(hyear, 7, 1) + 1; 00343 00344 }
KDE Logo
This file is part of the documentation for korganizer Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 27 12:53:18 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003