• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDECore

kcalendarsystemhebrew.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright (c) 2003 Hans Petter Bieker <bieker@kde.org>
00003     Copyright (c) 2007 John Layt <john@layt.net>
00004         Calendar conversion routines based on Hdate v6, by Amos
00005         Shapir 1978 (rev. 1985, 1992)
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Library General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Library General Public License for more details.
00016 
00017     You should have received a copy of the GNU Library General Public License
00018     along with this library; see the file COPYING.LIB.  If not, write to
00019     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020     Boston, MA 02110-1301, USA.
00021 */
00022 
00023 // Derived hebrew kde calendar class
00024 
00025 #include "kcalendarsystemhebrew.h"
00026 
00027 #include "kdebug.h"
00028 #include "klocale.h"
00029 
00030 #include <QtCore/QDate>
00031 #include <QtCore/QCharRef>
00032 
00033 //===========================================================================
00034 //  This section holds the old Hebrew <=> jd <=> Hebrew conversion code
00035 //  This is here to allow comparison testing to confirm old and new match
00036 //===========================================================================
00037 
00038 static int hebrewDaysElapsed( int y );
00039 
00040 static QString num2heb( int num, bool includeMillenium );
00041 
00042 class h_date
00043 {
00044 public:
00045     int hd_day;
00046     int hd_mon;
00047     int hd_year;
00048     int hd_dw;
00049     int hd_flg;
00050 };
00051 
00052 /*
00053  * compute general date structure from hebrew date
00054  */
00055 static class h_date * hebrewToGregorian( int y, int m, int d )
00056 {
00057     static class h_date h;
00058     int s;
00059 
00060     y -= 3744;
00061     s = hebrewDaysElapsed( y );
00062     d += s;
00063     s = hebrewDaysElapsed( y + 1 ) - s;    /* length of year */
00064 
00065     if ( s > 365 && m > 6 ) {
00066         --m;
00067         d += 30;
00068     }
00069     d += ( 59 * ( m - 1 ) + 1 ) / 2;  /* regular months */
00070     /* special cases */
00071     if ( s % 10 > 4 && m > 2 ) {  /* long Heshvan */
00072         d++;
00073     }
00074     if ( s % 10 < 4 && m > 3 ) {  /* short Kislev */
00075         d--;
00076     }
00077     // ### HPB: Broken in leap years
00078     //if (s > 365 && m > 6)  /* leap year */
00079     //  d += 30;
00080     d -= 6002;
00081 
00082     y = ( d + 36525 ) * 4 / 146097 - 1;
00083     d -= y / 4 * 146097 + ( y % 4 ) * 36524;
00084     y *= 100;
00085 
00086     /* compute year */
00087     s = ( d + 366 )*4 / 1461 - 1;
00088     d -= s / 4*1461 + ( s % 4 )*365;
00089     y += s;
00090     /* compute month */
00091     m = ( d + 245 )*12 / 367 - 7;
00092     d -= m*367 / 12 - 30;
00093     if ( ++m >= 12 ) {
00094         m -= 12;
00095         y++;
00096     }
00097     h.hd_day = d;
00098     h.hd_mon = m;
00099     h.hd_year = y;
00100     return( &h );
00101 }
00102 
00103 /*
00104  * compute date structure from no. of days since 1 Tishrei 3744
00105  */
00106 static class h_date * gregorianToHebrew( int y, int m, int d )
00107 {
00108     static class h_date h;
00109     int s;
00110 
00111     if ( ( m -= 2 ) <= 0 ) {
00112         m += 12;
00113         y--;
00114     }
00115     /* no. of days, Julian calendar */
00116     d += 365*y + y / 4 + 367*m / 12 + 5968;
00117     /* Gregorian calendar */
00118     d -= y / 100 - y / 400 - 2;
00119     h.hd_dw = ( d + 1 ) % 7;
00120 
00121     /* compute the year */
00122     y += 16;
00123     s = hebrewDaysElapsed( y );
00124     m = hebrewDaysElapsed( y + 1 );
00125     while( d >= m ) {  /* computed year was underestimated */
00126         s = m;
00127         y++;
00128         m = hebrewDaysElapsed( y + 1 );
00129     }
00130     d -= s;
00131     s = m - s;  /* size of current year */
00132     y += 3744;
00133 
00134     h.hd_flg = s % 10 - 4;
00135 
00136     /* compute day and month */
00137     if ( d >= s - 236 ) {  /* last 8 months are regular */
00138         d -= s - 236;
00139         m = d * 2 / 59;
00140         d -= ( m * 59 + 1 ) / 2;
00141         m += 4;
00142         if ( s > 365 && m <= 5 ) {  /* Adar of Meuberet */
00143             m += 8;
00144         }
00145     } else {
00146         /* first 4 months have 117-119 days */
00147         s = 114 + s % 10;
00148         m = d * 4 / s;
00149         d -= ( m * s + 3 ) / 4;
00150     }
00151 
00152     h.hd_day = d;
00153     h.hd_mon = m;
00154     h.hd_year = y;
00155     return( &h );
00156 }
00157 
00158 static QString num2heb( int num, bool includeMillenium )
00159 {
00160     const QChar decade[] = {
00161                                0x05D8, 0x05D9, 0x05DB, 0x05DC, 0x05DE,
00162                                0x05E0, 0x05E1, 0x05E2, 0x05E4, 0x05E6
00163                            };
00164     QString result;
00165 
00166     if ( num < 1 || num > 9999 ) {
00167         return QString::number( num );
00168     }
00169 
00170     if ( num >= 1000 ) {
00171         if ( includeMillenium || num % 1000 == 0 )
00172             result += QChar( 0x05D0 - 1 + num / 1000 );
00173         num %= 1000;
00174     }
00175 
00176     if ( num >= 100 ) {
00177         while ( num >= 500 ) {
00178             result += QChar( 0x05EA );
00179             num -= 400;
00180         }
00181         result += QChar( 0x05E7 - 1 + num / 100 );
00182         num %= 100;
00183     }
00184 
00185     if ( num >= 10 ) {
00186         if ( num == 15 || num == 16 )
00187             num -= 9;
00188         result += decade[num / 10];
00189         num %= 10;
00190     }
00191 
00192     if ( num > 0 ) {
00193         result += QChar( 0x05D0 - 1 + num );
00194     }
00195 
00196     if ( result.length() == 1 ) {
00197         result += '\'';
00198     } else {
00199         result.insert( result.length() - 1, '\"' );
00200     }
00201 
00202     return result;
00203 }
00204 
00205 static int heb2num( const QString &str, int &iLength )
00206 {
00207     QChar c;
00208     QString s = str;
00209     int result = 0;
00210     iLength = 0;
00211     int decadeValues[14] = {10, 20, 20, 30, 40, 40, 50,
00212                             50, 60, 70, 80, 80, 90, 90};
00213 
00214     int pos;
00215     for ( pos = 0 ; pos < s.length() ; pos++ ) {
00216         c = s[pos];
00217         if ( s.length() > pos && ( s[pos + 1] == QChar( '\'' ) ||
00218                                    s[pos + 1] == QChar( '\"' ) ) ) {
00219             iLength++;
00220             s.remove( pos + 1, 1 );
00221         }
00222 
00223         if ( c >= QChar( 0x05D0 ) && c <= QChar( 0x05D7 ) ) {
00224             if ( s.length() > pos && s[pos + 1] >= QChar( 0x05D0 ) &&
00225                     s[pos + 1] <= QChar( 0x05EA ) ) {
00226                 result += ( c.unicode() - 0x05D0 + 1 ) * 1000;
00227             } else {
00228                 result += c.unicode() - 0x05D0 + 1;
00229             }
00230         } else if ( c == QChar( 0x05D8 ) ) {
00231             if ( s.length() > pos && s[pos + 1] >= QChar( 0x05D0 ) &&
00232                     s[pos + 1] <= QChar( 0x05EA ) && s[pos + 1] != QChar( 0x05D5 ) &&
00233                     s[pos + 1] != QChar( 0x05D6 ) ) {
00234                 result += 9000;
00235             } else {
00236                 result += 9;
00237             }
00238         } else if ( c >= QChar( 0x05D9 ) && c <= QChar( 0x05E6 ) ) {
00239             if ( s.length() > pos && s[pos + 1] >= QChar( 0x05D9 ) ) {
00240                 return -1;
00241             } else {
00242                 result += decadeValues[c.unicode() - 0x05D9];
00243             }
00244         } else if ( c >= QChar( 0x05E7 ) && c <= QChar( 0x05EA ) ) {
00245             result += ( c.unicode() - 0x05E7 + 1 ) * 100;
00246         } else {
00247             break;
00248         }
00249     }
00250 
00251     iLength += pos;
00252 
00253     return result;
00254 }
00255 
00256 /* constants, in 1/18th of minute */
00257 static const int HOUR = 1080;
00258 static const int DAY = 24*HOUR;
00259 static const int WEEK = 7*DAY;
00260 #define M(h,p) ((h)*HOUR+p)
00261 #define MONTH (DAY+M(12,793))
00262 
00267 static int hebrewDaysElapsed( int y )
00268 {
00269     int m, nm, dw, s, l;
00270 
00271     l = y * 7 + 1;  // no. of leap months
00272     m = y * 12 + l / 19;  // total no. of months
00273     l %= 19;
00274     nm = m * MONTH + M( 1 + 6, 779 ); // molad new year 3744 (16BC) + 6 hours
00275     s = m * 28 + nm / DAY - 2;
00276 
00277     nm %= WEEK;
00278     dw = nm / DAY;
00279     nm %= DAY;
00280 
00281     // special cases of Molad Zaken
00282     if ( (l < 12 && dw == 3 && nm >= M( 9 + 6, 204 )) ||
00283             (l < 7 && dw == 2 && nm >= M( 15 + 6, 589 )) ) {
00284         s++, dw++;
00285     }
00286 
00287     /* ADU */
00288     if ( dw == 1 || dw == 4 || dw == 6 ) {
00289         s++;
00290     }
00291     return s;
00292 }
00293 
00298 static int long_cheshvan( int year )
00299 {
00300     QDate first, last;
00301     class h_date *gd;
00302 
00303     gd = hebrewToGregorian( year, 1, 1 );
00304     first.setYMD( gd->hd_year, gd->hd_mon + 1, gd->hd_day + 1 );
00305 
00306     gd = hebrewToGregorian( year + 1, 1, 1 );
00307     last.setYMD( gd->hd_year, gd->hd_mon + 1, gd->hd_day + 1 );
00308 
00309     return ( first.daysTo( last ) % 10 == 5 );
00310 }
00311 
00316 static int short_kislev( int year )
00317 {
00318     QDate first, last;
00319     class h_date * gd;
00320 
00321     gd = hebrewToGregorian( year, 1, 1 );
00322     first.setYMD( gd->hd_year, gd->hd_mon + 1, gd->hd_day + 1 );
00323 
00324     gd = hebrewToGregorian( year + 1, 1, 1 );
00325     last.setYMD( gd->hd_year, gd->hd_mon + 1, gd->hd_day + 1 );
00326 
00327     return ( first.daysTo( last ) % 10 == 3 );
00328 }
00329 
00330 static bool is_leap_year( int year )
00331 {
00332     return ( ( ( ( 7 * year ) + 1 ) % 19 ) < 7 );
00333 }
00334 
00335 // Ok
00336 static class h_date *toHebrew( const QDate &date )
00337 {
00338     class h_date *sd;
00339 
00340     sd = gregorianToHebrew( date.year(), date.month(), date.day() );
00341     ++sd->hd_mon;
00342     ++sd->hd_day;
00343 
00344     return sd;
00345 }
00346 
00347 //===========================================================================
00348 //  End of old code
00349 //===========================================================================
00350 
00351 class KCalendarSystemHebrewPrivate
00352 {
00353 public:
00354     int characterOfYear( int year ) const;
00355     int julianDayOfTishri1( int year ) const;
00356     int yearOfJulianDay( int jd ) const;
00357     int daysPreceedingMonth( int character, int month ) const;
00358 
00366     int hndays( int year, int mon ) const;
00367 };
00368 
00369 int KCalendarSystemHebrewPrivate::daysPreceedingMonth( int character, int month ) const
00370 {
00371     // FIXME move to Private class header as static when figure out how to do it without compiler errors :-)
00372     int daysPreceedingMonthTable[6][13] =
00373         {
00374             {0, 30, 59, 88, 117, 147, 176, 206, 235, 265, 294, 324, },
00375             {0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325, },
00376             {0, 30, 60, 90, 119, 149, 178, 208, 237, 267, 296, 326, },
00377             {0, 30, 59, 88, 117, 147, 177, 206, 236, 265, 295, 324, 354},
00378             {0, 30, 59, 89, 118, 148, 178, 207, 237, 266, 296, 325, 355},
00379             {0, 30, 60, 90, 119, 149, 179, 209, 238, 267, 297, 326, 356},
00380         };
00381 
00382     if ( character >= 1 && character <= 6  && month >= 1 && month <= 13 ) {
00383         return daysPreceedingMonthTable[character-1][month-1];
00384     }
00385     return -911;
00386 }
00387 
00388 int KCalendarSystemHebrewPrivate::characterOfYear( int year ) const
00389 {
00390     int jdTishri1ThisYear = julianDayOfTishri1( year );
00391     int jdTishri1NextYear = julianDayOfTishri1( year + 1 );
00392     int K = jdTishri1NextYear - jdTishri1ThisYear - 352
00393             - 27 * ( ( 7 * year + 13 ) % 19 ) / 12;
00394     return K;
00395 }
00396 
00397 // Hatcher formula G
00398 int KCalendarSystemHebrewPrivate::julianDayOfTishri1( int year ) const
00399 {
00400     // if calc of t overflows, have alternative formula for step
00401     long t = 31524 + 765433 * ( ( 235 * year - 234 ) / 19 );
00402     int d = t / 25920;
00403     int t1 = t % 25920;
00404     int w = 1 + ( d % 7 );
00405     int E = ( ( 7 * year + 13 ) % 19 ) / 12;
00406     int E1 = ( ( 7 * year + 6 ) % 19 ) / 12;
00407     if (  t1 >= 19940 ||
00408             ( t1 >= 9924 && w == 3 && E == 0 ) ||
00409             ( t1 >= 16788 && w == 2 && E == 0 && E1 == 1 ) ) {
00410         d = d + 1;
00411     }
00412     int jd = d + ( ( ( d + 5 ) % 7 ) % 2 ) + 347997;
00413     return jd;
00414 }
00415 
00416 // Hatcher formula H
00417 int KCalendarSystemHebrewPrivate::yearOfJulianDay( int jd ) const
00418 {
00419     long M = ( 25920 * ( jd - 347996 ) ) / 765433 + 1;
00420     int year = 19 * ( M / 235 ) + ( 19 * ( M % 2356 ) - 2 ) / 235 + 1;
00421     if ( julianDayOfTishri1( year ) > jd ) {
00422         year = year - 1;
00423     }
00424     return year;
00425 }
00426 
00427 int KCalendarSystemHebrewPrivate::hndays( int mon, int year ) const
00428 {
00429     if ( mon == 6 && is_leap_year( year ) ) {
00430         mon = 13; /*Adar I*/
00431     } else if ( mon == 7 && is_leap_year( year ) ) {
00432         mon = 14; /*Adar II*/
00433     } else if ( mon > 7 && is_leap_year( year ) ) {
00434         mon--; //Because of Adar II
00435     }
00436 
00437     if( mon == 8 /*IYYAR*/ || mon == 10 /*TAMUZ*/ ||
00438             mon == 12 /*ELUL*/ || mon == 4 /*TEVET*/ ||
00439             mon == 14 /*ADAR 2*/ ||
00440             ( mon == 6 /*ADAR*/ && !is_leap_year( year ) ) ||
00441             ( mon ==  2 /*CHESHVAN*/ && !long_cheshvan( year ) ) ||
00442             ( mon == 3 /*KISLEV*/ && short_kislev( year ) ) ) {
00443         return 29;
00444     } else {
00445         return 30;
00446     }
00447 }
00448 
00449 // Ok
00450 KCalendarSystemHebrew::KCalendarSystemHebrew( const KLocale * locale )
00451         : KCalendarSystem( locale ), d( new KCalendarSystemHebrewPrivate )
00452 {
00453 }
00454 
00455 // Ok
00456 KCalendarSystemHebrew::~KCalendarSystemHebrew()
00457 {
00458     delete d;
00459 }
00460 
00461 QString KCalendarSystemHebrew::calendarType() const
00462 {
00463     return QLatin1String( "hebrew" );
00464 }
00465 
00466 QDate KCalendarSystemHebrew::epoch() const
00467 {
00468     return QDate::fromJulianDay( 347998 );
00469 }
00470 
00471 QDate KCalendarSystemHebrew::earliestValidDate() const
00472 {
00473     return KCalendarSystem::earliestValidDate();
00474 }
00475 
00476 QDate KCalendarSystemHebrew::latestValidDate() const
00477 {
00478     // Set to last day of year 9999 until confirm date formats & widets support > 9999
00479     // Last day of Hebrew year 9999 is 9999-12-29
00480     // Which in Gregorian is 6239-09-25
00481     // Which is jd xxxx FIXME Find out jd and use that instead
00482     // Can't call setDate( 9999, 12, 29 ) as it creates circular reference!
00483     return QDate( 6239, 9, 25 );
00484 }
00485 
00486 bool KCalendarSystemHebrew::isValid( int y, int month, int day ) const
00487 {
00488     // taken from setYMD below, adapted to use new methods
00489     if ( y < year( earliestValidDate() ) || y > year( latestValidDate() ) ) {
00490         return false;
00491     }
00492     if ( month < 1 || month > ( isLeapYear( y ) ? 13 : 12 ) ) {
00493         return false;
00494     }
00495     if ( day < 1 || day > d->hndays( month, y ) ) {
00496         return false;
00497     }
00498     return true;
00499 }
00500 
00501 bool KCalendarSystemHebrew::isValid( const QDate &date ) const
00502 {
00503     return KCalendarSystem::isValid( date );
00504 }
00505 
00506 bool KCalendarSystemHebrew::setDate( QDate &date, int year, int month, int day ) const
00507 {
00508     return KCalendarSystem::setDate( date, year, month, day );
00509 }
00510 
00511 // Deprecated
00512 bool KCalendarSystemHebrew::setYMD( QDate & date, int y, int m, int day ) const
00513 {
00514     // range checks
00515     // Removed deleted minValidYear and maxValidYear methods
00516     // Still use minimum of 1753 for now due to QDate using Julian calendar before then
00517     // Later change to following once new methods validated
00518     // if ( y < year( earliestValidDate() ) || y > year( latestValidDate() ) )
00519     if ( y < year( QDate( 1753, 1, 1 ) ) || y > 9999 ) {
00520         return false;
00521     }
00522 
00523     if( m < 1 || m > ( is_leap_year( y ) ? 13 : 12 ) ) {
00524         return false;
00525     }
00526 
00527     if( day < 1 || day > d->hndays( m, y ) ) {
00528         return false;
00529     }
00530 
00531     class h_date * gd = hebrewToGregorian( y, m, day );
00532 
00533     return date.setYMD( gd->hd_year, gd->hd_mon + 1, gd->hd_day + 1 );
00534 }
00535 
00536 int KCalendarSystemHebrew::year( const QDate &date ) const
00537 {
00538     class h_date * sd = toHebrew( date );
00539     return sd->hd_year;
00540 }
00541 
00542 int KCalendarSystemHebrew::month( const QDate &date ) const
00543 {
00544     class h_date * sd = toHebrew( date );
00545 
00546     int month = sd->hd_mon;
00547     if ( is_leap_year( sd->hd_year ) ) {
00548         if( month == 13 /*AdarI*/ ) {
00549             month = 6;
00550         } else if( month == 14 /*AdarII*/ ) {
00551             month = 7;
00552         } else if ( month > 6 && month < 13 ) {
00553             ++month;
00554         }
00555     }
00556 
00557     return month;
00558 }
00559 
00560 int KCalendarSystemHebrew::day( const QDate &date ) const
00561 {
00562     class h_date * sd = toHebrew( date );
00563 
00564     return sd->hd_day;
00565 }
00566 
00567 QDate KCalendarSystemHebrew::addYears( const QDate &date, int nyears ) const
00568 {
00569     QDate result = date;
00570     int y = year( date ) + nyears;
00571 
00572     setYMD( result, y, month( date ), day( date ) );
00573 
00574     return result;
00575 }
00576 
00577 QDate KCalendarSystemHebrew::addMonths( const QDate &date, int nmonths ) const
00578 {
00579     QDate result = date;
00580 
00581     while ( nmonths > 0 ) {
00582         result = addDays( result, daysInMonth( result ) );
00583         --nmonths;
00584     }
00585 
00586     while ( nmonths < 0 ) {
00587         // get the number of days in the previous month to be consistent with
00588         // addMonths where nmonths > 0
00589         int nDaysInMonth = daysInMonth( addDays( result, -day( result ) ) );
00590         result = addDays( result, -nDaysInMonth );
00591         ++nmonths;
00592     }
00593 
00594     return result;
00595 }
00596 
00597 QDate KCalendarSystemHebrew::addDays( const QDate &date, int ndays ) const
00598 {
00599     return date.addDays( ndays );
00600 }
00601 
00602 int KCalendarSystemHebrew::monthsInYear( const QDate &date ) const
00603 {
00604     if ( is_leap_year( year( date ) ) ) {
00605         return 13;
00606     } else {
00607         return 12;
00608     }
00609 }
00610 
00611 int KCalendarSystemHebrew::weeksInYear( const QDate &date ) const
00612 {
00613     return KCalendarSystem::weeksInYear( date );
00614 }
00615 
00616 // Ok
00617 int KCalendarSystemHebrew::weeksInYear( int year ) const
00618 {
00619     QDate temp;
00620     setYMD( temp, year, 1, 1 );  // don't pass an uninitialized QDate to
00621     // monthsInYear in the next call
00622     setYMD( temp, year, monthsInYear( temp ), d->hndays( monthsInYear( temp ), year ) );
00623 
00624     int nWeekNumber = weekNumber( temp );
00625     // last week belongs to next year
00626     if( nWeekNumber == 1 ) {
00627         temp = temp.addDays( -7 );
00628         nWeekNumber = weekNumber( temp );
00629     }
00630 
00631     return nWeekNumber;
00632 }
00633 
00634 int KCalendarSystemHebrew::daysInYear( const QDate &date ) const
00635 {
00636     QDate first, last;
00637 
00638     setYMD( first, year( date ), 1, 1 ); // 1 Tishrey
00639     setYMD( last, year( date ) + 1, 1, 1 ); // 1 Tishrey the year later
00640 
00641     return first.daysTo( last );
00642 }
00643 
00644 int KCalendarSystemHebrew::daysInMonth( const QDate &date ) const
00645 {
00646     return d->hndays( month( date ), year( date ) );
00647 }
00648 
00649 int KCalendarSystemHebrew::daysInWeek( const QDate &date ) const
00650 {
00651     return KCalendarSystem::daysInWeek( date );
00652 }
00653 
00654 int KCalendarSystemHebrew::dayOfYear( const QDate &date ) const
00655 {
00656     QDate first;
00657 
00658     setYMD( first, year( date ), 1, 1 );
00659 
00660     return first.daysTo( date ) + 1;
00661 }
00662 
00663 int KCalendarSystemHebrew::dayOfWeek( const QDate &date ) const
00664 {
00665     class h_date * sd = toHebrew( date );
00666     if ( sd->hd_dw == 0 ) {
00667         return 7;
00668     } else {
00669         return ( sd->hd_dw );
00670     }
00671 }
00672 
00673 int KCalendarSystemHebrew::weekNumber( const QDate &date, int *yearNum ) const
00674 {
00675     QDate firstDayWeek1, lastDayOfYear;
00676     int y = year( date );
00677     int week;
00678     int weekDay1, dayOfWeek1InYear;
00679 
00680     // let's guess 1st day of 1st week
00681     setYMD( firstDayWeek1, y, 1, 1 );
00682     weekDay1 = dayOfWeek( firstDayWeek1 );
00683 
00684     // iso 8601: week 1  is the first containing thursday and week starts on
00685     // monday
00686     if ( weekDay1 > 4 /*Thursday*/ ) {
00687         firstDayWeek1 = addDays( firstDayWeek1 , 7 - weekDay1 + 1 ); // next monday
00688     }
00689 
00690     dayOfWeek1InYear = dayOfYear( firstDayWeek1 );
00691 
00692     // if our date in prev year's week
00693     if ( dayOfYear( date ) < dayOfWeek1InYear ) {
00694         if ( yearNum )
00695             * yearNum = y - 1;
00696         return weeksInYear( y - 1 );
00697     }
00698 
00699     // let's check if its last week belongs to next year
00700     setYMD( lastDayOfYear, y + 1, 1, 1 );
00701     lastDayOfYear = addDays( lastDayOfYear, -1 );
00702     // if our date is in last week && 1st week in next year has thursday
00703     if ( ( dayOfYear( date ) >= daysInYear( date ) - dayOfWeek( lastDayOfYear ) + 1 )
00704             && dayOfWeek( lastDayOfYear ) < 4 ) {
00705         if ( yearNum ) {
00706             * yearNum = y + 1;
00707         }
00708         week = 1;
00709     } else {
00710         // To calculate properly the number of weeks from day a to x let's make a day 1 of week
00711         if( weekDay1 < 5 ) {
00712             firstDayWeek1 = addDays( firstDayWeek1, -( weekDay1 - 1 ) );
00713         }
00714 
00715         week = firstDayWeek1.daysTo( date ) / 7 + 1;
00716     }
00717 
00718     return week;
00719 }
00720 
00721 bool KCalendarSystemHebrew::isLeapYear( int year ) const
00722 {
00723     // from is_leap_year above
00724     return ( ( ( ( 7 * year ) + 1 ) % 19 ) < 7 );
00725 }
00726 
00727 bool KCalendarSystemHebrew::isLeapYear( const QDate &date ) const
00728 {
00729     return QDate::isLeapYear( year( date ) );
00730 }
00731 
00732 // ### Fixme
00733 // JPL Fix what?
00734 // Ask translators for short fomats of month names!
00735 QString KCalendarSystemHebrew::monthName( int month, int year, MonthNameFormat format ) const
00736 {
00737     if ( month < 1 ) {
00738         return QString();
00739     }
00740 
00741     if ( is_leap_year( year ) && month > 13 ) {
00742         return QString();
00743     } else if ( month > 12 ) {
00744         return QString();
00745     }
00746 
00747     // We must map conversion algorithm month index to real index
00748     if( month == 6 && is_leap_year( year ) ) {
00749         month = 13; /*Adar I*/
00750     } else if ( month == 7 && is_leap_year( year ) ) {
00751         month = 14; /*Adar II*/
00752     } else if ( month > 7 && is_leap_year( year ) ) {
00753         month--; //Because of Adar II
00754     }
00755 
00756     if ( format == ShortNamePossessive || format == LongNamePossessive ) {
00757         switch( month ) {
00758         case 1:
00759             return ki18n( "of Tishrey" ).toString( locale() );
00760         case 2:
00761             return ki18n( "of Heshvan" ).toString( locale() );
00762         case 3:
00763             return ki18n( "of Kislev" ).toString( locale() );
00764         case 4:
00765             return ki18n( "of Tevet" ).toString( locale() );
00766         case 5:
00767             return ki18n( "of Shvat" ).toString( locale() );
00768         case 6:
00769             return ki18n( "of Adar" ).toString( locale() );
00770         case 7:
00771             return ki18n( "of Nisan" ).toString( locale() );
00772         case 8:
00773             return ki18n( "of Iyar" ).toString( locale() );
00774         case 9:
00775             return ki18n( "of Sivan" ).toString( locale() );
00776         case 10:
00777             return ki18n( "of Tamuz" ).toString( locale() );
00778         case 11:
00779             return ki18n( "of Av" ).toString( locale() );
00780         case 12:
00781             return ki18n( "of Elul" ).toString( locale() );
00782         case 13:
00783             return ki18n( "of Adar I" ).toString( locale() );
00784         case 14:
00785             return ki18n( "of Adar II" ).toString( locale() );
00786         default:
00787             return QString();
00788         }
00789     }
00790 
00791     switch( month ) {
00792     case 1:
00793         return ki18n( "Tishrey" ).toString( locale() );
00794     case 2:
00795         return ki18n( "Heshvan" ).toString( locale() );
00796     case 3:
00797         return ki18n( "Kislev" ).toString( locale() );
00798     case 4:
00799         return ki18n( "Tevet" ).toString( locale() );
00800     case 5:
00801         return ki18n( "Shvat" ).toString( locale() );
00802     case 6:
00803         return ki18n( "Adar" ).toString( locale() );
00804     case 7:
00805         return ki18n( "Nisan" ).toString( locale() );
00806     case 8:
00807         return ki18n( "Iyar" ).toString( locale() );
00808     case 9:
00809         return ki18n( "Sivan" ).toString( locale() );
00810     case 10:
00811         return ki18n( "Tamuz" ).toString( locale() );
00812     case 11:
00813         return ki18n( "Av" ).toString( locale() );
00814     case 12:
00815         return ki18n( "Elul" ).toString( locale() );
00816     case 13:
00817         return ki18n( "Adar I" ).toString( locale() );
00818     case 14:
00819         return ki18n( "Adar II" ).toString( locale() );
00820     default:
00821         return QString();
00822     }
00823 }
00824 
00825 QString KCalendarSystemHebrew::monthName( const QDate& date, MonthNameFormat format ) const
00826 {
00827     return monthName( month( date ), year( date ), format );
00828 }
00829 
00830 QString KCalendarSystemHebrew::weekDayName( int weekDay, WeekDayNameFormat format ) const
00831 {
00832     // Use Western day names for now as that's what the old version did,
00833     // but wouldn't it be better to use the right Hebrew names like Shabbat?
00834     // Could make it switchable by adding new enums to WeekDayFormat, e.g. ShortNameWestern?
00835     if ( format == ShortDayName ) {
00836         switch ( weekDay ) {
00837         case 1:  return ki18nc( "Monday", "Mon" ).toString( locale() );
00838         case 2:  return ki18nc( "Tuesday", "Tue" ).toString( locale() );
00839         case 3:  return ki18nc( "Wednesday", "Wed" ).toString( locale() );
00840         case 4:  return ki18nc( "Thursday", "Thu" ).toString( locale() );
00841         case 5:  return ki18nc( "Friday", "Fri" ).toString( locale() );
00842         case 6:  return ki18nc( "Saturday", "Sat" ).toString( locale() );
00843         case 7:  return ki18nc( "Sunday", "Sun" ).toString( locale() );
00844         default: return QString();
00845         }
00846     }
00847 
00848     switch ( weekDay ) {
00849     case 1:  return ki18n( "Monday" ).toString( locale() );
00850     case 2:  return ki18n( "Tuesday" ).toString( locale() );
00851     case 3:  return ki18n( "Wednesday" ).toString( locale() );
00852     case 4:  return ki18n( "Thursday" ).toString( locale() );
00853     case 5:  return ki18n( "Friday" ).toString( locale() );
00854     case 6:  return ki18n( "Saturday" ).toString( locale() );
00855     case 7:  return ki18n( "Sunday" ).toString( locale() );
00856     default: return QString();
00857     }
00858 }
00859 
00860 QString KCalendarSystemHebrew::weekDayName( const QDate &date, WeekDayNameFormat format ) const
00861 {
00862     return weekDayName( dayOfWeek( date ), format );
00863 }
00864 
00865 QString KCalendarSystemHebrew::yearString( const QDate &pDate, StringFormat format ) const
00866 {
00867     QString sResult;
00868 
00869     // Only use hebrew numbers if the hebrew setting is selected
00870     if ( locale()->language() == QLatin1String( "he" ) ) {
00871         if ( format == ShortFormat ) {
00872             sResult = num2heb( year( pDate ), false );
00873         }
00874     } else {
00875         sResult = KCalendarSystem::yearString( pDate, format );
00876     }
00877 
00878     return sResult;
00879 }
00880 
00881 QString KCalendarSystemHebrew::monthString( const QDate &pDate, StringFormat format ) const
00882 {
00883     return KCalendarSystem::monthString( pDate, format );
00884 }
00885 
00886 QString KCalendarSystemHebrew::dayString( const QDate &pDate, StringFormat format ) const
00887 {
00888     QString sResult;
00889 
00890     // Only use hebrew numbers if the hebrew setting is selected
00891     if ( locale()->language() == QLatin1String( "he" ) ) {
00892         sResult = num2heb( day( pDate ), false );
00893     } else {
00894         sResult = KCalendarSystem::dayString( pDate, format );
00895     }
00896 
00897     return sResult;
00898 }
00899 
00900 int KCalendarSystemHebrew::yearStringToInteger( const QString &sNum, int &iLength ) const
00901 {
00902     int iResult;
00903 
00904     if ( locale()->language() == "he" ) {
00905         iResult = heb2num( sNum, iLength );
00906     } else {
00907         iResult = KCalendarSystem::yearStringToInteger( sNum, iLength );
00908     }
00909 
00910     if ( iResult < 1000 ) {
00911         iResult += 5000; // assume we're in the 6th millenium (y6k bug)
00912     }
00913 
00914     return iResult;
00915 }
00916 
00917 int KCalendarSystemHebrew::monthStringToInteger( const QString &sNum, int &iLength ) const
00918 {
00919     return KCalendarSystem::monthStringToInteger( sNum, iLength );
00920 }
00921 
00922 int KCalendarSystemHebrew::dayStringToInteger( const QString &sNum, int &iLength ) const
00923 {
00924     int iResult;
00925 
00926     if ( locale()->language() == "he" ) {
00927         iResult = heb2num( sNum, iLength );
00928     } else {
00929         iResult = KCalendarSystem::yearStringToInteger( sNum, iLength );
00930     }
00931 
00932     return iResult;
00933 }
00934 
00935 QString KCalendarSystemHebrew::formatDate( const QDate &date, KLocale::DateFormat format ) const
00936 {
00937     return KCalendarSystem::formatDate( date, format );
00938 }
00939 
00940 QDate KCalendarSystemHebrew::readDate( const QString &str, bool *ok ) const
00941 {
00942     return KCalendarSystem::readDate( str, ok );
00943 }
00944 
00945 QDate KCalendarSystemHebrew::readDate( const QString &intstr, const QString &fmt, bool *ok ) const
00946 {
00947     return KCalendarSystem::readDate( intstr, fmt, ok );
00948 }
00949 
00950 QDate KCalendarSystemHebrew::readDate( const QString &str, KLocale::ReadDateFlags flags, bool *ok ) const
00951 {
00952     return KCalendarSystem::readDate( str, flags, ok );
00953 }
00954 
00955 int KCalendarSystemHebrew::weekDayOfPray() const
00956 {
00957     return 6; // saturday
00958 }
00959 
00960 int KCalendarSystemHebrew::weekStartDay() const
00961 {
00962     return KCalendarSystem::weekStartDay();
00963 }
00964 
00965 bool KCalendarSystemHebrew::isLunar() const
00966 {
00967     return false;
00968 }
00969 
00970 bool KCalendarSystemHebrew::isLunisolar() const
00971 {
00972     return true;
00973 }
00974 
00975 bool KCalendarSystemHebrew::isSolar() const
00976 {
00977     return false;
00978 }
00979 
00980 bool KCalendarSystemHebrew::isProleptic() const
00981 {
00982     return false;
00983 }
00984 
00985 bool KCalendarSystemHebrew::julianDayToDate( int jd, int &year, int &month, int &day ) const
00986 {
00987     if ( jd >= earliestValidDate().toJulianDay() && jd <= latestValidDate().toJulianDay() ) {
00988         // Hatcher formula I.  Fix me!
00989         year = d->yearOfJulianDay( jd );
00990         int jdTishri1ThisYear = d->julianDayOfTishri1( year );
00991         int dayInYear = jd - jdTishri1ThisYear + 1;
00992         int K = d->characterOfYear( year );
00993         int n = dayInYear / 30;
00994         if ( dayInYear > d->daysPreceedingMonth( K, n + 1 ) ) {
00995             month = n + 1;
00996         } else {
00997             if ( dayInYear > d->daysPreceedingMonth( K, n + 1 ) ) {
00998                 month = n;
00999             } else {
01000                 month = n - 1;
01001             }
01002         }
01003         day = dayInYear - d->daysPreceedingMonth( K, month );
01004         return true;
01005     }
01006     return false;
01007 }
01008 
01009 bool KCalendarSystemHebrew::dateToJulianDay( int year, int month, int day, int &jd ) const
01010 {
01011     // From Hatcher formula J.  Fix me!
01012     if ( isValid( year, month, day ) ) {
01013         int jdTishri1ThisYear = d->julianDayOfTishri1( year );
01014         jd = jdTishri1ThisYear
01015              + d->daysPreceedingMonth( d->characterOfYear( year ), month )
01016              + day - 1;
01017         return true;
01018     }
01019     return false;
01020 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal