00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050 #include "os.h"
00051 #include "sqliteInt.h"
00052 #include <ctype.h>
00053 #include <stdlib.h>
00054 #include <assert.h>
00055 #include <time.h>
00056
00057 #ifndef SQLITE_OMIT_DATETIME_FUNCS
00058
00059
00060
00061
00062 typedef struct DateTime DateTime;
00063 struct DateTime {
00064 double rJD;
00065 int Y, M, D;
00066 int h, m;
00067 int tz;
00068 double s;
00069 char validYMD;
00070 char validHMS;
00071 char validJD;
00072 char validTZ;
00073 };
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 static int getDigits(const char *zDate, ...){
00090 va_list ap;
00091 int val;
00092 int N;
00093 int min;
00094 int max;
00095 int nextC;
00096 int *pVal;
00097 int cnt = 0;
00098 va_start(ap, zDate);
00099 do{
00100 N = va_arg(ap, int);
00101 min = va_arg(ap, int);
00102 max = va_arg(ap, int);
00103 nextC = va_arg(ap, int);
00104 pVal = va_arg(ap, int*);
00105 val = 0;
00106 while( N-- ){
00107 if( !isdigit(*zDate) ){
00108 return cnt;
00109 }
00110 val = val*10 + *zDate - '0';
00111 zDate++;
00112 }
00113 if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){
00114 return cnt;
00115 }
00116 *pVal = val;
00117 zDate++;
00118 cnt++;
00119 }while( nextC );
00120 return cnt;
00121 }
00122
00123
00124
00125
00126
00127 static int getValue(const char *z, double *pR){
00128 const char *zEnd;
00129 *pR = sqliteAtoF(z, &zEnd);
00130 return zEnd - z;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 static int parseTimezone(const char *zDate, DateTime *p){
00146 int sgn = 0;
00147 int nHr, nMn;
00148 while( isspace(*zDate) ){ zDate++; }
00149 p->tz = 0;
00150 if( *zDate=='-' ){
00151 sgn = -1;
00152 }else if( *zDate=='+' ){
00153 sgn = +1;
00154 }else{
00155 return *zDate!=0;
00156 }
00157 zDate++;
00158 if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){
00159 return 1;
00160 }
00161 zDate += 5;
00162 p->tz = sgn*(nMn + nHr*60);
00163 while( isspace(*zDate) ){ zDate++; }
00164 return *zDate!=0;
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174 static int parseHhMmSs(const char *zDate, DateTime *p){
00175 int h, m, s;
00176 double ms = 0.0;
00177 if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
00178 return 1;
00179 }
00180 zDate += 5;
00181 if( *zDate==':' ){
00182 zDate++;
00183 if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
00184 return 1;
00185 }
00186 zDate += 2;
00187 if( *zDate=='.' && isdigit(zDate[1]) ){
00188 double rScale = 1.0;
00189 zDate++;
00190 while( isdigit(*zDate) ){
00191 ms = ms*10.0 + *zDate - '0';
00192 rScale *= 10.0;
00193 zDate++;
00194 }
00195 ms /= rScale;
00196 }
00197 }else{
00198 s = 0;
00199 }
00200 p->validJD = 0;
00201 p->validHMS = 1;
00202 p->h = h;
00203 p->m = m;
00204 p->s = s + ms;
00205 if( parseTimezone(zDate, p) ) return 1;
00206 p->validTZ = p->tz!=0;
00207 return 0;
00208 }
00209
00210
00211
00212
00213
00214
00215
00216 static void computeJD(DateTime *p){
00217 int Y, M, D, A, B, X1, X2;
00218
00219 if( p->validJD ) return;
00220 if( p->validYMD ){
00221 Y = p->Y;
00222 M = p->M;
00223 D = p->D;
00224 }else{
00225 Y = 2000;
00226 M = 1;
00227 D = 1;
00228 }
00229 if( M<=2 ){
00230 Y--;
00231 M += 12;
00232 }
00233 A = Y/100;
00234 B = 2 - A + (A/4);
00235 X1 = 365.25*(Y+4716);
00236 X2 = 30.6001*(M+1);
00237 p->rJD = X1 + X2 + D + B - 1524.5;
00238 p->validJD = 1;
00239 p->validYMD = 0;
00240 if( p->validHMS ){
00241 p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0;
00242 if( p->validTZ ){
00243 p->rJD += p->tz*60/86400.0;
00244 p->validHMS = 0;
00245 p->validTZ = 0;
00246 }
00247 }
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 static int parseYyyyMmDd(const char *zDate, DateTime *p){
00263 int Y, M, D, neg;
00264
00265 if( zDate[0]=='-' ){
00266 zDate++;
00267 neg = 1;
00268 }else{
00269 neg = 0;
00270 }
00271 if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){
00272 return 1;
00273 }
00274 zDate += 10;
00275 while( isspace(*zDate) ){ zDate++; }
00276 if( parseHhMmSs(zDate, p)==0 ){
00277
00278 }else if( *zDate==0 ){
00279 p->validHMS = 0;
00280 }else{
00281 return 1;
00282 }
00283 p->validJD = 0;
00284 p->validYMD = 1;
00285 p->Y = neg ? -Y : Y;
00286 p->M = M;
00287 p->D = D;
00288 if( p->validTZ ){
00289 computeJD(p);
00290 }
00291 return 0;
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310 static int parseDateOrTime(const char *zDate, DateTime *p){
00311 memset(p, 0, sizeof(*p));
00312 if( parseYyyyMmDd(zDate,p)==0 ){
00313 return 0;
00314 }else if( parseHhMmSs(zDate, p)==0 ){
00315 return 0;
00316 }else if( sqliteStrICmp(zDate,"now")==0){
00317 double r;
00318 if( sqliteOsCurrentTime(&r)==0 ){
00319 p->rJD = r;
00320 p->validJD = 1;
00321 return 0;
00322 }
00323 return 1;
00324 }else if( sqliteIsNumber(zDate) ){
00325 p->rJD = sqliteAtoF(zDate, 0);
00326 p->validJD = 1;
00327 return 0;
00328 }
00329 return 1;
00330 }
00331
00332
00333
00334
00335 static void computeYMD(DateTime *p){
00336 int Z, A, B, C, D, E, X1;
00337 if( p->validYMD ) return;
00338 if( !p->validJD ){
00339 p->Y = 2000;
00340 p->M = 1;
00341 p->D = 1;
00342 }else{
00343 Z = p->rJD + 0.5;
00344 A = (Z - 1867216.25)/36524.25;
00345 A = Z + 1 + A - (A/4);
00346 B = A + 1524;
00347 C = (B - 122.1)/365.25;
00348 D = 365.25*C;
00349 E = (B-D)/30.6001;
00350 X1 = 30.6001*E;
00351 p->D = B - D - X1;
00352 p->M = E<14 ? E-1 : E-13;
00353 p->Y = p->M>2 ? C - 4716 : C - 4715;
00354 }
00355 p->validYMD = 1;
00356 }
00357
00358
00359
00360
00361 static void computeHMS(DateTime *p){
00362 int Z, s;
00363 if( p->validHMS ) return;
00364 Z = p->rJD + 0.5;
00365 s = (p->rJD + 0.5 - Z)*86400000.0 + 0.5;
00366 p->s = 0.001*s;
00367 s = p->s;
00368 p->s -= s;
00369 p->h = s/3600;
00370 s -= p->h*3600;
00371 p->m = s/60;
00372 p->s += s - p->m*60;
00373 p->validHMS = 1;
00374 }
00375
00376
00377
00378
00379 static void computeYMD_HMS(DateTime *p){
00380 computeYMD(p);
00381 computeHMS(p);
00382 }
00383
00384
00385
00386
00387 static void clearYMD_HMS_TZ(DateTime *p){
00388 p->validYMD = 0;
00389 p->validHMS = 0;
00390 p->validTZ = 0;
00391 }
00392
00393
00394
00395
00396
00397 static double localtimeOffset(DateTime *p){
00398 DateTime x, y;
00399 time_t t;
00400 struct tm *pTm;
00401 x = *p;
00402 computeYMD_HMS(&x);
00403 if( x.Y<1971 || x.Y>=2038 ){
00404 x.Y = 2000;
00405 x.M = 1;
00406 x.D = 1;
00407 x.h = 0;
00408 x.m = 0;
00409 x.s = 0.0;
00410 } else {
00411 int s = x.s + 0.5;
00412 x.s = s;
00413 }
00414 x.tz = 0;
00415 x.validJD = 0;
00416 computeJD(&x);
00417 t = (x.rJD-2440587.5)*86400.0 + 0.5;
00418 sqliteOsEnterMutex();
00419 pTm = localtime(&t);
00420 y.Y = pTm->tm_year + 1900;
00421 y.M = pTm->tm_mon + 1;
00422 y.D = pTm->tm_mday;
00423 y.h = pTm->tm_hour;
00424 y.m = pTm->tm_min;
00425 y.s = pTm->tm_sec;
00426 sqliteOsLeaveMutex();
00427 y.validYMD = 1;
00428 y.validHMS = 1;
00429 y.validJD = 0;
00430 y.validTZ = 0;
00431 computeJD(&y);
00432 return y.rJD - x.rJD;
00433 }
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456 static int parseModifier(const char *zMod, DateTime *p){
00457 int rc = 1;
00458 int n;
00459 double r;
00460 char *z, zBuf[30];
00461 z = zBuf;
00462 for(n=0; n<sizeof(zBuf)-1 && zMod[n]; n++){
00463 z[n] = tolower(zMod[n]);
00464 }
00465 z[n] = 0;
00466 switch( z[0] ){
00467 case 'l': {
00468
00469
00470
00471
00472
00473 if( strcmp(z, "localtime")==0 ){
00474 computeJD(p);
00475 p->rJD += localtimeOffset(p);
00476 clearYMD_HMS_TZ(p);
00477 rc = 0;
00478 }
00479 break;
00480 }
00481 case 'u': {
00482
00483
00484
00485
00486
00487
00488 if( strcmp(z, "unixepoch")==0 && p->validJD ){
00489 p->rJD = p->rJD/86400.0 + 2440587.5;
00490 clearYMD_HMS_TZ(p);
00491 rc = 0;
00492 }else if( strcmp(z, "utc")==0 ){
00493 double c1;
00494 computeJD(p);
00495 c1 = localtimeOffset(p);
00496 p->rJD -= c1;
00497 clearYMD_HMS_TZ(p);
00498 p->rJD += c1 - localtimeOffset(p);
00499 rc = 0;
00500 }
00501 break;
00502 }
00503 case 'w': {
00504
00505
00506
00507
00508
00509
00510
00511 if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0
00512 && (n=r)==r && n>=0 && r<7 ){
00513 int Z;
00514 computeYMD_HMS(p);
00515 p->validTZ = 0;
00516 p->validJD = 0;
00517 computeJD(p);
00518 Z = p->rJD + 1.5;
00519 Z %= 7;
00520 if( Z>n ) Z -= 7;
00521 p->rJD += n - Z;
00522 clearYMD_HMS_TZ(p);
00523 rc = 0;
00524 }
00525 break;
00526 }
00527 case 's': {
00528
00529
00530
00531
00532
00533
00534 if( strncmp(z, "start of ", 9)!=0 ) break;
00535 z += 9;
00536 computeYMD(p);
00537 p->validHMS = 1;
00538 p->h = p->m = 0;
00539 p->s = 0.0;
00540 p->validTZ = 0;
00541 p->validJD = 0;
00542 if( strcmp(z,"month")==0 ){
00543 p->D = 1;
00544 rc = 0;
00545 }else if( strcmp(z,"year")==0 ){
00546 computeYMD(p);
00547 p->M = 1;
00548 p->D = 1;
00549 rc = 0;
00550 }else if( strcmp(z,"day")==0 ){
00551 rc = 0;
00552 }
00553 break;
00554 }
00555 case '+':
00556 case '-':
00557 case '0':
00558 case '1':
00559 case '2':
00560 case '3':
00561 case '4':
00562 case '5':
00563 case '6':
00564 case '7':
00565 case '8':
00566 case '9': {
00567 n = getValue(z, &r);
00568 if( n<=0 ) break;
00569 if( z[n]==':' ){
00570
00571
00572
00573
00574
00575 const char *z2 = z;
00576 DateTime tx;
00577 int day;
00578 if( !isdigit(*z2) ) z2++;
00579 memset(&tx, 0, sizeof(tx));
00580 if( parseHhMmSs(z2, &tx) ) break;
00581 computeJD(&tx);
00582 tx.rJD -= 0.5;
00583 day = (int)tx.rJD;
00584 tx.rJD -= day;
00585 if( z[0]=='-' ) tx.rJD = -tx.rJD;
00586 computeJD(p);
00587 clearYMD_HMS_TZ(p);
00588 p->rJD += tx.rJD;
00589 rc = 0;
00590 break;
00591 }
00592 z += n;
00593 while( isspace(z[0]) ) z++;
00594 n = strlen(z);
00595 if( n>10 || n<3 ) break;
00596 if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
00597 computeJD(p);
00598 rc = 0;
00599 if( n==3 && strcmp(z,"day")==0 ){
00600 p->rJD += r;
00601 }else if( n==4 && strcmp(z,"hour")==0 ){
00602 p->rJD += r/24.0;
00603 }else if( n==6 && strcmp(z,"minute")==0 ){
00604 p->rJD += r/(24.0*60.0);
00605 }else if( n==6 && strcmp(z,"second")==0 ){
00606 p->rJD += r/(24.0*60.0*60.0);
00607 }else if( n==5 && strcmp(z,"month")==0 ){
00608 int x, y;
00609 computeYMD_HMS(p);
00610 p->M += r;
00611 x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
00612 p->Y += x;
00613 p->M -= x*12;
00614 p->validJD = 0;
00615 computeJD(p);
00616 y = r;
00617 if( y!=r ){
00618 p->rJD += (r - y)*30.0;
00619 }
00620 }else if( n==4 && strcmp(z,"year")==0 ){
00621 computeYMD_HMS(p);
00622 p->Y += r;
00623 p->validJD = 0;
00624 computeJD(p);
00625 }else{
00626 rc = 1;
00627 }
00628 clearYMD_HMS_TZ(p);
00629 break;
00630 }
00631 default: {
00632 break;
00633 }
00634 }
00635 return rc;
00636 }
00637
00638
00639
00640
00641
00642
00643
00644 static int isDate(int argc, const char **argv, DateTime *p){
00645 int i;
00646 if( argc==0 ) return 1;
00647 if( argv[0]==0 || parseDateOrTime(argv[0], p) ) return 1;
00648 for(i=1; i<argc; i++){
00649 if( argv[i]==0 || parseModifier(argv[i], p) ) return 1;
00650 }
00651 return 0;
00652 }
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665 static void juliandayFunc(sqlite_func *context, int argc, const char **argv){
00666 DateTime x;
00667 if( isDate(argc, argv, &x)==0 ){
00668 computeJD(&x);
00669 sqlite_set_result_double(context, x.rJD);
00670 }
00671 }
00672
00673
00674
00675
00676
00677
00678 static void datetimeFunc(sqlite_func *context, int argc, const char **argv){
00679 DateTime x;
00680 if( isDate(argc, argv, &x)==0 ){
00681 char zBuf[100];
00682 computeYMD_HMS(&x);
00683 sprintf(zBuf, "%04d-%02d-%02d %02d:%02d:%02d",x.Y, x.M, x.D, x.h, x.m,
00684 (int)(x.s));
00685 sqlite_set_result_string(context, zBuf, -1);
00686 }
00687 }
00688
00689
00690
00691
00692
00693
00694 static void timeFunc(sqlite_func *context, int argc, const char **argv){
00695 DateTime x;
00696 if( isDate(argc, argv, &x)==0 ){
00697 char zBuf[100];
00698 computeHMS(&x);
00699 sprintf(zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
00700 sqlite_set_result_string(context, zBuf, -1);
00701 }
00702 }
00703
00704
00705
00706
00707
00708
00709 static void dateFunc(sqlite_func *context, int argc, const char **argv){
00710 DateTime x;
00711 if( isDate(argc, argv, &x)==0 ){
00712 char zBuf[100];
00713 computeYMD(&x);
00714 sprintf(zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
00715 sqlite_set_result_string(context, zBuf, -1);
00716 }
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738 static void strftimeFunc(sqlite_func *context, int argc, const char **argv){
00739 DateTime x;
00740 int n, i, j;
00741 char *z;
00742 const char *zFmt = argv[0];
00743 char zBuf[100];
00744 if( argv[0]==0 || isDate(argc-1, argv+1, &x) ) return;
00745 for(i=0, n=1; zFmt[i]; i++, n++){
00746 if( zFmt[i]=='%' ){
00747 switch( zFmt[i+1] ){
00748 case 'd':
00749 case 'H':
00750 case 'm':
00751 case 'M':
00752 case 'S':
00753 case 'W':
00754 n++;
00755
00756 case 'w':
00757 case '%':
00758 break;
00759 case 'f':
00760 n += 8;
00761 break;
00762 case 'j':
00763 n += 3;
00764 break;
00765 case 'Y':
00766 n += 8;
00767 break;
00768 case 's':
00769 case 'J':
00770 n += 50;
00771 break;
00772 default:
00773 return;
00774 }
00775 i++;
00776 }
00777 }
00778 if( n<sizeof(zBuf) ){
00779 z = zBuf;
00780 }else{
00781 z = sqliteMalloc( n );
00782 if( z==0 ) return;
00783 }
00784 computeJD(&x);
00785 computeYMD_HMS(&x);
00786 for(i=j=0; zFmt[i]; i++){
00787 if( zFmt[i]!='%' ){
00788 z[j++] = zFmt[i];
00789 }else{
00790 i++;
00791 switch( zFmt[i] ){
00792 case 'd': sprintf(&z[j],"%02d",x.D); j+=2; break;
00793 case 'f': {
00794 int s = x.s;
00795 int ms = (x.s - s)*1000.0;
00796 sprintf(&z[j],"%02d.%03d",s,ms);
00797 j += strlen(&z[j]);
00798 break;
00799 }
00800 case 'H': sprintf(&z[j],"%02d",x.h); j+=2; break;
00801 case 'W':
00802 case 'j': {
00803 int n;
00804 DateTime y = x;
00805 y.validJD = 0;
00806 y.M = 1;
00807 y.D = 1;
00808 computeJD(&y);
00809 n = x.rJD - y.rJD;
00810 if( zFmt[i]=='W' ){
00811 int wd;
00812 wd = ((int)(x.rJD+0.5)) % 7;
00813 sprintf(&z[j],"%02d",(n+7-wd)/7);
00814 j += 2;
00815 }else{
00816 sprintf(&z[j],"%03d",n+1);
00817 j += 3;
00818 }
00819 break;
00820 }
00821 case 'J': sprintf(&z[j],"%.16g",x.rJD); j+=strlen(&z[j]); break;
00822 case 'm': sprintf(&z[j],"%02d",x.M); j+=2; break;
00823 case 'M': sprintf(&z[j],"%02d",x.m); j+=2; break;
00824 case 's': {
00825 sprintf(&z[j],"%d",(int)((x.rJD-2440587.5)*86400.0 + 0.5));
00826 j += strlen(&z[j]);
00827 break;
00828 }
00829 case 'S': sprintf(&z[j],"%02d",(int)(x.s+0.5)); j+=2; break;
00830 case 'w': z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break;
00831 case 'Y': sprintf(&z[j],"%04d",x.Y); j+=strlen(&z[j]); break;
00832 case '%': z[j++] = '%'; break;
00833 }
00834 }
00835 }
00836 z[j] = 0;
00837 sqlite_set_result_string(context, z, -1);
00838 if( z!=zBuf ){
00839 sqliteFree(z);
00840 }
00841 }
00842
00843
00844 #endif
00845
00846
00847
00848
00849
00850
00851 void sqliteRegisterDateTimeFunctions(sqlite *db){
00852 #ifndef SQLITE_OMIT_DATETIME_FUNCS
00853 static struct {
00854 char *zName;
00855 int nArg;
00856 int dataType;
00857 void (*xFunc)(sqlite_func*,int,const char**);
00858 } aFuncs[] = {
00859 { "julianday", -1, SQLITE_NUMERIC, juliandayFunc },
00860 { "date", -1, SQLITE_TEXT, dateFunc },
00861 { "time", -1, SQLITE_TEXT, timeFunc },
00862 { "datetime", -1, SQLITE_TEXT, datetimeFunc },
00863 { "strftime", -1, SQLITE_TEXT, strftimeFunc },
00864 };
00865 int i;
00866
00867 for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
00868 sqlite_create_function(db, aFuncs[i].zName,
00869 aFuncs[i].nArg, aFuncs[i].xFunc, 0);
00870 if( aFuncs[i].xFunc ){
00871 sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType);
00872 }
00873 }
00874 #endif
00875 }