kspread Library API Documentation

kspread_functions_datetime.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998-2003 The KSpread Team
00003                            www.koffice.org/kspread
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.
00019 */
00020 
00021 // built-in date/time functions
00022 
00023 #include <stdlib.h>
00024 #include <math.h>
00025 #include <float.h>
00026 
00027 #include <kdebug.h>
00028 #include <klocale.h>
00029 
00030 #include <koscript_parser.h>
00031 #include <koscript_util.h>
00032 #include <koscript_func.h>
00033 #include <koscript_synext.h>
00034 
00035 #include "kspread_functions.h"
00036 #include "kspread_functions_helper.h"
00037 #include "kspread_interpreter.h"
00038 
00039 // prototypes, sorted
00040 bool kspreadfunc_currentDate( KSContext& context );
00041 bool kspreadfunc_currentDateTime( KSContext& context );
00042 bool kspreadfunc_currentTime( KSContext& context );
00043 bool kspreadfunc_date( KSContext& context );
00044 bool kspreadfunc_datevalue( KSContext& context );
00045 bool kspreadfunc_day( KSContext& context );
00046 bool kspreadfunc_dayname( KSContext& context );
00047 bool kspreadfunc_dayOfYear( KSContext& context );
00048 bool kspreadfunc_days( KSContext& context );
00049 bool kspreadfunc_days360( KSContext& context );
00050 bool kspreadfunc_daysInMonth( KSContext& context );
00051 bool kspreadfunc_daysInYear ( KSContext& context );
00052 bool kspreadfunc_easterSunday( KSContext& context );
00053 bool kspreadfunc_edate( KSContext& context );
00054 bool kspreadfunc_eomonth( KSContext& context );
00055 bool kspreadfunc_hour( KSContext& context );
00056 bool kspreadfunc_hours( KSContext& context );
00057 bool kspreadfunc_isLeapYear ( KSContext& context );
00058 bool kspreadfunc_isoWeekNum( KSContext& context );
00059 bool kspreadfunc_minute( KSContext& context );
00060 bool kspreadfunc_minutes( KSContext& context );
00061 bool kspreadfunc_month( KSContext& context );
00062 bool kspreadfunc_monthname( KSContext& context );
00063 bool kspreadfunc_months( KSContext& context );
00064 bool kspreadfunc_second( KSContext& context );
00065 bool kspreadfunc_seconds( KSContext& context );
00066 bool kspreadfunc_time( KSContext& context );
00067 bool kspreadfunc_timevalue( KSContext& context );
00068 bool kspreadfunc_today( KSContext& context );
00069 bool kspreadfunc_weekday( KSContext& context );
00070 bool kspreadfunc_weeks( KSContext& context );
00071 bool kspreadfunc_weeksInYear( KSContext& context );
00072 bool kspreadfunc_year( KSContext& context );
00073 bool kspreadfunc_years( KSContext& context );
00074 
00075 // registers all date/time functions
00076 // sadly, many of these functions aren't Excel compatible
00077 void KSpreadRegisterDateTimeFunctions()
00078 {
00079   // missing: Excel:    WORKDAY, NETWORKDAYS, WEEKNUM, DATEDIF
00080   //          Gnumeric: UNIX2DATE, DATE2UNIX
00081   // TODO: do we really need DATEVALUE and TIMEVALUE ?
00082   KSpreadFunctionRepository* repo = KSpreadFunctionRepository::self();
00083   repo->registerFunction( "CURRENTDATE",  kspreadfunc_currentDate );
00084   repo->registerFunction( "CURRENTDATETIME",  kspreadfunc_currentDateTime );
00085   repo->registerFunction( "CURRENTTIME",  kspreadfunc_currentTime );
00086   repo->registerFunction( "DATE",  kspreadfunc_date );
00087   repo->registerFunction( "DATEVALUE",  kspreadfunc_datevalue );
00088   repo->registerFunction( "DAY",  kspreadfunc_day );
00089   repo->registerFunction( "DAYNAME",  kspreadfunc_dayname );
00090   repo->registerFunction( "DAYOFYEAR",  kspreadfunc_dayOfYear );
00091   repo->registerFunction( "DAYS",  kspreadfunc_days );
00092   repo->registerFunction( "DAYS360",  kspreadfunc_days360 );
00093   repo->registerFunction( "DAYSINMONTH",  kspreadfunc_daysInMonth );
00094   repo->registerFunction( "DAYSINYEAR",  kspreadfunc_daysInYear );
00095   repo->registerFunction( "EASTERSUNDAY",  kspreadfunc_easterSunday );
00096   repo->registerFunction( "EDATE",  kspreadfunc_edate );
00097   repo->registerFunction( "EOMONTH",  kspreadfunc_eomonth );
00098   repo->registerFunction( "HOUR",  kspreadfunc_hour );
00099   repo->registerFunction( "HOURS",  kspreadfunc_hours );
00100   repo->registerFunction( "ISLEAPYEAR",  kspreadfunc_isLeapYear );
00101   repo->registerFunction( "ISOWEEKNUM",  kspreadfunc_isoWeekNum );
00102   repo->registerFunction( "MINUTE",  kspreadfunc_minute );
00103   repo->registerFunction( "MINUTES",  kspreadfunc_minutes );
00104   repo->registerFunction( "MONTH",  kspreadfunc_month );
00105   repo->registerFunction( "MONTHNAME",  kspreadfunc_monthname );
00106   repo->registerFunction( "MONTHS",  kspreadfunc_months );
00107   repo->registerFunction( "NOW",  kspreadfunc_currentDateTime );
00108   repo->registerFunction( "SECOND",  kspreadfunc_second );
00109   repo->registerFunction( "SECONDS",  kspreadfunc_seconds );
00110   repo->registerFunction( "TIME",  kspreadfunc_time );
00111   repo->registerFunction( "TIMEVALUE",  kspreadfunc_timevalue );
00112   repo->registerFunction( "TODAY",  kspreadfunc_today );
00113   repo->registerFunction( "WEEKDAY",  kspreadfunc_weekday );
00114   repo->registerFunction( "WEEKS",  kspreadfunc_weeks );
00115   repo->registerFunction( "WEEKSINYEAR",  kspreadfunc_weeksInYear );
00116   repo->registerFunction( "YEAR",   kspreadfunc_year );
00117   repo->registerFunction( "YEARS",  kspreadfunc_years );
00118 }
00119 
00120 // Function: EDATE
00121 bool kspreadfunc_edate( KSContext & context )
00122 {
00123   QValueList<KSValue::Ptr> & args = context.value()->listValue();
00124 
00125   if ( !KSUtil::checkArgumentsCount( context, 2, "EDATE", true ) )
00126     return false;
00127 
00128   QDate date;
00129 
00130   if ( !getDate( context, args[0], date ) )
00131     return false;
00132 
00133   int months;
00134 
00135   if ( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
00136   {
00137     if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
00138       return false;
00139 
00140     months = (int) args[1]->doubleValue();
00141   }
00142 
00143   months = args[1]->intValue();
00144 
00145   if ( months > 0 )
00146     addMonths( date, months );
00147   else
00148     subMonths( date, -months );
00149 
00150   if ( !date.isValid() )
00151     return false;
00152 
00153   context.setValue( new KSValue( date ) );
00154   return true;
00155 }
00156 
00157 // Function: EOMONTH
00158 bool kspreadfunc_eomonth( KSContext & context )
00159 {
00160   QValueList<KSValue::Ptr> & args = context.value()->listValue();
00161 
00162   QDate date;
00163   int months = 0;
00164 
00165   if ( !KSUtil::checkArgumentsCount( context, 2, "EOMONTH", true ) )
00166   {
00167     if ( !KSUtil::checkArgumentsCount( context, 1, "EOMONTH", true ) )
00168       return false;
00169 
00170     months = 0;
00171   }
00172   else
00173   {
00174     if ( !KSUtil::checkType( context, args[1], KSValue::DoubleType, true ) )
00175       return false;
00176 
00177     months = (int) args[1]->doubleValue();
00178   }
00179 
00180   if ( !getDate( context, args[0], date ) )
00181     return false;
00182 
00183   if ( months > 0 )
00184     addMonths( date, months );
00185   else
00186     subMonths( date, -months );
00187 
00188   if ( !date.isValid() )
00189     return false;
00190 
00191   date.setYMD( date.year(), date.month(), date.daysInMonth() );
00192 
00193   context.setValue( new KSValue( date ) );
00194   return true;
00195 }
00196 
00197 // Function: DAYS360
00198 // algorithm adapted from gnumeric
00199 bool kspreadfunc_days360( KSContext & context )
00200 {
00201   QValueList<KSValue::Ptr> & args = context.value()->listValue();
00202 
00203   QDate date1;
00204   QDate date2;
00205   bool european = false;
00206 
00207   if ( !KSUtil::checkArgumentsCount( context, 3, "DAYS360", true ) )
00208   {
00209     if ( !KSUtil::checkArgumentsCount( context, 2, "DAYS360", true ) )
00210       return false;
00211   }
00212   else
00213   {
00214     if ( !KSUtil::checkType( context, args[2], KSValue::BoolType, true ) )
00215       return false;
00216 
00217     european = args[2]->boolValue();
00218   }
00219 
00220   if ( !getDate( context, args[0], date1 ) )
00221     return false;
00222 
00223   if ( !getDate( context, args[1], date2 ) )
00224     return false;
00225 
00226   int day1, day2;
00227   int month1, month2;
00228   int year1, year2;
00229   bool negative = false;
00230 
00231   if ( date1.daysTo( date2 ) < 0 )
00232   {
00233     QDate tmp( date1 );
00234     date1 = date2;
00235     date2 = tmp;
00236     negative = true;
00237   }
00238 
00239   day1   = date1.day();
00240   day2   = date2.day();
00241   month1 = date1.month();
00242   month2 = date2.month();
00243   year1  = date1.year();
00244   year2  = date2.year();
00245 
00246   if ( european )
00247   {
00248     if ( day1 == 31 )
00249       day1 = 30;
00250     if ( day2 == 31 )
00251       day2 = 30;
00252   }
00253   else
00254   {
00255     // thanks to the Gnumeric developers for this...
00256     if ( month1 == 2 && month2 == 2
00257          && date1.daysInMonth() == day1
00258          && date2.daysInMonth() == day2 )
00259       day2 = 30;
00260 
00261     if ( month1 == 2 && date1.daysInMonth() == day1 )
00262       day1 = 30;
00263 
00264     if ( day2 == 31 && day1 >= 30 )
00265       day2 = 30;
00266 
00267     if ( day1 == 31 )
00268       day1 = 30;
00269   }
00270 
00271   int result = ( ( year2 - year1 ) * 12 + ( month2 - month1 ) ) * 30
00272     + ( day2 - day1 );
00273 
00274   context.setValue( new KSValue( ( negative ? -result : result ) ) );
00275   return true;
00276 }
00277 
00278 // Function: YEAR
00279 bool kspreadfunc_year( KSContext & context )
00280 {
00281   QValueList<KSValue::Ptr> & args = context.value()->listValue();
00282 
00283   if ( !KSUtil::checkArgumentsCount( context, 1, "YEAR", false ) )
00284   {
00285     context.setValue( new KSValue( QDate::currentDate().year() ) );
00286     return true;
00287   }
00288 
00289   QDate date;
00290   if ( !getDate( context, args[0], date ) )
00291     return false;
00292 
00293   context.setValue( new KSValue( date.year() ) );
00294   return true;
00295 }
00296 
00297 // Function: MONTH
00298 bool kspreadfunc_month( KSContext & context )
00299 {
00300   QValueList<KSValue::Ptr> & args = context.value()->listValue();
00301 
00302   if ( !KSUtil::checkArgumentsCount( context, 1, "MONTH", false ) )
00303   {
00304     context.setValue( new KSValue( QDate::currentDate().month() ) );
00305     return true;
00306   }
00307 
00308   QDate date;
00309   if ( !getDate( context, args[0], date ) )
00310     return false;
00311 
00312   context.setValue( new KSValue( date.month() ) );
00313   return true;
00314 }
00315 
00316 // Function: DAY
00317 bool kspreadfunc_day( KSContext & context )
00318 {
00319   QValueList<KSValue::Ptr> & args = context.value()->listValue();
00320 
00321   if ( !KSUtil::checkArgumentsCount( context, 1, "DAY", false ) )
00322   {
00323     context.setValue( new KSValue( QDate::currentDate().day() ) );
00324     return true;
00325   }
00326 
00327   QDate date;
00328   if ( !getDate( context, args[0], date ) )
00329     return false;
00330 
00331   context.setValue( new KSValue( date.day() ) );
00332   return true;
00333 }
00334 
00335 // Function: HOUR
00336 bool kspreadfunc_hour( KSContext & context )
00337 {
00338   QValueList<KSValue::Ptr> & args = context.value()->listValue();
00339 
00340   int hour;
00341 
00342   if ( !KSUtil::checkArgumentsCount( context, 1, "HOUR", false ) )
00343   {
00344     context.setValue( new KSValue( QTime::currentTime().hour() ) );
00345     return true;
00346   }
00347 
00348   if ( KSUtil::checkType( context, args[0], KSValue::TimeType, true ) )
00349   {
00350     hour = args[0]->timeValue().hour();
00351   }
00352   else if ( KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00353   {
00354     double d = args[0]->doubleValue() + HALFSEC;
00355 
00356     uint secs = (uint) ( ( d - floor( d ) ) * SECSPERDAY );
00357 
00358     hour = secs / 3600;
00359   }
00360   else if ( KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00361   {
00362     QString s = args[0]->stringValue();
00363     bool valid = false;
00364     QTime tmpTime = KGlobal::locale()->readTime( s, &valid );
00365     if ( !valid )
00366       return false;
00367 
00368     hour = tmpTime.hour();
00369   }
00370   else
00371     return false;
00372 
00373   context.setValue( new KSValue( hour ) );
00374   return true;
00375 }
00376 
00377 // Function: MINUTE
00378 bool kspreadfunc_minute( KSContext & context )
00379 {
00380   QValueList<KSValue::Ptr> & args = context.value()->listValue();
00381 
00382   int minute;
00383 
00384   if ( !KSUtil::checkArgumentsCount( context, 1, "MINUTE", false ) )
00385   {
00386     context.setValue( new KSValue( QTime::currentTime().minute() ) );
00387     return true;
00388   }
00389 
00390   if ( KSUtil::checkType( context, args[0], KSValue::TimeType, true ) )
00391   {
00392     minute = args[0]->timeValue().minute();
00393   }
00394   else if ( KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00395   {
00396     double d = args[0]->doubleValue() + HALFSEC;
00397 
00398     uint secs = (uint) ( ( d - floor( d ) ) * SECSPERDAY );
00399     minute = ( secs / 60 ) % 60;
00400   }
00401   else if ( KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00402   {
00403     QString s = args[0]->stringValue();
00404     bool valid = false;
00405     QTime tmpTime = KGlobal::locale()->readTime( s, &valid );
00406     if ( !valid )
00407       return false;
00408 
00409     minute = tmpTime.minute();
00410   }
00411   else
00412     return false;
00413 
00414   context.setValue( new KSValue( minute ) );
00415   return true;
00416 }
00417 
00418 // Function: SECOND
00419 bool kspreadfunc_second( KSContext & context )
00420 {
00421   QValueList<KSValue::Ptr> & args = context.value()->listValue();
00422 
00423   int second;
00424 
00425   if ( !KSUtil::checkArgumentsCount( context, 1, "SECOND", true ) )
00426   {
00427     context.setValue( new KSValue( QTime::currentTime().second() ) );
00428     return true;
00429   }
00430 
00431   if ( KSUtil::checkType( context, args[0], KSValue::TimeType, true ) )
00432   {
00433     second = args[0]->timeValue().second();
00434   }
00435   else if ( KSUtil::checkType( context, args[0], KSValue::DoubleType, true ) )
00436   {
00437     double d = args[0]->doubleValue() + HALFSEC;
00438 
00439     uint secs = (uint) ( ( d - floor( d ) ) * SECSPERDAY );
00440     second = secs % 60;
00441   }
00442   else if ( KSUtil::checkType( context, args[0], KSValue::StringType, true ) )
00443   {
00444     QString s = args[0]->stringValue();
00445     bool valid = false;
00446     QTime tmpTime = KGlobal::locale()->readTime( s, &valid );
00447     if ( !valid )
00448       return false;
00449 
00450     second = tmpTime.second();
00451   }
00452   else
00453     return false;
00454 
00455   context.setValue( new KSValue( second ) );
00456   return true;
00457 }
00458 
00459 // Function: weekday
00460 bool kspreadfunc_weekday( KSContext & context )
00461 {
00462   QValueList<KSValue::Ptr> & args = context.value()->listValue();
00463 
00464   int method = 1;
00465 
00466   if ( !KSUtil::checkArgumentsCount( context, 2, "WEEKDAY", true ) )
00467   {
00468     if ( !KSUtil::checkArgumentsCount( context, 1, "WEEKDAY", false ) )
00469       return false;
00470 
00471     method = 1;
00472   }
00473   else
00474   {
00475     if ( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
00476       return false;
00477 
00478     method = args[1]->intValue();
00479 
00480     if ( method < 1 || method > 3 )
00481       return false;
00482   }
00483 
00484   QDate date;
00485 
00486   if ( !getDate( context, args[0], date ) )
00487     return false;
00488 
00489   int result = date.dayOfWeek();
00490 
00491   if ( method == 3 )
00492     --result;
00493   else if ( method == 1 )
00494   {
00495     ++result;
00496     result = result % 7;
00497   }
00498 
00499   context.setValue( new KSValue( result ) );
00500   return true;
00501 }
00502 
00503 // Function: datevalue
00504 // TODO: do we really need this function ? One can get the same result
00505 // by using the numeric format on a cell with a date/time ...
00506 bool kspreadfunc_datevalue( KSContext & context )
00507 {
00508   QValueList<KSValue::Ptr> & args = context.value()->listValue();
00509 
00510   if ( !KSUtil::checkArgumentsCount( context, 1, "DATEVALUE", true ) )
00511     return false;
00512 
00513   QDate date;
00514 
00515   if ( !getDate( context, args[0], date ) )
00516     return false;
00517 
00518   long int result = (long int) EDate::greg2jul( date );
00519 
00520   context.setValue( new KSValue( result ) );
00521   return true;
00522 }
00523 
00524 // Function: timevalue
00525 // TODO: do we really need this function ? One can get the same result
00526 // by using the numeric format on a cell with a date/time ...
00527 bool kspreadfunc_timevalue( KSContext & context )
00528 {
00529   QValueList<KSValue::Ptr> & args = context.value()->listValue();
00530 
00531   if ( !KSUtil::checkArgumentsCount( context, 1, "TIMEVALUE", true ) )
00532     return false;
00533 
00534   QTime time;
00535 
00536   if ( !getTime( context, args[0], time ) )
00537     return false;
00538 
00539   double result = time.hour() * 3600 + time.minute() * 60 + time.second();
00540   result = result / (double) SECSPERDAY;
00541 
00542   context.setValue( new KSValue( result ) );
00543   return true;
00544 }
00545 
00546 // Function: years
00547 bool kspreadfunc_years( KSContext& context )
00548 {
00549   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00550 
00551   if ( !KSUtil::checkArgumentsCount( context, 3, "YEARS", true ) )
00552     return false;
00553 
00554   // date1 is supposed to be the smaller one
00555   QDate date1;
00556   QDate date2;
00557 
00558   if (!KSUtil::checkType( context, args[2], KSValue::IntType, true ))
00559     return false;
00560 
00561   if ( !getDate( context, args[0], date1 ) )
00562     return false;
00563 
00564   if ( !getDate( context, args[1], date2 ) )
00565     return false;
00566 
00567   if (!date1.isValid())
00568     return false;
00569 
00570   if (!date2.isValid())
00571     return false;
00572 
00573   int type  = args[2]->intValue();
00574   int years = 0;
00575 
00576   if (type == 0)
00577   {
00578     // max. possible years between both dates
00579 
00580     years  = date2.year() - date1.year();
00581 
00582     if (date2.month() < date1.month())
00583     {
00584       --years;
00585     }
00586     else if ( (date2.month() == date1.month()) && (date2.day() < date1.day()) )
00587     {
00588       --years;
00589     }
00590 
00591     context.setValue( new KSValue( years ) );
00592   }
00593   else
00594     //  if (type == 1)
00595   {
00596     // the number of full years in between, starting on 1/1/XXXX
00597     if ( date1.year() == date2.year() )
00598     {
00599       context.setValue( new KSValue( 0 ) );
00600 
00601       return true;
00602     }
00603 
00604     if ( (date1.month() != 1) || (date1.day() != 1) )
00605       date1.setYMD(date1.year() + 1, 1, 1);
00606 
00607     date2.setYMD(date2.year(), 1, 1);
00608 
00609     context.setValue( new KSValue( date2.year() - date1.year() ) );
00610   }
00611 
00612   return true;
00613 }
00614 
00615 // Function: months
00616 bool kspreadfunc_months( KSContext& context )
00617 {
00618   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00619 
00620   if ( !KSUtil::checkArgumentsCount( context, 3, "WEEKS", true ) )
00621     return false;
00622 
00623   // date1 is supposed to be the smaller one
00624   QDate date1;
00625   QDate date2;
00626 
00627   if (!KSUtil::checkType( context, args[2], KSValue::IntType, true ))
00628     return false;
00629 
00630   if ( !getDate( context, args[0], date1 ) )
00631     return false;
00632 
00633   if ( !getDate( context, args[1], date2 ) )
00634     return false;
00635 
00636   if (!date1.isValid())
00637     return false;
00638 
00639   if (!date2.isValid())
00640     return false;
00641 
00642   int type   = args[2]->intValue();
00643   int months = 0;
00644 
00645   if (type == 0)
00646   {
00647     months  = (date2.year() - date1.year()) * 12;
00648     months += date2.month() - date1.month();
00649 
00650     if (date2.day() < date1.day())
00651     {
00652       if (date2.day() != date2.daysInMonth())
00653         --months;
00654     }
00655 
00656     context.setValue( new KSValue( months ) );
00657   }
00658   else
00659   //  if (type == 1)
00660   {
00661     // the number of full months in between, starting on 1/XX/XXXX
00662     if (date1.month() == 12)
00663       date1.setYMD(date1.year() + 1, 1, 1);
00664     else
00665       date1.setYMD(date1.year(), date1.month() + 1, 1);
00666     date2.setYMD(date2.year(), date2.month(), 1);
00667 
00668     months  = (date2.year() - date1.year()) * 12;
00669     months += date2.month() - date1.month();
00670 
00671     context.setValue( new KSValue( months ) );
00672   }
00673 
00674   return true;
00675 }
00676 
00677 // Function: weeks
00678 bool kspreadfunc_weeks( KSContext& context )
00679 {
00680   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00681 
00682   if ( !KSUtil::checkArgumentsCount( context, 3, "WEEKS", true ) )
00683     return false;
00684 
00685   // date1 is supposed to be the smaller one
00686   QDate date1;
00687   QDate date2;
00688 
00689   if (!KSUtil::checkType( context, args[2], KSValue::IntType, true ))
00690     return false;
00691 
00692   if ( !getDate( context, args[0], date1 ) )
00693     return false;
00694 
00695   if ( !getDate( context, args[1], date2 ) )
00696     return false;
00697 
00698   if (!date1.isValid())
00699     return false;
00700 
00701   if (!date2.isValid())
00702     return false;
00703 
00704   int type = args[2]->intValue();
00705 
00706   int days = date1.daysTo(date2);
00707 
00708   if (type == 0)
00709   {
00710     // just the number of full weeks between
00711     context.setValue( new KSValue( (int)(days / 7) ) );
00712     return true;
00713   }
00714   else
00715     //  if (type == 1)
00716   {
00717     // the number of full weeks between starting on mondays
00718     bool mondayFirstDay = KGlobal::locale()->weekStartsMonday();
00719 
00720     int dow1 = date1.dayOfWeek();
00721     int dow2 = date2.dayOfWeek();
00722 
00723     if (mondayFirstDay)
00724     {
00725       days -= (8 - dow1);
00726       days -= (dow2 - 1);
00727     }
00728     else
00729     {
00730       days -= (7 - dow1);
00731       days -= dow2;
00732     }
00733 
00734     context.setValue( new KSValue( (int) (days / 7) ) );
00735   }
00736 
00737   return true;
00738 }
00739 
00740 // Function: days
00741 bool kspreadfunc_days( KSContext& context )
00742 {
00743   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00744 
00745   if ( !KSUtil::checkArgumentsCount( context, 2, "DAYS", true ) )
00746     return false;
00747 
00748   QDate date1;
00749   QDate date2;
00750 
00751   if ( !getDate( context, args[0], date1 ) )
00752     return false;
00753 
00754   if ( !getDate( context, args[1], date2 ) )
00755     return false;
00756 
00757   if (!date1.isValid())
00758     return false;
00759 
00760   if (!date2.isValid())
00761     return false;
00762 
00763   int result = date1.daysTo(date2);
00764 
00765   context.setValue( new KSValue(result));
00766   return true;
00767 }
00768 
00769 // Function: hours
00770 bool kspreadfunc_hours( KSContext& context )
00771 {
00772   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00773 
00774   if ( !KSUtil::checkArgumentsCount( context, 1, "hours", true ) )
00775     return false;
00776 
00777   QTime tmpTime;
00778 
00779   if (!getTime(context, args[0], tmpTime))
00780     return false;
00781 
00782   context.setValue( new KSValue( tmpTime.hour() ) );
00783 
00784   return true;
00785 }
00786 
00787 // Function: minutes
00788 bool kspreadfunc_minutes( KSContext& context )
00789 {
00790   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00791 
00792   if ( !KSUtil::checkArgumentsCount( context, 1, "minutes", true ) )
00793     return false;
00794 
00795   QTime tmpTime;
00796 
00797   if (!getTime(context, args[0], tmpTime))
00798     return false;
00799 
00800   context.setValue( new KSValue( tmpTime.minute() ) );
00801 
00802   return true;
00803 }
00804 
00805 // Function: seconds
00806 bool kspreadfunc_seconds( KSContext& context )
00807 {
00808   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00809 
00810   if ( !KSUtil::checkArgumentsCount( context, 1, "seconds", true ) )
00811     return false;
00812 
00813   QTime tmpTime;
00814 
00815   if (!getTime(context, args[0], tmpTime))
00816     return false;
00817 
00818   context.setValue( new KSValue( tmpTime.second() ) );
00819 
00820   return true;
00821 }
00822 
00823 // Function: date
00824 bool kspreadfunc_date( KSContext& context )
00825 {
00826   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00827 
00828   if ( !KSUtil::checkArgumentsCount( context,3, "date",true ) )
00829     return false;
00830 
00831   if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
00832     return false;
00833 
00834   if ( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
00835     return false;
00836 
00837   if ( !KSUtil::checkType( context, args[2], KSValue::IntType, true ) )
00838     return false;
00839 
00840   QDate _date;
00841   if( _date.setYMD(args[0]->intValue(), args[1]->intValue(), args[2]->intValue()) )
00842     context.setValue( new KSValue(_date));
00843   else
00844     context.setValue( new KSValue(i18n("Err")) );
00845 
00846   return true;
00847 }
00848 
00849 // Function: day
00850 bool kspreadfunc_dayname( KSContext& context )
00851 {
00852   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00853   QString tmp;
00854   if ( !KSUtil::checkArgumentsCount( context,1, "DAYNAME", true ) )
00855     return false;
00856 
00857   if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
00858     return false;
00859 
00860   if ( KGlobal::locale()->weekDayName( args[0]->intValue() ).isNull() )
00861     tmp = i18n( "Err" );
00862   else
00863     tmp = KGlobal::locale()->weekDayName( args[0]->intValue() );
00864 
00865   context.setValue( new KSValue( tmp ) );
00866   return true;
00867 }
00868 
00869 // Function: monthname
00870 bool kspreadfunc_monthname( KSContext& context )
00871 {
00872   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00873   QString tmp;
00874   if ( !KSUtil::checkArgumentsCount( context, 1, "MONTHNAME", true ) )
00875     return false;
00876 
00877   if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
00878     return false;
00879 
00880   if ( KGlobal::locale()->monthName( args[0]->intValue()).isNull() )
00881     tmp = i18n( "Err" );
00882   else
00883     tmp = KGlobal::locale()->monthName( args[0]->intValue() );
00884 
00885   context.setValue( new KSValue( tmp ) );
00886   return true;
00887 }
00888 
00889 // Function: time
00890 bool kspreadfunc_time( KSContext& context )
00891 {
00892   int hour;
00893   int minute;
00894   int second;
00895 
00896   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00897 
00898   if ( !KSUtil::checkArgumentsCount( context,3, "time",true ) )
00899     return false;
00900 
00901   if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
00902     return false;
00903 
00904   if ( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
00905     return false;
00906 
00907   if ( !KSUtil::checkType( context, args[2], KSValue::IntType, true ) )
00908     return false;
00909 
00910   hour = args[0]->intValue();
00911   minute = args[1]->intValue();
00912   second = args[2]->intValue();
00913 
00914   /* normalize the data */
00915   minute += second / 60;
00916   second = second % 60;
00917   hour += minute / 60;
00918   minute = minute % 60;
00919 
00920   /* we'll lose hours data that carries over into days */
00921   hour = hour % 24;
00922 
00923   /* now carry down hours/minutes for negative minutes/seconds */
00924 
00925   if (second < 0)
00926   {
00927     second += 60;
00928     minute -= 1;
00929   }
00930 
00931   if (minute < 0)
00932   {
00933     minute += 60;
00934     hour -= 1;
00935   }
00936 
00937   if (hour < 0)
00938   {
00939     hour += 24;
00940   }
00941 
00942   context.setValue( new KSValue(QTime(hour, minute, second)));
00943 
00944   return true;
00945 }
00946 
00947 // Function: currentDate
00948 bool kspreadfunc_currentDate( KSContext& context )
00949 {
00950     if ( !KSUtil::checkArgumentsCount( context,0, "currentDate",true ) )
00951       return false;
00952 
00953     context.setValue( new KSValue(QDate::currentDate()));
00954 
00955     return true;
00956 }
00957 
00958 // Function: today
00959 // same as currentDate - merge maybe ?
00960 bool kspreadfunc_today( KSContext& context )
00961 {
00962     if ( !KSUtil::checkArgumentsCount( context,0, "today",true ) )
00963       return false;
00964 
00965     context.setValue( new KSValue(QDate::currentDate()) );
00966 
00967     return true;
00968 }
00969 
00970 // Function: currentTime
00971 bool kspreadfunc_currentTime( KSContext& context )
00972 {
00973     if ( !KSUtil::checkArgumentsCount( context,0, "currentTime",true ) )
00974       return false;
00975 
00976     context.setValue( new KSValue(QTime::currentTime()));
00977 
00978     return true;
00979 }
00980 
00981 // Function: currentDateTime
00982 bool kspreadfunc_currentDateTime( KSContext& context )
00983 {
00984     if ( !KSUtil::checkArgumentsCount( context,0, "currentDateTime",true ) )
00985       return false;
00986 // TODO: do NOT format the date here with the new parser (old one doesn't
00987 // support QDateTime, so I cannot do it here, sorry)
00988     context.setValue( new KSValue(KGlobal::locale()->formatDateTime(QDateTime::currentDateTime(), false)));
00989 
00990     return true;
00991 }
00992 
00993 // Function: dayOfYear
00994 bool kspreadfunc_dayOfYear( KSContext& context )
00995 {
00996   QValueList<KSValue::Ptr>& args = context.value()->listValue();
00997 
00998   if ( !KSUtil::checkArgumentsCount( context,3, "dayOfYear",true ) )
00999     return false;
01000 
01001   if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
01002     return false;
01003 
01004   if ( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
01005     return false;
01006 
01007   if ( !KSUtil::checkType( context, args[2], KSValue::IntType, true ) )
01008     return false;
01009 
01010   context.setValue( new KSValue(QDate(args[0]->intValue(),
01011                                       args[1]->intValue(),args[2]->intValue()).dayOfYear() ));
01012 
01013   return true;
01014 }
01015 
01016 bool isLeapYear_helper(int _year)
01017 {
01018     return (((_year % 4) == 0) && ((_year % 100) != 0) || ((_year % 400) == 0));
01019 }
01020 
01021 // Function: daysInMonth
01022 bool kspreadfunc_daysInMonth( KSContext& context )
01023 {
01024   QValueList<KSValue::Ptr>& args = context.value()->listValue();
01025   if ( !KSUtil::checkArgumentsCount( context,2,"daysInMonth",true ) )
01026     return false;
01027 
01028   if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
01029   {
01030     context.setValue( new KSValue( i18n("Err") ) );
01031     return true;
01032   }
01033   if ( !KSUtil::checkType( context, args[1], KSValue::IntType, true ) )
01034   {
01035     context.setValue( new KSValue( i18n("Err") ) );
01036     return true;
01037   }
01038 
01039   static uint aDaysInMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
01040   int nYear = args[0]->intValue();
01041   int nMonth = args[1]->intValue();
01042   int result;
01043 
01044   if ( nMonth != 2)
01045     result = aDaysInMonth[nMonth-1];
01046   else
01047   {
01048     if (isLeapYear_helper(nYear))
01049         result = aDaysInMonth[nMonth-1] + 1;
01050     else
01051         result = aDaysInMonth[nMonth-1];
01052   }
01053 
01054   context.setValue( new KSValue(result));
01055 
01056   return true;
01057 }
01058 
01059 // Function: isLeapYear
01060 bool kspreadfunc_isLeapYear ( KSContext& context )
01061 {
01062   QValueList<KSValue::Ptr>& args = context.value()->listValue();
01063   if ( !KSUtil::checkArgumentsCount( context,1,"isLeapYear",true ) )
01064     return false;
01065   bool result=true;
01066   if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
01067     return false;
01068 
01069   if(result)
01070   {
01071     int nYear = args[0]->intValue();
01072     result = isLeapYear_helper(nYear);
01073   }
01074 
01075   context.setValue( new KSValue(result));
01076 
01077   return true;
01078 }
01079 
01080 // Function: daysInYear
01081 bool kspreadfunc_daysInYear ( KSContext& context )
01082 {
01083   QValueList<KSValue::Ptr>& args = context.value()->listValue();
01084   if ( !KSUtil::checkArgumentsCount( context,1,"daysInYear",true ) )
01085     return false;
01086   if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
01087     return false;
01088 
01089   int nYear = args[0]->intValue();
01090   bool leap = isLeapYear_helper(nYear);
01091   int result;
01092 
01093   if (leap)
01094     result = 366;
01095   else
01096     result = 365;
01097 
01098   context.setValue( new KSValue(result));
01099 
01100   return true;
01101 }
01102 
01103 // Function: weeksInYear
01104 bool kspreadfunc_weeksInYear( KSContext& context )
01105 {
01106   QValueList<KSValue::Ptr>& args = context.value()->listValue();
01107   if ( !KSUtil::checkArgumentsCount( context,1,"weeksInYear",true ) )
01108     return false;
01109   if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
01110     return false;
01111 
01112   int nYear = args[0]->intValue();
01113   int result;
01114   QDate _date(nYear, 1, 1);
01115   int nJan1DayOfWeek = _date.dayOfWeek();   //first day of the year
01116 
01117   if ( nJan1DayOfWeek == 4 ) { // Thursday
01118         result = 53;
01119   } else if ( nJan1DayOfWeek == 3 ) { // Wednesday
01120         result = isLeapYear_helper(nYear) ? 53 : 52 ;
01121   } else {
01122         result = 52;
01123   }
01124 
01125   context.setValue( new KSValue(result));
01126 
01127   return true;
01128 }
01129 
01130 // Function: easterSunday
01131 bool kspreadfunc_easterSunday( KSContext& context )
01132 {
01133     QValueList<KSValue::Ptr>& args = context.value()->listValue();
01134     if ( !KSUtil::checkArgumentsCount( context,1,"easterSunday",true ) )
01135         return false;
01136     if ( !KSUtil::checkType( context, args[0], KSValue::IntType, true ) )
01137         return false;
01138 
01139     int nDay, nMonth;
01140     int nYear = args[0]->intValue();
01141 
01142     int B,C,D,E,F,G,H,I,K,L,M,N,O;
01143     N = nYear % 19;
01144     B = int(nYear / 100);
01145     C = nYear % 100;
01146     D = int(B / 4);
01147     E = B % 4;
01148     F = int((B + 8) / 25);
01149     G = int((B - F + 1) / 3);
01150     H = (19 * N + B - D - G + 15) % 30;
01151     I = int(C / 4);
01152     K = C % 4;
01153     L = (32 + 2 * E + 2 * I - H - K) % 7;
01154     M = int((N + 11 * H + 22 * L) / 451);
01155     O = H + L - 7 * M + 114;
01156     nDay = O % 31 + 1;
01157     nMonth = int(O / 31);
01158 
01159     context.setValue( new KSValue(QDate(nYear, nMonth, nDay)));
01160 
01161     return true;
01162 }
01163 
01164 // Function: isoWeekNum
01165 bool kspreadfunc_isoWeekNum( KSContext& context )
01166 {
01167     QValueList<KSValue::Ptr>& args = context.value()->listValue();
01168     if ( !KSUtil::checkArgumentsCount( context,1,"isoWeekNum",true ) )
01169         return false;
01170 
01171     QDate tmpDate;
01172 
01173     if (!getDate(context, args[0], tmpDate))
01174         return false;
01175 
01176     if (!tmpDate.isValid())
01177         return false;
01178 
01179     int result = tmpDate.weekNumber();
01180 
01181     if (result==0)
01182         return false;
01183 
01184     context.setValue( new KSValue(result) );
01185     return true;
01186 }
KDE Logo
This file is part of the documentation for kspread Library Version 1.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Feb 13 09:43:09 2006 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003