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-1; ++i) {
00249 saved_year[i] = saved_year[1 + i];
00250 saved_value[i] = saved_value[1 + i];
00251 }
00252 saved_year[MEMORY - 1] = year;
00253 saved_value[MEMORY - 1] = hebrew_elapsed_days2(year);
00254 return saved_value[MEMORY - 1];
00255 }
00256
00257 long Converter::hebrew_elapsed_days2(int year)
00258 {
00259 long prev_year = year - 1;
00260 long months_elapsed = 235L * (prev_year / 19)
00261 + 12L * (prev_year % 19)
00262 + (((prev_year % 19) * 7 + 1) / 19);
00263 long parts_elapsed = 5604 + 13753 * months_elapsed;
00264 long day = 1 + 29 * months_elapsed + parts_elapsed / 25920;
00265 long parts = parts_elapsed % 25920;
00266 int weekday = (day % 7);
00267 long alt_day = ((parts >= 19440)
00268 || (weekday == 2 && (parts >= 9924)
00269 && !hebrew_leap_year_p(year)) || (weekday == 1
00270 && (parts >=
00271 16789)
00272 &&
00273 hebrew_leap_year_p
00274 (prev_year)))
00275 ? day + 1 : day;
00276 switch (alt_day % 7)
00277 {
00278 case 0:
00279 case 3:
00280 case 5:
00281 return 1 + alt_day;
00282 default:
00283 return alt_day;
00284 }
00285 }
00286
00287
00288 int Converter::hebrew_year_length(int year)
00289 {
00290 return hebrew_elapsed_days(1 + year) - hebrew_elapsed_days(year);
00291 }
00292
00293
00294 void
00295 Converter::SecularToHebrewConversion(int syear, int smonth,
00296 int sday,
00297 struct DateResult *result)
00298 {
00299 int hyear, hmonth, hday;
00300 long absolute;
00301
00302 absolute = absolute_from_gregorian(syear, smonth, sday);
00303
00304 hebrew_from_absolute(absolute, &hyear, &hmonth, &hday);
00305
00306 result->year = hyear;
00307 result->month = hmonth;
00308 result->day = hday;
00309 finish_up(absolute, hyear, hmonth, syear, smonth, result);
00310 }
00311
00312
00313 void
00314 Converter::HebrewToSecularConversion(int hyear, int hmonth,
00315 int hday,
00316 struct DateResult *result)
00317 {
00318 int syear, smonth, sday;
00319 long absolute;
00320
00321 absolute = absolute_from_hebrew(hyear, hmonth, hday);
00322 gregorian_from_absolute(absolute, &syear, &smonth, &sday);
00323 result->year = hyear;
00324 result->month = hmonth;
00325 result->day = hday;
00326 finish_up(absolute, hyear, hmonth, syear, smonth, result);
00327 }
00328
00329
00330 void
00331 Converter::finish_up(long absolute, int hyear, int hmonth,
00332 int syear, int smonth,
00333 struct DateResult *result)
00334 {
00335 result->hebrew_month_length = hebrew_month_length(hyear, hmonth);
00336 result->secular_month_length = secular_month_length(syear, smonth);
00337 result->hebrew_leap_year_p = hebrew_leap_year_p(hyear);
00338 result->secular_leap_year_p = gregorian_leap_year_p(syear);
00339 result->kvia = (hebrew_year_length(hyear) % 10) - 3;
00340
00341 result->day_of_week = (7 + absolute) % 7;
00342 result->hebrew_day_number =
00343 absolute - absolute_from_hebrew(hyear, 7, 1) + 1;
00344
00345 }