00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "functions.h"
00025 #include "kspread_functions_helper.h"
00026 #include "valuecalc.h"
00027 #include "valueconverter.h"
00028
00029 #include <kcalendarsystem.h>
00030 #include <klocale.h>
00031
00032 using namespace KSpread;
00033
00034
00035 Value func_currentDate (valVector args, ValueCalc *calc, FuncExtra *);
00036 Value func_currentDateTime (valVector args, ValueCalc *calc, FuncExtra *);
00037 Value func_currentTime (valVector args, ValueCalc *calc, FuncExtra *);
00038 Value func_date (valVector args, ValueCalc *calc, FuncExtra *);
00039 Value func_datevalue (valVector args, ValueCalc *calc, FuncExtra *);
00040 Value func_day (valVector args, ValueCalc *calc, FuncExtra *);
00041 Value func_dayname (valVector args, ValueCalc *calc, FuncExtra *);
00042 Value func_dayOfYear (valVector args, ValueCalc *calc, FuncExtra *);
00043 Value func_days (valVector args, ValueCalc *calc, FuncExtra *);
00044 Value func_days360 (valVector args, ValueCalc *calc, FuncExtra *);
00045 Value func_daysInMonth (valVector args, ValueCalc *calc, FuncExtra *);
00046 Value func_daysInYear (valVector args, ValueCalc *calc, FuncExtra *);
00047 Value func_easterSunday (valVector args, ValueCalc *calc, FuncExtra *);
00048 Value func_edate (valVector args, ValueCalc *calc, FuncExtra *);
00049 Value func_eomonth (valVector args, ValueCalc *calc, FuncExtra *);
00050 Value func_hour (valVector args, ValueCalc *calc, FuncExtra *);
00051 Value func_hours (valVector args, ValueCalc *calc, FuncExtra *);
00052 Value func_isLeapYear (valVector args, ValueCalc *calc, FuncExtra *);
00053 Value func_isoWeekNum (valVector args, ValueCalc *calc, FuncExtra *);
00054 Value func_minute (valVector args, ValueCalc *calc, FuncExtra *);
00055 Value func_minutes (valVector args, ValueCalc *calc, FuncExtra *);
00056 Value func_month (valVector args, ValueCalc *calc, FuncExtra *);
00057 Value func_monthname (valVector args, ValueCalc *calc, FuncExtra *);
00058 Value func_months (valVector args, ValueCalc *calc, FuncExtra *);
00059 Value func_second (valVector args, ValueCalc *calc, FuncExtra *);
00060 Value func_seconds (valVector args, ValueCalc *calc, FuncExtra *);
00061 Value func_time (valVector args, ValueCalc *calc, FuncExtra *);
00062 Value func_timevalue (valVector args, ValueCalc *calc, FuncExtra *);
00063 Value func_today (valVector args, ValueCalc *calc, FuncExtra *);
00064 Value func_weekday (valVector args, ValueCalc *calc, FuncExtra *);
00065 Value func_weeks (valVector args, ValueCalc *calc, FuncExtra *);
00066 Value func_weeksInYear (valVector args, ValueCalc *calc, FuncExtra *);
00067 Value func_year (valVector args, ValueCalc *calc, FuncExtra *);
00068 Value func_years (valVector args, ValueCalc *calc, FuncExtra *);
00069
00070
00071
00072 void RegisterDateTimeFunctions()
00073 {
00074
00075
00076
00077 FunctionRepository* repo = FunctionRepository::self();
00078 Function *f;
00079
00080 f = new Function ("CURRENTDATE", func_currentDate);
00081 f->setParamCount (0);
00082 repo->add (f);
00083 f = new Function ("CURRENTDATETIME", func_currentDateTime);
00084 f->setParamCount (0);
00085 repo->add (f);
00086 f = new Function ("CURRENTTIME", func_currentTime);
00087 f->setParamCount (0);
00088 repo->add (f);
00089 f = new Function ("DATE", func_date);
00090 f->setParamCount (3);
00091 repo->add (f);
00092 f = new Function ("DATEVALUE", func_datevalue);
00093 repo->add (f);
00094 f = new Function ("DAY", func_day);
00095 repo->add (f);
00096 f = new Function ("DAYNAME", func_dayname);
00097 repo->add (f);
00098 f = new Function ("DAYOFYEAR", func_dayOfYear);
00099 f->setParamCount (3);
00100 repo->add (f);
00101 f = new Function ("DAYS", func_days);
00102 f->setParamCount (2);
00103 repo->add (f);
00104 f = new Function ("DAYS360", func_days360);
00105 f->setParamCount (2, 3);
00106 repo->add (f);
00107 f = new Function ("DAYSINMONTH", func_daysInMonth);
00108 f->setParamCount (2);
00109 repo->add (f);
00110 f = new Function ("DAYSINYEAR", func_daysInYear);
00111 repo->add (f);
00112 f = new Function ("EASTERSUNDAY", func_easterSunday);
00113 repo->add (f);
00114 f = new Function ("EDATE", func_edate);
00115 f->setParamCount (2);
00116 repo->add (f);
00117 f = new Function ("EOMONTH", func_eomonth);
00118 f->setParamCount (2);
00119 repo->add (f);
00120 f = new Function ("HOUR", func_hour);
00121 f->setParamCount (0, 1);
00122 repo->add (f);
00123 f = new Function ("HOURS", func_hour);
00124 f->setParamCount (0, 1);
00125 repo->add (f);
00126 f = new Function ("ISLEAPYEAR", func_isLeapYear);
00127 repo->add (f);
00128 f = new Function ("ISOWEEKNUM", func_isoWeekNum);
00129 repo->add (f);
00130 f = new Function ("MINUTE", func_minute);
00131 f->setParamCount (0, 1);
00132 repo->add (f);
00133 f = new Function ("MINUTES", func_minute);
00134 f->setParamCount (0, 1);
00135 repo->add (f);
00136 f = new Function ("MONTH", func_month);
00137 repo->add (f);
00138 f = new Function ("MONTHNAME", func_monthname);
00139 repo->add (f);
00140 f = new Function ("MONTHS", func_months);
00141 f->setParamCount (3);
00142 repo->add (f);
00143 f = new Function ("NOW", func_currentDateTime);
00144 f->setParamCount (0);
00145 repo->add (f);
00146 f = new Function ("SECOND", func_second);
00147 f->setParamCount (0, 1);
00148 repo->add (f);
00149 f = new Function ("SECONDS", func_second);
00150 f->setParamCount (0, 1);
00151 repo->add (f);
00152 f = new Function ("TIME", func_time);
00153 f->setParamCount (3);
00154 repo->add (f);
00155 f = new Function ("TIMEVALUE", func_timevalue);
00156 repo->add (f);
00157 f = new Function ("TODAY", func_currentDate);
00158 f->setParamCount (0);
00159 repo->add (f);
00160 f = new Function ("WEEKDAY", func_weekday);
00161 f->setParamCount (1, 2);
00162 repo->add (f);
00163 f = new Function ("WEEKS", func_weeks);
00164 f->setParamCount (3);
00165 repo->add (f);
00166 f = new Function ("WEEKSINYEAR", func_weeksInYear);
00167 repo->add (f);
00168 f = new Function ("YEAR", func_year);
00169 repo->add (f);
00170 f = new Function ("YEARS", func_years);
00171 f->setParamCount (3);
00172 repo->add (f);
00173 }
00174
00175
00176 Value func_edate (valVector args, ValueCalc *calc, FuncExtra *)
00177 {
00178 QDate date = calc->conv()->asDate (args[0]).asDate();
00179 int months = calc->conv()->asInteger (args[1]).asInteger();
00180
00181 date = calc->conv()->locale()->calendar()->addMonths (date, months);
00182
00183 if (!date.isValid())
00184 return Value::errorVALUE();
00185
00186 return Value (date);
00187 }
00188
00189
00190 Value func_eomonth (valVector args, ValueCalc *calc, FuncExtra *)
00191 {
00192
00193 Value modDate = func_edate (args, calc, 0);
00194 if (modDate.isError()) return modDate;
00195
00196
00197 QDate date = modDate.asDate();
00198 date.setYMD (date.year(), date.month(), date.daysInMonth());
00199
00200 return Value (date);
00201 }
00202
00203
00204
00205 Value func_days360 (valVector args, ValueCalc *calc, FuncExtra *)
00206 {
00207 QDate date1 = calc->conv()->asDate (args[0]).asDate();
00208 QDate date2 = calc->conv()->asDate (args[1]).asDate();
00209 bool european = false;
00210 if (args.count() == 3)
00211 european = calc->conv()->asBoolean (args[2]).asBoolean();
00212
00213 int day1, day2;
00214 int month1, month2;
00215 int year1, year2;
00216 bool negative = false;
00217
00218 if (date1.daysTo( date2 ) < 0)
00219 {
00220 QDate tmp( date1 );
00221 date1 = date2;
00222 date2 = tmp;
00223 negative = true;
00224 }
00225
00226 day1 = date1.day();
00227 day2 = date2.day();
00228 month1 = date1.month();
00229 month2 = date2.month();
00230 year1 = date1.year();
00231 year2 = date2.year();
00232
00233 if ( european )
00234 {
00235 if ( day1 == 31 )
00236 day1 = 30;
00237 if ( day2 == 31 )
00238 day2 = 30;
00239 }
00240 else
00241 {
00242
00243 if ( month1 == 2 && month2 == 2
00244 && date1.daysInMonth() == day1
00245 && date2.daysInMonth() == day2 )
00246 day2 = 30;
00247
00248 if ( month1 == 2 && date1.daysInMonth() == day1 )
00249 day1 = 30;
00250
00251 if ( day2 == 31 && day1 >= 30 )
00252 day2 = 30;
00253
00254 if ( day1 == 31 )
00255 day1 = 30;
00256 }
00257
00258 int result = ( ( year2 - year1 ) * 12 + ( month2 - month1 ) ) * 30
00259 + ( day2 - day1 );
00260
00261 return Value (result);
00262 }
00263
00264
00265 Value func_year (valVector args, ValueCalc *calc, FuncExtra *)
00266 {
00267 Value v = calc->conv()->asDate (args[0]);
00268 if (v.isError()) return v;
00269 QDate date = v.asDate();
00270 return Value (date.year ());
00271 }
00272
00273
00274 Value func_month (valVector args, ValueCalc *calc, FuncExtra *)
00275 {
00276 Value v = calc->conv()->asDate (args[0]);
00277 if (v.isError()) return v;
00278 QDate date = v.asDate();
00279 return Value (date.month ());
00280 }
00281
00282
00283 Value func_day (valVector args, ValueCalc *calc, FuncExtra *)
00284 {
00285 Value v = calc->conv()->asDate (args[0]);
00286 if (v.isError()) return v;
00287 QDate date = v.asDate();
00288 return Value (date.day ());
00289 }
00290
00291
00292 Value func_hour (valVector args, ValueCalc *calc, FuncExtra *)
00293 {
00294 QTime time;
00295 if (args.count() == 1)
00296 {
00297 Value v = calc->conv()->asTime (args[0]);
00298 if (v.isError()) return v;
00299 time = v.asTime();
00300 }
00301 else
00302 time = QTime::currentTime ();
00303 return Value (time.hour ());
00304 }
00305
00306
00307 Value func_minute (valVector args, ValueCalc *calc, FuncExtra *)
00308 {
00309 QTime time;
00310 if (args.count() == 1)
00311 {
00312 Value v = calc->conv()->asTime (args[0]);
00313 if (v.isError()) return v;
00314 time = v.asTime();
00315 }
00316 else
00317 time = QTime::currentTime ();
00318 return Value (time.minute ());
00319 }
00320
00321
00322 Value func_second (valVector args, ValueCalc *calc, FuncExtra *)
00323 {
00324 QTime time;
00325 if (args.count() == 1)
00326 {
00327 Value v = calc->conv()->asTime (args[0]);
00328 if (v.isError()) return v;
00329 time = v.asTime();
00330 }
00331 else
00332 time = QTime::currentTime ();
00333 return Value (time.second ());
00334 }
00335
00336
00337 Value func_weekday (valVector args, ValueCalc *calc, FuncExtra *)
00338 {
00339 Value v = calc->conv()->asDate (args[0]).asDate();
00340 if (v.isError()) return v;
00341 QDate date = v.asDate();
00342 int method = 1;
00343 if (args.count() == 2)
00344 method = calc->conv()->asInteger (args[1]).asInteger();
00345
00346 if ( method < 1 || method > 3 )
00347 return Value::errorVALUE();
00348
00349 int result = date.dayOfWeek();
00350
00351 if (method == 3)
00352 --result;
00353 else if (method == 1)
00354 {
00355 ++result;
00356 result = result % 7;
00357 }
00358
00359 return Value (result);
00360 }
00361
00362
00363
00364 Value func_datevalue (valVector args, ValueCalc *calc, FuncExtra *)
00365 {
00366 return calc->conv()->asFloat (calc->conv()->asDate (args[0]));
00367 }
00368
00369
00370
00371 Value func_timevalue (valVector args, ValueCalc *calc, FuncExtra *)
00372 {
00373 return calc->conv()->asFloat (calc->conv()->asTime (args[0]));
00374 }
00375
00376
00377 Value func_years (valVector args, ValueCalc *calc, FuncExtra *)
00378 {
00379 QDate date1 = calc->conv()->asDate (args[0]).asDate();
00380 QDate date2 = calc->conv()->asDate (args[1]).asDate();
00381 if (!date1.isValid() || !date2.isValid())
00382 return Value::errorVALUE();
00383
00384 int type = calc->conv()->asInteger (args[2]).asInteger();
00385 if (type == 0)
00386 {
00387
00388 int years = date2.year() - date1.year();
00389
00390 if (date2.month() < date1.month())
00391 --years;
00392 else if ( (date2.month() == date1.month()) && (date2.day() < date1.day()) )
00393 --years;
00394
00395 return Value (years);
00396 }
00397
00398
00399
00400 if ( date1.year() == date2.year() )
00401 return Value (0);
00402
00403 if ( (date1.month() != 1) || (date1.day() != 1) )
00404 date1.setYMD(date1.year() + 1, 1, 1);
00405 date2.setYMD(date2.year(), 1, 1);
00406
00407 return Value (date2.year() - date1.year());
00408 }
00409
00410
00411 Value func_months (valVector args, ValueCalc *calc, FuncExtra *)
00412 {
00413 QDate date1 = calc->conv()->asDate (args[0]).asDate();
00414 QDate date2 = calc->conv()->asDate (args[1]).asDate();
00415 if (!date1.isValid() || !date2.isValid())
00416 return Value::errorVALUE();
00417
00418 int type = calc->conv()->asInteger (args[2]).asInteger();
00419 if (type == 0)
00420 {
00421 int months = (date2.year() - date1.year()) * 12;
00422 months += date2.month() - date1.month();
00423
00424 if (date2.day() < date1.day())
00425 if (date2.day() != date2.daysInMonth())
00426 --months;
00427
00428 return Value (months);
00429 }
00430
00431
00432
00433 if (date1.month() == 12)
00434 date1.setYMD(date1.year() + 1, 1, 1);
00435 else
00436 date1.setYMD(date1.year(), date1.month() + 1, 1);
00437 date2.setYMD(date2.year(), date2.month(), 1);
00438
00439 int months = (date2.year() - date1.year()) * 12;
00440 months += date2.month() - date1.month();
00441
00442 return Value (months);
00443 }
00444
00445
00446 Value func_weeks (valVector args, ValueCalc *calc, FuncExtra *)
00447 {
00448 QDate date1 = calc->conv()->asDate (args[0]).asDate();
00449 QDate date2 = calc->conv()->asDate (args[1]).asDate();
00450 if (!date1.isValid() || !date2.isValid())
00451 return Value::errorVALUE();
00452
00453 int type = calc->conv()->asInteger (args[2]).asInteger();
00454 int days = date1.daysTo (date2);
00455 if (type == 0)
00456
00457 return Value ((int) (days / 7));
00458
00459
00460 int weekStartDay = calc->conv()->locale()->weekStartDay();
00461
00462 int dow1 = date1.dayOfWeek();
00463 int dow2 = date2.dayOfWeek();
00464
00465 days -= (7 + (weekStartDay % 7) - dow1);
00466 days -= ((dow2 - weekStartDay) % 7);
00467
00468 return Value ((int) (days / 7));
00469 }
00470
00471
00472 Value func_days (valVector args, ValueCalc *calc, FuncExtra *)
00473 {
00474 QDate date1 = calc->conv()->asDate (args[0]).asDate();
00475 QDate date2 = calc->conv()->asDate (args[1]).asDate();
00476 if (!date1.isValid() || !date2.isValid())
00477 return Value::errorVALUE();
00478
00479 return Value (date1.daysTo (date2));
00480 }
00481
00482
00483 Value func_date (valVector args, ValueCalc *calc, FuncExtra *)
00484 {
00485 int y = calc->conv()->asInteger (args[0]).asInteger();
00486 int m = calc->conv()->asInteger (args[1]).asInteger();
00487 int d = calc->conv()->asInteger (args[2]).asInteger();
00488
00489 QDate _date;
00490 if( _date.setYMD (y, m, d))
00491 return Value (_date);
00492 return Value::errorVALUE();
00493 }
00494
00495
00496 Value func_dayname (valVector args, ValueCalc *calc, FuncExtra *)
00497 {
00498 int number = calc->conv()->asInteger (args[0]).asInteger();
00499
00500 QString weekName = calc->conv()->locale()->calendar()->weekDayName (number);
00501 if (weekName.isNull())
00502 return Value::errorVALUE();
00503 return Value (weekName);
00504 }
00505
00506
00507 Value func_monthname (valVector args, ValueCalc *calc, FuncExtra *)
00508 {
00509 int number = calc->conv()->asInteger (args[0]).asInteger();
00510
00511 QString monthName = calc->conv()->locale()->calendar()->monthName (number,
00512 QDate::currentDate().year());
00513 if (monthName.isNull())
00514 return Value::errorVALUE();
00515 return Value (monthName);
00516 }
00517
00518
00519 Value func_time (valVector args, ValueCalc *calc, FuncExtra *)
00520 {
00521 int h = calc->conv()->asInteger (args[0]).asInteger();
00522 int m = calc->conv()->asInteger (args[1]).asInteger();
00523 int s = calc->conv()->asInteger (args[2]).asInteger();
00524
00525
00526 m += s / 60;
00527 s = s % 60;
00528 h += m / 60;
00529 m = m % 60;
00530
00531 h = h % 24;
00532
00533
00534 if (s < 0) {
00535 s += 60;
00536 m -= 1;
00537 }
00538 if (m < 0) {
00539 m += 60;
00540 h -= 1;
00541 }
00542 if (h < 0)
00543 h += 24;
00544
00545 return Value (QTime (h, m, s));
00546 }
00547
00548
00549 Value func_currentDate (valVector, ValueCalc *, FuncExtra *)
00550 {
00551 return Value (QDate::currentDate ());
00552 }
00553
00554
00555 Value func_currentTime (valVector, ValueCalc *, FuncExtra *)
00556 {
00557 return Value (QTime::currentTime ());
00558 }
00559
00560
00561 Value func_currentDateTime (valVector, ValueCalc *, FuncExtra *)
00562 {
00563 return Value (QDateTime::currentDateTime ());
00564 }
00565
00566
00567 Value func_dayOfYear (valVector args, ValueCalc *calc, FuncExtra *)
00568 {
00569 Value date = func_date (args, calc, 0);
00570 if (date.isError()) return date;
00571 return Value (date.asDate().dayOfYear());
00572 }
00573
00574
00575 Value func_daysInMonth (valVector args, ValueCalc *calc, FuncExtra *)
00576 {
00577 int y = calc->conv()->asInteger (args[0]).asInteger();
00578 int m = calc->conv()->asInteger (args[1]).asInteger();
00579 QDate date (y, m, 1);
00580 return Value (date.daysInMonth());
00581 }
00582
00583
00584 Value func_isLeapYear (valVector args, ValueCalc *calc, FuncExtra *)
00585 {
00586 int y = calc->conv()->asInteger (args[0]).asInteger();
00587 return Value (QDate::leapYear (y));
00588 }
00589
00590
00591 Value func_daysInYear (valVector args, ValueCalc *calc, FuncExtra *)
00592 {
00593 int y = calc->conv()->asInteger (args[0]).asInteger();
00594 return Value (QDate::leapYear (y) ? 366 : 365);
00595 }
00596
00597
00598 Value func_weeksInYear (valVector args, ValueCalc *calc, FuncExtra *)
00599 {
00600 int y = calc->conv()->asInteger (args[0]).asInteger();
00601 QDate date (y, 12, 31);
00602 return Value (date.weekNumber ());
00603 }
00604
00605
00606 Value func_easterSunday (valVector args, ValueCalc *calc, FuncExtra *)
00607 {
00608 int nDay, nMonth;
00609 int nYear = calc->conv()->asInteger (args[0]).asInteger();
00610
00611
00612 int B,C,D,E,F,G,H,I,K,L,M,N,O;
00613 N = nYear % 19;
00614 B = int(nYear / 100);
00615 C = nYear % 100;
00616 D = int(B / 4);
00617 E = B % 4;
00618 F = int((B + 8) / 25);
00619 G = int((B - F + 1) / 3);
00620 H = (19 * N + B - D - G + 15) % 30;
00621 I = int(C / 4);
00622 K = C % 4;
00623 L = (32 + 2 * E + 2 * I - H - K) % 7;
00624 M = int((N + 11 * H + 22 * L) / 451);
00625 O = H + L - 7 * M + 114;
00626 nDay = O % 31 + 1;
00627 nMonth = int(O / 31);
00628
00629 return Value (QDate (nYear, nMonth, nDay));
00630 }
00631
00632
00633 Value func_isoWeekNum (valVector args, ValueCalc *calc, FuncExtra *)
00634 {
00635 QDate date = calc->conv()->asDate (args[0]).asDate();
00636 if (!date.isValid())
00637 return Value::errorVALUE();
00638
00639 return Value (date.weekNumber());
00640 }