00001
00002
00003
00004
00005
00006
00007
00008
00009
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 +
00036 365L * xyear +
00037 (xyear / 4) +
00038 (-(xyear / 100)) +
00039 (xyear / 400);
00040 }
00041
00042
00043
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
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
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
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
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
00150 if ((hebrew_year_length(year) % 10) == 5)
00151 return 30;
00152 else
00153 return 29;
00154
00155 case Kislev:
00156
00157 if ((hebrew_year_length(year) % 10) == 3)
00158 return 29;
00159 else
00160 return 30;
00161
00162 case Adar:
00163
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
00175 int
00176 Converter::secular_month_length(int year,
00177 int month )
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
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
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
00235
00236
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)
00260 + 12L * (prev_year % 19)
00261 + (((prev_year % 19) * 7 + 1) / 19);
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
00287 int Converter::hebrew_year_length(int year)
00288 {
00289 return hebrew_elapsed_days(1 + year) - hebrew_elapsed_days(year);
00290 }
00291
00292
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
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
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
00340 result->day_of_week = (7 + absolute) % 7;
00341 result->hebrew_day_number =
00342 absolute - absolute_from_hebrew(hyear, 7, 1) + 1;
00343
00344 }