• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • 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 2007, 2009, 2010 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_p.h"
00026 #include "kcalendarsystemprivate_p.h"
00027 
00028 #include "kdebug.h"
00029 #include "klocale.h"
00030 
00031 #include <QtCore/QDate>
00032 #include <QtCore/QCharRef>
00033 
00034 static int hebrewDaysElapsed( int y );
00035 
00036 class h_date
00037 {
00038 public:
00039     int hd_day;
00040     int hd_mon;
00041     int hd_year;
00042     int hd_dw;
00043     int hd_flg;
00044 };
00045 
00046 /*
00047  * compute general date structure from hebrew date
00048  */
00049 static class h_date * hebrewToGregorian( int y, int m, int d )
00050 {
00051     static class h_date h;
00052     int s;
00053 
00054     y -= 3744;
00055     s = hebrewDaysElapsed( y );
00056     d += s;
00057     s = hebrewDaysElapsed( y + 1 ) - s;    /* length of year */
00058 
00059     if ( s > 365 && m > 6 ) {
00060         --m;
00061         d += 30;
00062     }
00063     d += ( 59 * ( m - 1 ) + 1 ) / 2;  /* regular months */
00064     /* special cases */
00065     if ( s % 10 > 4 && m > 2 ) {  /* long Heshvan */
00066         d++;
00067     }
00068     if ( s % 10 < 4 && m > 3 ) {  /* short Kislev */
00069         d--;
00070     }
00071     // ### HPB: Broken in leap years
00072     //if (s > 365 && m > 6)  /* leap year */
00073     //  d += 30;
00074     d -= 6002;
00075 
00076     y = ( d + 36525 ) * 4 / 146097 - 1;
00077     d -= y / 4 * 146097 + ( y % 4 ) * 36524;
00078     y *= 100;
00079 
00080     /* compute year */
00081     s = ( d + 366 )*4 / 1461 - 1;
00082     d -= s / 4*1461 + ( s % 4 )*365;
00083     y += s;
00084     /* compute month */
00085     m = ( d + 245 )*12 / 367 - 7;
00086     d -= m*367 / 12 - 30;
00087     if ( ++m >= 12 ) {
00088         m -= 12;
00089         y++;
00090     }
00091     h.hd_day = d;
00092     h.hd_mon = m;
00093     h.hd_year = y;
00094     return( &h );
00095 }
00096 
00097 /*
00098  * compute date structure from no. of days since 1 Tishrei 3744
00099  */
00100 static class h_date * gregorianToHebrew( int y, int m, int d )
00101 {
00102     static class h_date h;
00103     int s;
00104 
00105     if ( ( m -= 2 ) <= 0 ) {
00106         m += 12;
00107         y--;
00108     }
00109     /* no. of days, Julian calendar */
00110     d += 365*y + y / 4 + 367*m / 12 + 5968;
00111     /* Gregorian calendar */
00112     d -= y / 100 - y / 400 - 2;
00113     h.hd_dw = ( d + 1 ) % 7;
00114 
00115     /* compute the year */
00116     y += 16;
00117     s = hebrewDaysElapsed( y );
00118     m = hebrewDaysElapsed( y + 1 );
00119     while( d >= m ) {  /* computed year was underestimated */
00120         s = m;
00121         y++;
00122         m = hebrewDaysElapsed( y + 1 );
00123     }
00124     d -= s;
00125     s = m - s;  /* size of current year */
00126     y += 3744;
00127 
00128     h.hd_flg = s % 10 - 4;
00129 
00130     /* compute day and month */
00131     if ( d >= s - 236 ) {  /* last 8 months are regular */
00132         d -= s - 236;
00133         m = d * 2 / 59;
00134         d -= ( m * 59 + 1 ) / 2;
00135         m += 4;
00136         if ( s > 365 && m <= 5 ) {  /* Adar of Meuberet */
00137             m += 8;
00138         }
00139     } else {
00140         /* first 4 months have 117-119 days */
00141         s = 114 + s % 10;
00142         m = d * 4 / s;
00143         d -= ( m * s + 3 ) / 4;
00144     }
00145 
00146     h.hd_day = d;
00147     h.hd_mon = m;
00148     h.hd_year = y;
00149     return( &h );
00150 }
00151 
00152 /* constants, in 1/18th of minute */
00153 static const int HOUR = 1080;
00154 static const int DAY = 24*HOUR;
00155 static const int WEEK = 7*DAY;
00156 #define M(h,p) ((h)*HOUR+p)
00157 #define MONTH (DAY+M(12,793))
00158 
00163 static int hebrewDaysElapsed( int y )
00164 {
00165     int m, nm, dw, s, l;
00166 
00167     l = y * 7 + 1;  // no. of leap months
00168     m = y * 12 + l / 19;  // total no. of months
00169     l %= 19;
00170     nm = m * MONTH + M( 1 + 6, 779 ); // molad new year 3744 (16BC) + 6 hours
00171     s = m * 28 + nm / DAY - 2;
00172 
00173     nm %= WEEK;
00174     dw = nm / DAY;
00175     nm %= DAY;
00176 
00177     // special cases of Molad Zaken
00178     if ( (l < 12 && dw == 3 && nm >= M( 9 + 6, 204 )) ||
00179             (l < 7 && dw == 2 && nm >= M( 15 + 6, 589 )) ) {
00180         s++, dw++;
00181     }
00182 
00183     /* ADU */
00184     if ( dw == 1 || dw == 4 || dw == 6 ) {
00185         s++;
00186     }
00187     return s;
00188 }
00189 
00194 static int long_cheshvan( int year )
00195 {
00196     QDate first, last;
00197     class h_date *gd;
00198 
00199     gd = hebrewToGregorian( year, 1, 1 );
00200     first.setYMD( gd->hd_year, gd->hd_mon + 1, gd->hd_day + 1 );
00201 
00202     gd = hebrewToGregorian( year + 1, 1, 1 );
00203     last.setYMD( gd->hd_year, gd->hd_mon + 1, gd->hd_day + 1 );
00204 
00205     return ( first.daysTo( last ) % 10 == 5 );
00206 }
00207 
00212 static int short_kislev( int year )
00213 {
00214     QDate first, last;
00215     class h_date * gd;
00216 
00217     gd = hebrewToGregorian( year, 1, 1 );
00218     first.setYMD( gd->hd_year, gd->hd_mon + 1, gd->hd_day + 1 );
00219 
00220     gd = hebrewToGregorian( year + 1, 1, 1 );
00221     last.setYMD( gd->hd_year, gd->hd_mon + 1, gd->hd_day + 1 );
00222 
00223     return ( first.daysTo( last ) % 10 == 3 );
00224 }
00225 
00226 // Ok
00227 static class h_date *toHebrew( const QDate &date )
00228 {
00229     class h_date *sd;
00230 
00231     sd = gregorianToHebrew( date.year(), date.month(), date.day() );
00232     ++sd->hd_mon;
00233     ++sd->hd_day;
00234 
00235     return sd;
00236 }
00237 
00238 class KCalendarSystemHebrewPrivate : public KCalendarSystemPrivate
00239 {
00240 public:
00241     explicit KCalendarSystemHebrewPrivate( KCalendarSystemHebrew *q );
00242 
00243     virtual ~KCalendarSystemHebrewPrivate();
00244 
00245     // Virtual methods each calendar system must re-implement
00246     virtual KLocale::CalendarSystem calendarSystem() const;
00247     virtual void loadDefaultEraList();
00248     virtual int monthsInYear( int year ) const;
00249     virtual int daysInMonth( int year, int month ) const;
00250     virtual int daysInYear( int year ) const;
00251     virtual int daysInWeek() const;
00252     virtual bool isLeapYear( int year ) const;
00253     virtual bool hasLeapMonths() const;
00254     virtual bool hasYearZero() const;
00255     virtual int maxDaysInWeek() const;
00256     virtual int maxMonthsInYear() const;
00257     virtual int earliestValidYear() const;
00258     virtual int latestValidYear() const;
00259 
00260     virtual int integerFromString( const QString &string, int maxLength, int &readLength ) const;
00261     virtual QString stringFromInteger( int number, int padWidth = 0, QChar padChar = QLatin1Char('0') ) const;
00262     virtual QString stringFromInteger( int number, int padWidth, QChar padChar, KLocale::DigitSet digitSet ) const;
00263 
00264     virtual int monthNumberToMonthIndex( int year, int month ) const;
00265 };
00266 
00267 // Shared d pointer base class definitions
00268 
00269 KCalendarSystemHebrewPrivate::KCalendarSystemHebrewPrivate( KCalendarSystemHebrew *q )
00270                              :KCalendarSystemPrivate( q )
00271 {
00272 }
00273 
00274 KCalendarSystemHebrewPrivate::~KCalendarSystemHebrewPrivate()
00275 {
00276 }
00277 
00278 KLocale::CalendarSystem KCalendarSystemHebrewPrivate::calendarSystem() const
00279 {
00280     return KLocale::HebrewCalendar;
00281 }
00282 
00283 void KCalendarSystemHebrewPrivate::loadDefaultEraList()
00284 {
00285     QString name, shortName, format;
00286     // Jewish Era, Anno Mundi, "Year of the World".
00287     name = i18nc( "Calendar Era: Hebrew Era, years > 0, LongFormat", "Anno Mundi" );
00288     shortName = i18nc( "Calendar Era: Hebrew Era, years > 0, ShortFormat", "AM" );
00289     format = i18nc( "(kdedt-format) Hebrew, AM, full era year format used for %EY, e.g. 2000 AM", "%Ey %EC" );
00290     addEra( '+', 1, q->epoch(), 1, q->latestValidDate(), name, shortName, format );
00291 }
00292 
00293 int KCalendarSystemHebrewPrivate::monthsInYear( int year ) const
00294 {
00295     if ( isLeapYear( year ) ) {
00296         return 13;
00297     } else {
00298         return 12;
00299     }
00300 }
00301 
00302 int KCalendarSystemHebrewPrivate::daysInMonth( int year, int month ) const
00303 {
00304     int mi = monthNumberToMonthIndex( year, month );
00305 
00306     if ( mi == 2 && long_cheshvan( year ) ) {
00307         return 30;
00308     }
00309 
00310     if ( mi == 3 && short_kislev( year ) ) {
00311         return 29;
00312     }
00313 
00314     if ( mi % 2 == 0 ) {  // Even number months have 29 days
00315         return 29;
00316     } else {  // Odd number months have 30 days
00317         return 30;
00318     }
00319 }
00320 
00321 int KCalendarSystemHebrewPrivate::daysInYear( int year ) const
00322 {
00323     int days;
00324 
00325     // Get Regular year length
00326     if ( isLeapYear( year ) ) {  // Has 13 months
00327         days = 384;
00328     } else {  // Has 12 months
00329         days = 354;
00330     }
00331 
00332     // Check if is Deficient or Abundant year
00333     if ( short_kislev( year ) ) { // Deficient
00334         days = days - 1;
00335     } else if ( long_cheshvan( year ) ) { // Abundant
00336         days = days + 1;
00337     }
00338 
00339     return days;
00340 }
00341 
00342 int KCalendarSystemHebrewPrivate::daysInWeek() const
00343 {
00344     return 7;
00345 }
00346 
00347 bool KCalendarSystemHebrewPrivate::isLeapYear( int year ) const
00348 {
00349     return ( ( ( ( 7 * year ) + 1 ) % 19 ) < 7 );
00350 }
00351 
00352 bool KCalendarSystemHebrewPrivate::hasLeapMonths() const
00353 {
00354     return true;
00355 }
00356 
00357 bool KCalendarSystemHebrewPrivate::hasYearZero() const
00358 {
00359     return false;
00360 }
00361 
00362 int KCalendarSystemHebrewPrivate::maxDaysInWeek() const
00363 {
00364     return 7;
00365 }
00366 
00367 int KCalendarSystemHebrewPrivate::maxMonthsInYear() const
00368 {
00369     return 13;
00370 }
00371 
00372 int KCalendarSystemHebrewPrivate::earliestValidYear() const
00373 {
00374     return 5344;
00375 }
00376 
00377 int KCalendarSystemHebrewPrivate::latestValidYear() const
00378 {
00379     return 8119;
00380 }
00381 
00382 int KCalendarSystemHebrewPrivate::integerFromString( const QString &inputString, int maxLength, int &readLength ) const
00383 {
00384     if ( locale()->language() == QLatin1String("he") ) {
00385 
00386         // Hebrew numbers are composed of combinations of normal letters which have a numeric value.
00387         // This is a non-positional system, the numeric values are simply added together, however
00388         // convention is for a RTL highest to lowest value ordering. There is also a degree of
00389         // ambiguity due to the lack of a letter for 0, hence 5 and 5000 are written the same.
00390         // Hebrew numbers are only used in dates.
00391         // See http://www.i18nguy.com/unicode/hebrew-numbers.html for more explaination
00392 
00393         /*
00394         Ref table for numbers to Hebrew chars
00395 
00396         Value     1       2       3        4        5       6         7        8      9
00397 
00398         x 1    Alef א  Bet  ב  Gimel ג  Dalet ד  He   ה  Vav  ו    Zayen ז  Het  ח  Tet  ט
00399                0x05D0  0x05D1  0x05D2   0x05D3   0x05D4  0x05D5    0x05D6   0x05D7  0x05D8
00400 
00401         x 10   Yod  י  Kaf  כ  Lamed ל  Mem  מ   Nun  נ  Samekh ס  Ayin ע   Pe   פ  Tzadi צ
00402                0x05D9  0x05DB  0x05DC   0x05DE   0x05E0  0x05E1    0x05E2   0x05E4  0x05E6
00403 
00404         x 100  Qof  ק  Resh ר  Shin ש   Tav  ת
00405                0x05E7  0x05E8  0x05E9   0x05EA
00406 
00407         Note special cases 15 = 9 + 6 = 96 טו and 16 = 9 + 7 = 97 טז
00408         */
00409 
00410         int decadeValues[14] = {10, 20, 20, 30, 40, 40, 50, 50, 60, 70, 80, 80, 90, 90};
00411 
00412         QChar thisChar, nextChar;
00413         QString string = inputString;
00414 
00415         int stringLength = string.length();
00416         readLength = 0;
00417         int position = 0;
00418         int result = 0;
00419         int value = 0;
00420 
00421         for ( ; position < stringLength ; ++position ) {
00422 
00423             thisChar = string[position];
00424 
00425             if ( position + 1 < stringLength ) {
00426                 nextChar = string[position + 1];
00427                 // Ignore any geresh or gershayim chars, we don't bother checking they are in the right place
00428                 if ( nextChar == QLatin1Char('\'') ||  nextChar == QChar( 0x05F3 ) ||   // geresh
00429                      nextChar == QLatin1Char('\"') ||  nextChar == QChar( 0x05F4 ) ) {  // gershayim
00430                     string.remove( position + 1, 1 );
00431                     stringLength = string.length();
00432                     if ( position + 1 < stringLength ) {
00433                         nextChar = string[position + 1];
00434                     } else {
00435                         nextChar = QChar();
00436                     }
00437                     readLength = readLength + 1;
00438                 }
00439             } else {
00440                 nextChar = QChar();
00441             }
00442 
00443             if ( thisChar >= QChar( 0x05D0 ) && thisChar <= QChar( 0x05D7 ) ) {
00444 
00445                 // If this char Alef to Het, 1 to 8, א to ח
00446 
00447                 // If next char is any valid digit char (Alef to Tav, 1 to 400, א to ת)
00448                 // then this char is a thousands digit
00449                 // else this char is a ones digit
00450 
00451                 if ( nextChar >= QChar( 0x05D0 ) && nextChar <= QChar( 0x05EA ) ) {
00452                     value = ( thisChar.unicode() - 0x05D0 + 1 ) * 1000;
00453                 } else {
00454                     value = thisChar.unicode() - 0x05D0 + 1;
00455                 }
00456 
00457             } else if ( thisChar == QChar( 0x05D8 ) ) {
00458 
00459                 // If this char is Tet, 9, ט
00460 
00461                 // If next char is any valid digit char (Alef to Tav, 1 to 400, א to ת)
00462                 // and next char not 6 (Special case for 96 = 15)
00463                 // and next char not 7 (Special case for 97 = 16)
00464                 // then is a thousands digit else is 9
00465 
00466                 if ( nextChar >= QChar( 0x05D0 ) && nextChar <= QChar( 0x05EA ) &&
00467                      nextChar != QChar( 0x05D5 ) && nextChar != QChar( 0x05D6 ) ) {
00468                     value = 9000;
00469                 } else {
00470                     value = 9;
00471                 }
00472 
00473             } else if ( thisChar >= QChar( 0x05D9 ) && thisChar <= QChar( 0x05E6 ) ) {
00474 
00475                 // If this char Yod to Tsadi, 10 to 90, י to צ
00476 
00477                 // If next char is a tens or hundreds char then is an error
00478                 // Else is a tens digit
00479 
00480                 if ( nextChar >= QChar( 0x05D9 ) ) {
00481                     return -1;
00482                 } else {
00483                     value = decadeValues[thisChar.unicode() - 0x05D9];
00484                 }
00485 
00486             } else if ( thisChar >= QChar( 0x05E7 ) && thisChar <= QChar( 0x05EA ) ) {
00487 
00488                 // If this char Qof to Tav, 100 to 400, ק to ת, then is hundreds digit
00489 
00490                 value = ( thisChar.unicode() - 0x05E7 + 1 ) * 100;
00491 
00492             } else {
00493 
00494                 // If this char any non-digit char including whitespace or punctuation, we're done
00495                 break;
00496 
00497             }
00498 
00499             result = result + value;
00500 
00501             value = 0;
00502         }
00503 
00504         readLength += position;
00505 
00506         return result;
00507 
00508     } else {
00509         return KCalendarSystemPrivate::integerFromString( inputString, maxLength, readLength );
00510     }
00511 }
00512 
00513 QString KCalendarSystemHebrewPrivate::stringFromInteger( int number, int padWidth, QChar padChar ) const
00514 {
00515     return KCalendarSystemPrivate::stringFromInteger( number, padWidth, padChar );
00516 }
00517 
00518 QString KCalendarSystemHebrewPrivate::stringFromInteger( int number, int padWidth, QChar padChar, KLocale::DigitSet digitSet ) const
00519 {
00520     if ( locale()->language() == QLatin1String("he") ) {
00521 
00522         // Hebrew numbers are composed of combinations of normal letters which have a numeric value.
00523         // This is a non-positional system, the numeric values are simply added together, however
00524         // convention is for a RTL highest to lowest value ordering. There is also a degree of
00525         // ambiguity due to the lack of a letter for 0, hence 5 and 5000 are written the same.
00526         // Hebrew numbers are only used in dates.
00527         // See http://www.i18nguy.com/unicode/hebrew-numbers.html for more explaination
00528 
00529         /*
00530         Ref table for numbers to Hebrew chars
00531 
00532         Value     1       2       3        4        5       6         7        8      9
00533 
00534         x 1    Alef א  Bet  ב  Gimel ג  Dalet ד  He   ה  Vav  ו    Zayen ז  Het  ח  Tet  ט
00535                0x05D0  0x05D1  0x05D2   0x05D3   0x05D4  0x05D5    0x05D6   0x05D7  0x05D8
00536 
00537         x 10   Yod  י  Kaf  כ  Lamed ל  Mem  מ   Nun  נ  Samekh ס  Ayin ע   Pe   פ  Tzadi צ
00538                0x05D9  0x05DB  0x05DC   0x05DE   0x05E0  0x05E1    0x05E2   0x05E4  0x05E6
00539 
00540         x 100  Qof  ק  Resh ר  Shin ש   Tav  ת
00541                0x05E7  0x05E8  0x05E9   0x05EA
00542 
00543         Note special cases 15 = 9 + 6 = 96 טו and 16 = 9 + 7 = 97 טז
00544         */
00545 
00546         const QChar decade[] = {
00547         //  Tet = ט,    Yod = י,    Kaf = כ,    Lamed = ל,  Mem = מ
00548         //  Nun = נ,    Samekh = ס, Ayin = ע,   Pe = פ,     Tsadi = צ
00549             0x05D8,     0x05D9,     0x05DB,     0x05DC,     0x05DE,
00550             0x05E0,     0x05E1,     0x05E2,     0x05E4,     0x05E6
00551         };
00552 
00553         QString result;
00554 
00555         // We have no rules for coping with numbers outside this range
00556         if ( number < 1 || number > 9999 ) {
00557             return KCalendarSystemPrivate::stringFromInteger( number, padWidth, padChar, digitSet );
00558         }
00559 
00560         // Translate the thousands digit, just uses letter for number 1..9 ( א to ט, Alef to Tet )
00561         // Years 5001-5999 do not have the thousands by convention
00562         if ( number >= 1000 ) {
00563             if ( number <= 5000 || number >= 6000 ) {
00564                 result += QChar( 0x05D0 - 1 + number / 1000 );  // Alef א to Tet ט
00565             }
00566             number %= 1000;
00567         }
00568 
00569         // Translate the hundreds digit
00570         // Use traditional method where we only have letters assigned values for 100, 200, 300 and 400
00571         // so may need to repeat 400 twice to make up the required number
00572         if ( number >= 100 ) {
00573             while ( number >= 500 ) {
00574                 result += QChar( 0x05EA );  // Tav = ת
00575                 number -= 400;
00576             }
00577             result += QChar( 0x05E7 - 1 + number / 100 ); // Qof = ק to xxx
00578             number %= 100;
00579         }
00580 
00581         // Translate the tens digit
00582         // The numbers 15 and 16 translate to letters that spell out the name of God which is
00583         // forbidden, so require special treatment where 15 = 9 + 6 and 1 = 9 + 7.
00584         if ( number >= 10 ) {
00585             if ( number == 15 || number == 16 )
00586                 number -= 9;
00587             result += decade[number / 10];
00588             number %= 10;
00589         }
00590 
00591         // Translate the ones digit, uses letter for number 1..9 ( א to ט, Alef to Tet )
00592         if ( number > 0 ) {
00593             result += QChar( 0x05D0 - 1 + number );  // Alef = א to xxx
00594         }
00595 
00596         // When used in a string with mixed names and numbers the numbers need special chars to
00597         // distinguish them from words composed of the same letters.
00598         // Single digit numbers are followed by a geresh symbol ? (Unicode = 0x05F3), but we use
00599         // single quote for convenience.
00600         // Multiple digit numbers have a gershayim symbol ? (Unicode = 0x05F4) as second-to-last
00601         // char, but we use double quote for convenience.
00602         if ( result.length() == 1 ) {
00603             result += QLatin1Char('\'');
00604         } else {
00605             result.insert( result.length() - 1, QLatin1Char('\"') );
00606         }
00607 
00608         return result;
00609 
00610     } else {
00611         return KCalendarSystemPrivate::stringFromInteger( number, padWidth, padChar, digitSet );
00612     }
00613 }
00614 
00615 int KCalendarSystemHebrewPrivate::monthNumberToMonthIndex( int year, int month ) const
00616 {
00617     if ( isLeapYear( year ) ) {
00618         if ( month == 6 ) {
00619             return 13;        // Adar I
00620         } else if ( month == 7 ) {
00621             return 14;        // Adar II
00622         } else if ( month > 7 ) {
00623             return month - 1; // Because of Adar II
00624         }
00625     }
00626 
00627     return month;
00628 }
00629 
00630 
00631 KCalendarSystemHebrew::KCalendarSystemHebrew( const KLocale *locale )
00632                      : KCalendarSystem( *new KCalendarSystemHebrewPrivate( this ), KSharedConfig::Ptr(), locale ),
00633                        dont_use( 0 )
00634 {
00635     d_ptr->loadConfig( calendarType() );
00636 }
00637 
00638 KCalendarSystemHebrew::KCalendarSystemHebrew( const KSharedConfig::Ptr config, const KLocale *locale )
00639                      : KCalendarSystem( *new KCalendarSystemHebrewPrivate( this ), config, locale ),
00640                        dont_use( 0 )
00641 {
00642     d_ptr->loadConfig( calendarType() );
00643 }
00644 
00645 KCalendarSystemHebrew::KCalendarSystemHebrew( KCalendarSystemHebrewPrivate &dd,
00646                                               const KSharedConfig::Ptr config, const KLocale *locale )
00647                      : KCalendarSystem( dd, config, locale ),
00648                        dont_use( 0 )
00649 {
00650     d_ptr->loadConfig( calendarType() );
00651 }
00652 
00653 KCalendarSystemHebrew::~KCalendarSystemHebrew()
00654 {
00655     delete dont_use;
00656 }
00657 
00658 QString KCalendarSystemHebrew::calendarType() const
00659 {
00660     return QLatin1String( "hebrew" );
00661 }
00662 
00663 QDate KCalendarSystemHebrew::epoch() const
00664 {
00665     // Hebrew 0001-01-01 (Gregorian -3760-09-07, Julian -3761-10-07)
00666     return QDate::fromJulianDay( 347998 );
00667 }
00668 
00669 QDate KCalendarSystemHebrew::earliestValidDate() const
00670 {
00671     // Current formulas using direct Gregorian <-> Hebrew conversion using Qt
00672     // will return invalid results prior to the Gregorian switchover in 1582
00673     // Next valid Hebrew year starts 5344-01-01 (Gregorian 1583-09-17)
00674     return QDate::fromJulianDay( 2299498 );
00675 }
00676 
00677 QDate KCalendarSystemHebrew::latestValidDate() const
00678 {
00679     // Testing shows current formulas only work up to 8119-13-29 (Gregorian 4359-10-07)
00680     return QDate::fromJulianDay( 3313431 );
00681 }
00682 
00683 bool KCalendarSystemHebrew::isValid( int year, int month, int day ) const
00684 {
00685     return KCalendarSystem::isValid( year, month, day );
00686 }
00687 
00688 bool KCalendarSystemHebrew::isValid( const QDate &date ) const
00689 {
00690     return KCalendarSystem::isValid( date );
00691 }
00692 
00693 bool KCalendarSystemHebrew::setDate( QDate &date, int year, int month, int day ) const
00694 {
00695     return KCalendarSystem::setDate( date, year, month, day );
00696 }
00697 
00698 // Deprecated
00699 bool KCalendarSystemHebrew::setYMD( QDate &date, int year, int month, int day ) const
00700 {
00701     return KCalendarSystem::setYMD( date, year, month, day );
00702 }
00703 
00704 int KCalendarSystemHebrew::year( const QDate &date ) const
00705 {
00706     return KCalendarSystem::year( date );
00707 }
00708 
00709 int KCalendarSystemHebrew::month( const QDate &date ) const
00710 {
00711     return KCalendarSystem::month( date );
00712 }
00713 
00714 int KCalendarSystemHebrew::day( const QDate &date ) const
00715 {
00716     return KCalendarSystem::day( date );
00717 }
00718 
00719 QDate KCalendarSystemHebrew::addYears( const QDate &date, int nyears ) const
00720 {
00721     return KCalendarSystem::addYears( date, nyears );
00722 }
00723 
00724 QDate KCalendarSystemHebrew::addMonths( const QDate &date, int nmonths ) const
00725 {
00726     return KCalendarSystem::addMonths( date, nmonths );
00727 }
00728 
00729 QDate KCalendarSystemHebrew::addDays( const QDate &date, int ndays ) const
00730 {
00731     return KCalendarSystem::addDays( date, ndays );
00732 }
00733 
00734 int KCalendarSystemHebrew::monthsInYear( const QDate &date ) const
00735 {
00736     return KCalendarSystem::monthsInYear( date );
00737 }
00738 
00739 int KCalendarSystemHebrew::weeksInYear( const QDate &date ) const
00740 {
00741     return KCalendarSystem::weeksInYear( date );
00742 }
00743 
00744 int KCalendarSystemHebrew::weeksInYear( int year ) const
00745 {
00746     return KCalendarSystem::weeksInYear( year );
00747 }
00748 
00749 int KCalendarSystemHebrew::daysInYear( const QDate &date ) const
00750 {
00751     return KCalendarSystem::daysInYear( date );
00752 }
00753 
00754 int KCalendarSystemHebrew::daysInMonth( const QDate &date ) const
00755 {
00756     return KCalendarSystem::daysInMonth( date );
00757 }
00758 
00759 int KCalendarSystemHebrew::daysInWeek( const QDate &date ) const
00760 {
00761     return KCalendarSystem::daysInWeek( date );
00762 }
00763 
00764 int KCalendarSystemHebrew::dayOfYear( const QDate &date ) const
00765 {
00766     return KCalendarSystem::dayOfYear( date );
00767 }
00768 
00769 int KCalendarSystemHebrew::dayOfWeek( const QDate &date ) const
00770 {
00771     class h_date * sd = toHebrew( date );
00772     if ( sd->hd_dw == 0 ) {
00773         return 7;
00774     } else {
00775         return ( sd->hd_dw );
00776     }
00777 }
00778 
00779 int KCalendarSystemHebrew::weekNumber( const QDate &date, int *yearNum ) const
00780 {
00781     return KCalendarSystem::weekNumber( date, yearNum );
00782 }
00783 
00784 bool KCalendarSystemHebrew::isLeapYear( int year ) const
00785 {
00786     return KCalendarSystem::isLeapYear( year );
00787 }
00788 
00789 bool KCalendarSystemHebrew::isLeapYear( const QDate &date ) const
00790 {
00791     return KCalendarSystem::isLeapYear( date );
00792 }
00793 
00794 // ### Fixme
00795 // JPL Fix what?
00796 // Ask translators for short fomats of month names!
00797 QString KCalendarSystemHebrew::monthName( int month, int year, MonthNameFormat format ) const
00798 {
00799     Q_D( const KCalendarSystemHebrew );
00800 
00801     if ( month < 1 || month > d->monthsInYear( year ) ) {
00802         return QString();
00803     }
00804 
00805     // We must map month number to month index
00806     int monthIndex = d->monthNumberToMonthIndex( year, month );
00807 
00808     if ( format == ShortNamePossessive || format == LongNamePossessive ) {
00809         switch( monthIndex ) {
00810         case 1:
00811             return ki18n( "of Tishrey" ).toString( locale() );
00812         case 2:
00813             return ki18n( "of Heshvan" ).toString( locale() );
00814         case 3:
00815             return ki18n( "of Kislev" ).toString( locale() );
00816         case 4:
00817             return ki18n( "of Tevet" ).toString( locale() );
00818         case 5:
00819             return ki18n( "of Shvat" ).toString( locale() );
00820         case 6:
00821             return ki18n( "of Adar" ).toString( locale() );
00822         case 7:
00823             return ki18n( "of Nisan" ).toString( locale() );
00824         case 8:
00825             return ki18n( "of Iyar" ).toString( locale() );
00826         case 9:
00827             return ki18n( "of Sivan" ).toString( locale() );
00828         case 10:
00829             return ki18n( "of Tamuz" ).toString( locale() );
00830         case 11:
00831             return ki18n( "of Av" ).toString( locale() );
00832         case 12:
00833             return ki18n( "of Elul" ).toString( locale() );
00834         case 13:
00835             return ki18n( "of Adar I" ).toString( locale() );
00836         case 14:
00837             return ki18n( "of Adar II" ).toString( locale() );
00838         default:
00839             return QString();
00840         }
00841     }
00842 
00843     switch( monthIndex ) {
00844     case 1:
00845         return ki18n( "Tishrey" ).toString( locale() );
00846     case 2:
00847         return ki18n( "Heshvan" ).toString( locale() );
00848     case 3:
00849         return ki18n( "Kislev" ).toString( locale() );
00850     case 4:
00851         return ki18n( "Tevet" ).toString( locale() );
00852     case 5:
00853         return ki18n( "Shvat" ).toString( locale() );
00854     case 6:
00855         return ki18n( "Adar" ).toString( locale() );
00856     case 7:
00857         return ki18n( "Nisan" ).toString( locale() );
00858     case 8:
00859         return ki18n( "Iyar" ).toString( locale() );
00860     case 9:
00861         return ki18n( "Sivan" ).toString( locale() );
00862     case 10:
00863         return ki18n( "Tamuz" ).toString( locale() );
00864     case 11:
00865         return ki18n( "Av" ).toString( locale() );
00866     case 12:
00867         return ki18n( "Elul" ).toString( locale() );
00868     case 13:
00869         return ki18n( "Adar I" ).toString( locale() );
00870     case 14:
00871         return ki18n( "Adar II" ).toString( locale() );
00872     default:
00873         return QString();
00874     }
00875 }
00876 
00877 QString KCalendarSystemHebrew::monthName( const QDate& date, MonthNameFormat format ) const
00878 {
00879     return monthName( month( date ), year( date ), format );
00880 }
00881 
00882 QString KCalendarSystemHebrew::weekDayName( int weekDay, WeekDayNameFormat format ) const
00883 {
00884     // Use Western day names for now as that's what the old version did,
00885     // but wouldn't it be better to use the right Hebrew names like Shabbat?
00886     // Could make it switchable by adding new enums to WeekDayFormat, e.g. ShortNameWestern?
00887     if ( format == ShortDayName ) {
00888         switch ( weekDay ) {
00889         case 1:  return ki18nc( "Monday", "Mon" ).toString( locale() );
00890         case 2:  return ki18nc( "Tuesday", "Tue" ).toString( locale() );
00891         case 3:  return ki18nc( "Wednesday", "Wed" ).toString( locale() );
00892         case 4:  return ki18nc( "Thursday", "Thu" ).toString( locale() );
00893         case 5:  return ki18nc( "Friday", "Fri" ).toString( locale() );
00894         case 6:  return ki18nc( "Saturday", "Sat" ).toString( locale() );
00895         case 7:  return ki18nc( "Sunday", "Sun" ).toString( locale() );
00896         default: return QString();
00897         }
00898     }
00899 
00900     switch ( weekDay ) {
00901     case 1:  return ki18n( "Monday" ).toString( locale() );
00902     case 2:  return ki18n( "Tuesday" ).toString( locale() );
00903     case 3:  return ki18n( "Wednesday" ).toString( locale() );
00904     case 4:  return ki18n( "Thursday" ).toString( locale() );
00905     case 5:  return ki18n( "Friday" ).toString( locale() );
00906     case 6:  return ki18n( "Saturday" ).toString( locale() );
00907     case 7:  return ki18n( "Sunday" ).toString( locale() );
00908     default: return QString();
00909     }
00910 }
00911 
00912 QString KCalendarSystemHebrew::weekDayName( const QDate &date, WeekDayNameFormat format ) const
00913 {
00914     return weekDayName( dayOfWeek( date ), format );
00915 }
00916 
00917 QString KCalendarSystemHebrew::yearString( const QDate &date, StringFormat format ) const
00918 {
00919     return KCalendarSystem::yearString( date, format );
00920 }
00921 
00922 QString KCalendarSystemHebrew::monthString( const QDate &date, StringFormat format ) const
00923 {
00924     return KCalendarSystem::monthString( date, format );
00925 }
00926 
00927 QString KCalendarSystemHebrew::dayString( const QDate &date, StringFormat format ) const
00928 {
00929     return KCalendarSystem::dayString( date, format );
00930 }
00931 
00932 int KCalendarSystemHebrew::yearStringToInteger( const QString &string, int &readLength ) const
00933 {
00934     int result = KCalendarSystem::yearStringToInteger( string, readLength );
00935 
00936     // Hebrew has no letter for 0, so 5 and 5000 are written the same
00937     // Assume if less than 10 then we are in an exact multiple of 1000
00938     if ( result < 10 ) {
00939         result = result * 1000;
00940     }
00941 
00942     // Not good just assuming, make configurable
00943     if ( result < 1000 ) {
00944         result += 5000; // assume we're in the 6th millenium (y6k bug)
00945     }
00946 
00947     return result;
00948 }
00949 
00950 int KCalendarSystemHebrew::monthStringToInteger( const QString &string, int &readLength ) const
00951 {
00952     return KCalendarSystem::monthStringToInteger( string, readLength );
00953 }
00954 
00955 int KCalendarSystemHebrew::dayStringToInteger( const QString &string, int &readLength ) const
00956 {
00957     return KCalendarSystem::yearStringToInteger( string, readLength );
00958 }
00959 
00960 QString KCalendarSystemHebrew::formatDate( const QDate &date, KLocale::DateFormat format ) const
00961 {
00962     return KCalendarSystem::formatDate( date, format );
00963 }
00964 
00965 QDate KCalendarSystemHebrew::readDate( const QString &str, bool *ok ) const
00966 {
00967     return KCalendarSystem::readDate( str, ok );
00968 }
00969 
00970 QDate KCalendarSystemHebrew::readDate( const QString &intstr, const QString &fmt, bool *ok ) const
00971 {
00972     return KCalendarSystem::readDate( intstr, fmt, ok );
00973 }
00974 
00975 QDate KCalendarSystemHebrew::readDate( const QString &str, KLocale::ReadDateFlags flags, bool *ok ) const
00976 {
00977     return KCalendarSystem::readDate( str, flags, ok );
00978 }
00979 
00980 int KCalendarSystemHebrew::weekDayOfPray() const
00981 {
00982     return 6; // Saturday
00983 }
00984 
00985 int KCalendarSystemHebrew::weekStartDay() const
00986 {
00987     return KCalendarSystem::weekStartDay();
00988 }
00989 
00990 bool KCalendarSystemHebrew::isLunar() const
00991 {
00992     return false;
00993 }
00994 
00995 bool KCalendarSystemHebrew::isLunisolar() const
00996 {
00997     return true;
00998 }
00999 
01000 bool KCalendarSystemHebrew::isSolar() const
01001 {
01002     return false;
01003 }
01004 
01005 bool KCalendarSystemHebrew::isProleptic() const
01006 {
01007     return false;
01008 }
01009 
01010 bool KCalendarSystemHebrew::julianDayToDate( int jd, int &year, int &month, int &day ) const
01011 {
01012     class h_date * sd = toHebrew( QDate::fromJulianDay( jd ) );
01013 
01014     year = sd->hd_year;
01015 
01016     month = sd->hd_mon;
01017     if ( isLeapYear( sd->hd_year ) ) {
01018         if( month == 13 /*AdarI*/ ) {
01019             month = 6;
01020         } else if( month == 14 /*AdarII*/ ) {
01021             month = 7;
01022         } else if ( month > 6 && month < 13 ) {
01023             ++month;
01024         }
01025     }
01026 
01027     day = sd->hd_day;
01028 
01029     return true;
01030 }
01031 
01032 bool KCalendarSystemHebrew::dateToJulianDay( int year, int month, int day, int &jd ) const
01033 {
01034     class h_date * gd = hebrewToGregorian( year, month, day );
01035 
01036     QDate tempDate( gd->hd_year, gd->hd_mon + 1, gd->hd_day + 1 );
01037 
01038     jd = tempDate.toJulianDay();
01039 
01040     return true;
01041 }

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
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
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