PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - pdo_sqlite/sqlite/src - date.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 425
Code covered: 0.9 % Executed lines: 4
Legend: not executed executed

       1                 : /*
       2                 : ** 2003 October 31
       3                 : **
       4                 : ** The author disclaims copyright to this source code.  In place of
       5                 : ** a legal notice, here is a blessing:
       6                 : **
       7                 : **    May you do good and not evil.
       8                 : **    May you find forgiveness for yourself and forgive others.
       9                 : **    May you share freely, never taking more than you give.
      10                 : **
      11                 : *************************************************************************
      12                 : ** This file contains the C functions that implement date and time
      13                 : ** functions for SQLite.  
      14                 : **
      15                 : ** There is only one exported symbol in this file - the function
      16                 : ** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
      17                 : ** All other code has file scope.
      18                 : **
      19                 : ** $Id$
      20                 : **
      21                 : ** NOTES:
      22                 : **
      23                 : ** SQLite processes all times and dates as Julian Day numbers.  The
      24                 : ** dates and times are stored as the number of days since noon
      25                 : ** in Greenwich on November 24, 4714 B.C. according to the Gregorian
      26                 : ** calendar system.
      27                 : **
      28                 : ** 1970-01-01 00:00:00 is JD 2440587.5
      29                 : ** 2000-01-01 00:00:00 is JD 2451544.5
      30                 : **
      31                 : ** This implemention requires years to be expressed as a 4-digit number
      32                 : ** which means that only dates between 0000-01-01 and 9999-12-31 can
      33                 : ** be represented, even though julian day numbers allow a much wider
      34                 : ** range of dates.
      35                 : **
      36                 : ** The Gregorian calendar system is used for all dates and times,
      37                 : ** even those that predate the Gregorian calendar.  Historians usually
      38                 : ** use the Julian calendar for dates prior to 1582-10-15 and for some
      39                 : ** dates afterwards, depending on locale.  Beware of this difference.
      40                 : **
      41                 : ** The conversion algorithms are implemented based on descriptions
      42                 : ** in the following text:
      43                 : **
      44                 : **      Jean Meeus
      45                 : **      Astronomical Algorithms, 2nd Edition, 1998
      46                 : **      ISBM 0-943396-61-1
      47                 : **      Willmann-Bell, Inc
      48                 : **      Richmond, Virginia (USA)
      49                 : */
      50                 : #include "sqliteInt.h"
      51                 : #include "os.h"
      52                 : #include <ctype.h>
      53                 : #include <stdlib.h>
      54                 : #include <assert.h>
      55                 : #include <time.h>
      56                 : #ifndef PHP_WIN32
      57                 : #include "main/php_reentrancy.h"
      58                 : #endif
      59                 : 
      60                 : #ifndef SQLITE_OMIT_DATETIME_FUNCS
      61                 : 
      62                 : /*
      63                 : ** A structure for holding a single date and time.
      64                 : */
      65                 : typedef struct DateTime DateTime;
      66                 : struct DateTime {
      67                 :   double rJD;      /* The julian day number */
      68                 :   int Y, M, D;     /* Year, month, and day */
      69                 :   int h, m;        /* Hour and minutes */
      70                 :   int tz;          /* Timezone offset in minutes */
      71                 :   double s;        /* Seconds */
      72                 :   char validYMD;   /* True if Y,M,D are valid */
      73                 :   char validHMS;   /* True if h,m,s are valid */
      74                 :   char validJD;    /* True if rJD is valid */
      75                 :   char validTZ;    /* True if tz is valid */
      76                 : };
      77                 : 
      78                 : 
      79                 : /*
      80                 : ** Convert zDate into one or more integers.  Additional arguments
      81                 : ** come in groups of 5 as follows:
      82                 : **
      83                 : **       N       number of digits in the integer
      84                 : **       min     minimum allowed value of the integer
      85                 : **       max     maximum allowed value of the integer
      86                 : **       nextC   first character after the integer
      87                 : **       pVal    where to write the integers value.
      88                 : **
      89                 : ** Conversions continue until one with nextC==0 is encountered.
      90                 : ** The function returns the number of successful conversions.
      91                 : */
      92               0 : static int getDigits(const char *zDate, ...){
      93                 :   va_list ap;
      94                 :   int val;
      95                 :   int N;
      96                 :   int min;
      97                 :   int max;
      98                 :   int nextC;
      99                 :   int *pVal;
     100               0 :   int cnt = 0;
     101               0 :   va_start(ap, zDate);
     102                 :   do{
     103               0 :     N = va_arg(ap, int);
     104               0 :     min = va_arg(ap, int);
     105               0 :     max = va_arg(ap, int);
     106               0 :     nextC = va_arg(ap, int);
     107               0 :     pVal = va_arg(ap, int*);
     108               0 :     val = 0;
     109               0 :     while( N-- ){
     110               0 :       if( !isdigit(*(u8*)zDate) ){
     111               0 :         goto end_getDigits;
     112                 :       }
     113               0 :       val = val*10 + *zDate - '0';
     114               0 :       zDate++;
     115                 :     }
     116               0 :     if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){
     117                 :       goto end_getDigits;
     118                 :     }
     119               0 :     *pVal = val;
     120               0 :     zDate++;
     121               0 :     cnt++;
     122               0 :   }while( nextC );
     123               0 : end_getDigits:
     124               0 :   va_end(ap);
     125               0 :   return cnt;
     126                 : }
     127                 : 
     128                 : /*
     129                 : ** Read text from z[] and convert into a floating point number.  Return
     130                 : ** the number of digits converted.
     131                 : */
     132                 : #define getValue sqlite3AtoF
     133                 : 
     134                 : /*
     135                 : ** Parse a timezone extension on the end of a date-time.
     136                 : ** The extension is of the form:
     137                 : **
     138                 : **        (+/-)HH:MM
     139                 : **
     140                 : ** If the parse is successful, write the number of minutes
     141                 : ** of change in *pnMin and return 0.  If a parser error occurs,
     142                 : ** return 0.
     143                 : **
     144                 : ** A missing specifier is not considered an error.
     145                 : */
     146               0 : static int parseTimezone(const char *zDate, DateTime *p){
     147               0 :   int sgn = 0;
     148                 :   int nHr, nMn;
     149               0 :   while( isspace(*(u8*)zDate) ){ zDate++; }
     150               0 :   p->tz = 0;
     151               0 :   if( *zDate=='-' ){
     152               0 :     sgn = -1;
     153               0 :   }else if( *zDate=='+' ){
     154               0 :     sgn = +1;
     155                 :   }else{
     156               0 :     return *zDate!=0;
     157                 :   }
     158               0 :   zDate++;
     159               0 :   if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){
     160               0 :     return 1;
     161                 :   }
     162               0 :   zDate += 5;
     163               0 :   p->tz = sgn*(nMn + nHr*60);
     164               0 :   while( isspace(*(u8*)zDate) ){ zDate++; }
     165               0 :   return *zDate!=0;
     166                 : }
     167                 : 
     168                 : /*
     169                 : ** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF.
     170                 : ** The HH, MM, and SS must each be exactly 2 digits.  The
     171                 : ** fractional seconds FFFF can be one or more digits.
     172                 : **
     173                 : ** Return 1 if there is a parsing error and 0 on success.
     174                 : */
     175               0 : static int parseHhMmSs(const char *zDate, DateTime *p){
     176                 :   int h, m, s;
     177               0 :   double ms = 0.0;
     178               0 :   if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
     179               0 :     return 1;
     180                 :   }
     181               0 :   zDate += 5;
     182               0 :   if( *zDate==':' ){
     183               0 :     zDate++;
     184               0 :     if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
     185               0 :       return 1;
     186                 :     }
     187               0 :     zDate += 2;
     188               0 :     if( *zDate=='.' && isdigit((u8)zDate[1]) ){
     189               0 :       double rScale = 1.0;
     190               0 :       zDate++;
     191               0 :       while( isdigit(*(u8*)zDate) ){
     192               0 :         ms = ms*10.0 + *zDate - '0';
     193               0 :         rScale *= 10.0;
     194               0 :         zDate++;
     195                 :       }
     196               0 :       ms /= rScale;
     197                 :     }
     198                 :   }else{
     199               0 :     s = 0;
     200                 :   }
     201               0 :   p->validJD = 0;
     202               0 :   p->validHMS = 1;
     203               0 :   p->h = h;
     204               0 :   p->m = m;
     205               0 :   p->s = s + ms;
     206               0 :   if( parseTimezone(zDate, p) ) return 1;
     207               0 :   p->validTZ = p->tz!=0;
     208               0 :   return 0;
     209                 : }
     210                 : 
     211                 : /*
     212                 : ** Convert from YYYY-MM-DD HH:MM:SS to julian day.  We always assume
     213                 : ** that the YYYY-MM-DD is according to the Gregorian calendar.
     214                 : **
     215                 : ** Reference:  Meeus page 61
     216                 : */
     217               0 : static void computeJD(DateTime *p){
     218                 :   int Y, M, D, A, B, X1, X2;
     219                 : 
     220               0 :   if( p->validJD ) return;
     221               0 :   if( p->validYMD ){
     222               0 :     Y = p->Y;
     223               0 :     M = p->M;
     224               0 :     D = p->D;
     225                 :   }else{
     226               0 :     Y = 2000;  /* If no YMD specified, assume 2000-Jan-01 */
     227               0 :     M = 1;
     228               0 :     D = 1;
     229                 :   }
     230               0 :   if( M<=2 ){
     231               0 :     Y--;
     232               0 :     M += 12;
     233                 :   }
     234               0 :   A = Y/100;
     235               0 :   B = 2 - A + (A/4);
     236               0 :   X1 = 365.25*(Y+4716);
     237               0 :   X2 = 30.6001*(M+1);
     238               0 :   p->rJD = X1 + X2 + D + B - 1524.5;
     239               0 :   p->validJD = 1;
     240               0 :   if( p->validHMS ){
     241               0 :     p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0;
     242               0 :     if( p->validTZ ){
     243               0 :       p->rJD -= p->tz*60/86400.0;
     244               0 :       p->validYMD = 0;
     245               0 :       p->validHMS = 0;
     246               0 :       p->validTZ = 0;
     247                 :     }
     248                 :   }
     249                 : }
     250                 : 
     251                 : /*
     252                 : ** Parse dates of the form
     253                 : **
     254                 : **     YYYY-MM-DD HH:MM:SS.FFF
     255                 : **     YYYY-MM-DD HH:MM:SS
     256                 : **     YYYY-MM-DD HH:MM
     257                 : **     YYYY-MM-DD
     258                 : **
     259                 : ** Write the result into the DateTime structure and return 0
     260                 : ** on success and 1 if the input string is not a well-formed
     261                 : ** date.
     262                 : */
     263               0 : static int parseYyyyMmDd(const char *zDate, DateTime *p){
     264                 :   int Y, M, D, neg;
     265                 : 
     266               0 :   if( zDate[0]=='-' ){
     267               0 :     zDate++;
     268               0 :     neg = 1;
     269                 :   }else{
     270               0 :     neg = 0;
     271                 :   }
     272               0 :   if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){
     273               0 :     return 1;
     274                 :   }
     275               0 :   zDate += 10;
     276               0 :   while( isspace(*(u8*)zDate) || 'T'==*(u8*)zDate ){ zDate++; }
     277               0 :   if( parseHhMmSs(zDate, p)==0 ){
     278                 :     /* We got the time */
     279               0 :   }else if( *zDate==0 ){
     280               0 :     p->validHMS = 0;
     281                 :   }else{
     282               0 :     return 1;
     283                 :   }
     284               0 :   p->validJD = 0;
     285               0 :   p->validYMD = 1;
     286               0 :   p->Y = neg ? -Y : Y;
     287               0 :   p->M = M;
     288               0 :   p->D = D;
     289               0 :   if( p->validTZ ){
     290               0 :     computeJD(p);
     291                 :   }
     292               0 :   return 0;
     293                 : }
     294                 : 
     295                 : /*
     296                 : ** Attempt to parse the given string into a Julian Day Number.  Return
     297                 : ** the number of errors.
     298                 : **
     299                 : ** The following are acceptable forms for the input string:
     300                 : **
     301                 : **      YYYY-MM-DD HH:MM:SS.FFF  +/-HH:MM
     302                 : **      DDDD.DD 
     303                 : **      now
     304                 : **
     305                 : ** In the first form, the +/-HH:MM is always optional.  The fractional
     306                 : ** seconds extension (the ".FFF") is optional.  The seconds portion
     307                 : ** (":SS.FFF") is option.  The year and date can be omitted as long
     308                 : ** as there is a time string.  The time string can be omitted as long
     309                 : ** as there is a year and date.
     310                 : */
     311               0 : static int parseDateOrTime(const char *zDate, DateTime *p){
     312               0 :   memset(p, 0, sizeof(*p));
     313               0 :   if( parseYyyyMmDd(zDate,p)==0 ){
     314               0 :     return 0;
     315               0 :   }else if( parseHhMmSs(zDate, p)==0 ){
     316               0 :     return 0;
     317               0 :   }else if( sqlite3StrICmp(zDate,"now")==0){
     318                 :     double r;
     319               0 :     sqlite3OsCurrentTime(&r);
     320               0 :     p->rJD = r;
     321               0 :     p->validJD = 1;
     322               0 :     return 0;
     323               0 :   }else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){
     324               0 :     getValue(zDate, &p->rJD);
     325               0 :     p->validJD = 1;
     326               0 :     return 0;
     327                 :   }
     328               0 :   return 1;
     329                 : }
     330                 : 
     331                 : /*
     332                 : ** Compute the Year, Month, and Day from the julian day number.
     333                 : */
     334               0 : static void computeYMD(DateTime *p){
     335                 :   int Z, A, B, C, D, E, X1;
     336               0 :   if( p->validYMD ) return;
     337               0 :   if( !p->validJD ){
     338               0 :     p->Y = 2000;
     339               0 :     p->M = 1;
     340               0 :     p->D = 1;
     341                 :   }else{
     342               0 :     Z = p->rJD + 0.5;
     343               0 :     A = (Z - 1867216.25)/36524.25;
     344               0 :     A = Z + 1 + A - (A/4);
     345               0 :     B = A + 1524;
     346               0 :     C = (B - 122.1)/365.25;
     347               0 :     D = 365.25*C;
     348               0 :     E = (B-D)/30.6001;
     349               0 :     X1 = 30.6001*E;
     350               0 :     p->D = B - D - X1;
     351               0 :     p->M = E<14 ? E-1 : E-13;
     352               0 :     p->Y = p->M>2 ? C - 4716 : C - 4715;
     353                 :   }
     354               0 :   p->validYMD = 1;
     355                 : }
     356                 : 
     357                 : /*
     358                 : ** Compute the Hour, Minute, and Seconds from the julian day number.
     359                 : */
     360               0 : static void computeHMS(DateTime *p){
     361                 :   int Z, s;
     362               0 :   if( p->validHMS ) return;
     363               0 :   computeJD(p);
     364               0 :   Z = p->rJD + 0.5;
     365               0 :   s = (p->rJD + 0.5 - Z)*86400000.0 + 0.5;
     366               0 :   p->s = 0.001*s;
     367               0 :   s = p->s;
     368               0 :   p->s -= s;
     369               0 :   p->h = s/3600;
     370               0 :   s -= p->h*3600;
     371               0 :   p->m = s/60;
     372               0 :   p->s += s - p->m*60;
     373               0 :   p->validHMS = 1;
     374                 : }
     375                 : 
     376                 : /*
     377                 : ** Compute both YMD and HMS
     378                 : */
     379               0 : static void computeYMD_HMS(DateTime *p){
     380               0 :   computeYMD(p);
     381               0 :   computeHMS(p);
     382               0 : }
     383                 : 
     384                 : /*
     385                 : ** Clear the YMD and HMS and the TZ
     386                 : */
     387               0 : static void clearYMD_HMS_TZ(DateTime *p){
     388               0 :   p->validYMD = 0;
     389               0 :   p->validHMS = 0;
     390               0 :   p->validTZ = 0;
     391               0 : }
     392                 : 
     393                 : /*
     394                 : ** Compute the difference (in days) between localtime and UTC (a.k.a. GMT)
     395                 : ** for the time value p where p is in UTC.
     396                 : */
     397               0 : static double localtimeOffset(DateTime *p){
     398                 :   DateTime x, y;
     399                 :   time_t t;
     400                 :   struct tm *pTm, tmbuf;
     401               0 :   x = *p;
     402               0 :   computeYMD_HMS(&x);
     403               0 :   if( x.Y<1971 || x.Y>=2038 ){
     404               0 :     x.Y = 2000;
     405               0 :     x.M = 1;
     406               0 :     x.D = 1;
     407               0 :     x.h = 0;
     408               0 :     x.m = 0;
     409               0 :     x.s = 0.0;
     410                 :   } else {
     411               0 :     int s = x.s + 0.5;
     412               0 :     x.s = s;
     413                 :   }
     414               0 :   x.tz = 0;
     415               0 :   x.validJD = 0;
     416               0 :   computeJD(&x);
     417               0 :   t = (x.rJD-2440587.5)*86400.0 + 0.5;
     418               0 :   sqlite3OsEnterMutex();
     419               0 :   pTm = php_localtime_r(&t, &tmbuf);
     420               0 :   if (!pTm) {
     421               0 :           return 0;
     422                 :   }
     423               0 :   y.Y = pTm->tm_year + 1900;
     424               0 :   y.M = pTm->tm_mon + 1;
     425               0 :   y.D = pTm->tm_mday;
     426               0 :   y.h = pTm->tm_hour;
     427               0 :   y.m = pTm->tm_min;
     428               0 :   y.s = pTm->tm_sec;
     429               0 :   sqlite3OsLeaveMutex();
     430               0 :   y.validYMD = 1;
     431               0 :   y.validHMS = 1;
     432               0 :   y.validJD = 0;
     433               0 :   y.validTZ = 0;
     434               0 :   computeJD(&y);
     435               0 :   return y.rJD - x.rJD;
     436                 : }
     437                 : 
     438                 : /*
     439                 : ** Process a modifier to a date-time stamp.  The modifiers are
     440                 : ** as follows:
     441                 : **
     442                 : **     NNN days
     443                 : **     NNN hours
     444                 : **     NNN minutes
     445                 : **     NNN.NNNN seconds
     446                 : **     NNN months
     447                 : **     NNN years
     448                 : **     start of month
     449                 : **     start of year
     450                 : **     start of week
     451                 : **     start of day
     452                 : **     weekday N
     453                 : **     unixepoch
     454                 : **     localtime
     455                 : **     utc
     456                 : **
     457                 : ** Return 0 on success and 1 if there is any kind of error.
     458                 : */
     459               0 : static int parseModifier(const char *zMod, DateTime *p){
     460               0 :   int rc = 1;
     461                 :   int n;
     462                 :   double r;
     463                 :   char *z, zBuf[30];
     464               0 :   z = zBuf;
     465               0 :   for(n=0; n<sizeof(zBuf)-1 && zMod[n]; n++){
     466               0 :     z[n] = tolower(zMod[n]);
     467                 :   }
     468               0 :   z[n] = 0;
     469               0 :   switch( z[0] ){
     470                 :     case 'l': {
     471                 :       /*    localtime
     472                 :       **
     473                 :       ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
     474                 :       ** show local time.
     475                 :       */
     476               0 :       if( strcmp(z, "localtime")==0 ){
     477               0 :         computeJD(p);
     478               0 :         p->rJD += localtimeOffset(p);
     479               0 :         clearYMD_HMS_TZ(p);
     480               0 :         rc = 0;
     481                 :       }
     482               0 :       break;
     483                 :     }
     484                 :     case 'u': {
     485                 :       /*
     486                 :       **    unixepoch
     487                 :       **
     488                 :       ** Treat the current value of p->rJD as the number of
     489                 :       ** seconds since 1970.  Convert to a real julian day number.
     490                 :       */
     491               0 :       if( strcmp(z, "unixepoch")==0 && p->validJD ){
     492               0 :         p->rJD = p->rJD/86400.0 + 2440587.5;
     493               0 :         clearYMD_HMS_TZ(p);
     494               0 :         rc = 0;
     495               0 :       }else if( strcmp(z, "utc")==0 ){
     496                 :         double c1;
     497               0 :         computeJD(p);
     498               0 :         c1 = localtimeOffset(p);
     499               0 :         p->rJD -= c1;
     500               0 :         clearYMD_HMS_TZ(p);
     501               0 :         p->rJD += c1 - localtimeOffset(p);
     502               0 :         rc = 0;
     503                 :       }
     504               0 :       break;
     505                 :     }
     506                 :     case 'w': {
     507                 :       /*
     508                 :       **    weekday N
     509                 :       **
     510                 :       ** Move the date to the same time on the next occurrence of
     511                 :       ** weekday N where 0==Sunday, 1==Monday, and so forth.  If the
     512                 :       ** date is already on the appropriate weekday, this is a no-op.
     513                 :       */
     514               0 :       if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0
     515                 :                  && (n=r)==r && n>=0 && r<7 ){
     516                 :         int Z;
     517               0 :         computeYMD_HMS(p);
     518               0 :         p->validTZ = 0;
     519               0 :         p->validJD = 0;
     520               0 :         computeJD(p);
     521               0 :         Z = p->rJD + 1.5;
     522               0 :         Z %= 7;
     523               0 :         if( Z>n ) Z -= 7;
     524               0 :         p->rJD += n - Z;
     525               0 :         clearYMD_HMS_TZ(p);
     526               0 :         rc = 0;
     527                 :       }
     528               0 :       break;
     529                 :     }
     530                 :     case 's': {
     531                 :       /*
     532                 :       **    start of TTTTT
     533                 :       **
     534                 :       ** Move the date backwards to the beginning of the current day,
     535                 :       ** or month or year.
     536                 :       */
     537               0 :       if( strncmp(z, "start of ", 9)!=0 ) break;
     538               0 :       z += 9;
     539               0 :       computeYMD(p);
     540               0 :       p->validHMS = 1;
     541               0 :       p->h = p->m = 0;
     542               0 :       p->s = 0.0;
     543               0 :       p->validTZ = 0;
     544               0 :       p->validJD = 0;
     545               0 :       if( strcmp(z,"month")==0 ){
     546               0 :         p->D = 1;
     547               0 :         rc = 0;
     548               0 :       }else if( strcmp(z,"year")==0 ){
     549               0 :         computeYMD(p);
     550               0 :         p->M = 1;
     551               0 :         p->D = 1;
     552               0 :         rc = 0;
     553               0 :       }else if( strcmp(z,"day")==0 ){
     554               0 :         rc = 0;
     555                 :       }
     556               0 :       break;
     557                 :     }
     558                 :     case '+':
     559                 :     case '-':
     560                 :     case '0':
     561                 :     case '1':
     562                 :     case '2':
     563                 :     case '3':
     564                 :     case '4':
     565                 :     case '5':
     566                 :     case '6':
     567                 :     case '7':
     568                 :     case '8':
     569                 :     case '9': {
     570               0 :       n = getValue(z, &r);
     571                 :       assert( n>=1 );
     572               0 :       if( z[n]==':' ){
     573                 :         /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
     574                 :         ** specified number of hours, minutes, seconds, and fractional seconds
     575                 :         ** to the time.  The ".FFF" may be omitted.  The ":SS.FFF" may be
     576                 :         ** omitted.
     577                 :         */
     578               0 :         const char *z2 = z;
     579                 :         DateTime tx;
     580                 :         int day;
     581               0 :         if( !isdigit(*(u8*)z2) ) z2++;
     582               0 :         memset(&tx, 0, sizeof(tx));
     583               0 :         if( parseHhMmSs(z2, &tx) ) break;
     584               0 :         computeJD(&tx);
     585               0 :         tx.rJD -= 0.5;
     586               0 :         day = (int)tx.rJD;
     587               0 :         tx.rJD -= day;
     588               0 :         if( z[0]=='-' ) tx.rJD = -tx.rJD;
     589               0 :         computeJD(p);
     590               0 :         clearYMD_HMS_TZ(p);
     591               0 :         p->rJD += tx.rJD;
     592               0 :         rc = 0;
     593               0 :         break;
     594                 :       }
     595               0 :       z += n;
     596               0 :       while( isspace(*(u8*)z) ) z++;
     597               0 :       n = strlen(z);
     598               0 :       if( n>10 || n<3 ) break;
     599               0 :       if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
     600               0 :       computeJD(p);
     601               0 :       rc = 0;
     602               0 :       if( n==3 && strcmp(z,"day")==0 ){
     603               0 :         p->rJD += r;
     604               0 :       }else if( n==4 && strcmp(z,"hour")==0 ){
     605               0 :         p->rJD += r/24.0;
     606               0 :       }else if( n==6 && strcmp(z,"minute")==0 ){
     607               0 :         p->rJD += r/(24.0*60.0);
     608               0 :       }else if( n==6 && strcmp(z,"second")==0 ){
     609               0 :         p->rJD += r/(24.0*60.0*60.0);
     610               0 :       }else if( n==5 && strcmp(z,"month")==0 ){
     611                 :         int x, y;
     612               0 :         computeYMD_HMS(p);
     613               0 :         p->M += r;
     614               0 :         x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
     615               0 :         p->Y += x;
     616               0 :         p->M -= x*12;
     617               0 :         p->validJD = 0;
     618               0 :         computeJD(p);
     619               0 :         y = r;
     620               0 :         if( y!=r ){
     621               0 :           p->rJD += (r - y)*30.0;
     622                 :         }
     623               0 :       }else if( n==4 && strcmp(z,"year")==0 ){
     624               0 :         computeYMD_HMS(p);
     625               0 :         p->Y += r;
     626               0 :         p->validJD = 0;
     627               0 :         computeJD(p);
     628                 :       }else{
     629               0 :         rc = 1;
     630                 :       }
     631               0 :       clearYMD_HMS_TZ(p);
     632                 :       break;
     633                 :     }
     634                 :     default: {
     635                 :       break;
     636                 :     }
     637                 :   }
     638               0 :   return rc;
     639                 : }
     640                 : 
     641                 : /*
     642                 : ** Process time function arguments.  argv[0] is a date-time stamp.
     643                 : ** argv[1] and following are modifiers.  Parse them all and write
     644                 : ** the resulting time into the DateTime structure p.  Return 0
     645                 : ** on success and 1 if there are any errors.
     646                 : */
     647               0 : static int isDate(int argc, sqlite3_value **argv, DateTime *p){
     648                 :   int i;
     649               0 :   if( argc==0 ) return 1;
     650               0 :   if( SQLITE_NULL==sqlite3_value_type(argv[0]) || 
     651               0 :       parseDateOrTime((char*)sqlite3_value_text(argv[0]), p) ) return 1;
     652               0 :   for(i=1; i<argc; i++){
     653               0 :     if( SQLITE_NULL==sqlite3_value_type(argv[i]) || 
     654               0 :         parseModifier((char*)sqlite3_value_text(argv[i]), p) ) return 1;
     655                 :   }
     656               0 :   return 0;
     657                 : }
     658                 : 
     659                 : 
     660                 : /*
     661                 : ** The following routines implement the various date and time functions
     662                 : ** of SQLite.
     663                 : */
     664                 : 
     665                 : /*
     666                 : **    julianday( TIMESTRING, MOD, MOD, ...)
     667                 : **
     668                 : ** Return the julian day number of the date specified in the arguments
     669                 : */
     670                 : static void juliandayFunc(
     671                 :   sqlite3_context *context,
     672                 :   int argc,
     673                 :   sqlite3_value **argv
     674               0 : ){
     675                 :   DateTime x;
     676               0 :   if( isDate(argc, argv, &x)==0 ){
     677               0 :     computeJD(&x);
     678               0 :     sqlite3_result_double(context, x.rJD);
     679                 :   }
     680               0 : }
     681                 : 
     682                 : /*
     683                 : **    datetime( TIMESTRING, MOD, MOD, ...)
     684                 : **
     685                 : ** Return YYYY-MM-DD HH:MM:SS
     686                 : */
     687                 : static void datetimeFunc(
     688                 :   sqlite3_context *context,
     689                 :   int argc,
     690                 :   sqlite3_value **argv
     691               0 : ){
     692                 :   DateTime x;
     693               0 :   if( isDate(argc, argv, &x)==0 ){
     694                 :     char zBuf[100];
     695               0 :     computeYMD_HMS(&x);
     696               0 :     sprintf(zBuf, "%04d-%02d-%02d %02d:%02d:%02d",x.Y, x.M, x.D, x.h, x.m,
     697                 :            (int)(x.s));
     698               0 :     sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
     699                 :   }
     700               0 : }
     701                 : 
     702                 : /*
     703                 : **    time( TIMESTRING, MOD, MOD, ...)
     704                 : **
     705                 : ** Return HH:MM:SS
     706                 : */
     707                 : static void timeFunc(
     708                 :   sqlite3_context *context,
     709                 :   int argc,
     710                 :   sqlite3_value **argv
     711               0 : ){
     712                 :   DateTime x;
     713               0 :   if( isDate(argc, argv, &x)==0 ){
     714                 :     char zBuf[100];
     715               0 :     computeHMS(&x);
     716               0 :     sprintf(zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
     717               0 :     sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
     718                 :   }
     719               0 : }
     720                 : 
     721                 : /*
     722                 : **    date( TIMESTRING, MOD, MOD, ...)
     723                 : **
     724                 : ** Return YYYY-MM-DD
     725                 : */
     726                 : static void dateFunc(
     727                 :   sqlite3_context *context,
     728                 :   int argc,
     729                 :   sqlite3_value **argv
     730               0 : ){
     731                 :   DateTime x;
     732               0 :   if( isDate(argc, argv, &x)==0 ){
     733                 :     char zBuf[100];
     734               0 :     computeYMD(&x);
     735               0 :     sprintf(zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
     736               0 :     sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
     737                 :   }
     738               0 : }
     739                 : 
     740                 : /*
     741                 : **    strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
     742                 : **
     743                 : ** Return a string described by FORMAT.  Conversions as follows:
     744                 : **
     745                 : **   %d  day of month
     746                 : **   %f  ** fractional seconds  SS.SSS
     747                 : **   %H  hour 00-24
     748                 : **   %j  day of year 000-366
     749                 : **   %J  ** Julian day number
     750                 : **   %m  month 01-12
     751                 : **   %M  minute 00-59
     752                 : **   %s  seconds since 1970-01-01
     753                 : **   %S  seconds 00-59
     754                 : **   %w  day of week 0-6  sunday==0
     755                 : **   %W  week of year 00-53
     756                 : **   %Y  year 0000-9999
     757                 : **   %%  %
     758                 : */
     759                 : static void strftimeFunc(
     760                 :   sqlite3_context *context,
     761                 :   int argc,
     762                 :   sqlite3_value **argv
     763               0 : ){
     764                 :   DateTime x;
     765                 :   int n, i, j;
     766                 :   char *z;
     767               0 :   const char *zFmt = (const char*)sqlite3_value_text(argv[0]);
     768                 :   char zBuf[100];
     769               0 :   if( zFmt==0 || isDate(argc-1, argv+1, &x) ) return;
     770               0 :   for(i=0, n=1; zFmt[i]; i++, n++){
     771               0 :     if( zFmt[i]=='%' ){
     772               0 :       switch( zFmt[i+1] ){
     773                 :         case 'd':
     774                 :         case 'H':
     775                 :         case 'm':
     776                 :         case 'M':
     777                 :         case 'S':
     778                 :         case 'W':
     779               0 :           n++;
     780                 :           /* fall thru */
     781                 :         case 'w':
     782                 :         case '%':
     783               0 :           break;
     784                 :         case 'f':
     785               0 :           n += 8;
     786               0 :           break;
     787                 :         case 'j':
     788               0 :           n += 3;
     789               0 :           break;
     790                 :         case 'Y':
     791               0 :           n += 8;
     792               0 :           break;
     793                 :         case 's':
     794                 :         case 'J':
     795               0 :           n += 50;
     796               0 :           break;
     797                 :         default:
     798               0 :           return;  /* ERROR.  return a NULL */
     799                 :       }
     800               0 :       i++;
     801                 :     }
     802                 :   }
     803               0 :   if( n<sizeof(zBuf) ){
     804               0 :     z = zBuf;
     805                 :   }else{
     806               0 :     z = sqliteMalloc( n );
     807               0 :     if( z==0 ) return;
     808                 :   }
     809               0 :   computeJD(&x);
     810               0 :   computeYMD_HMS(&x);
     811               0 :   for(i=j=0; zFmt[i]; i++){
     812               0 :     if( zFmt[i]!='%' ){
     813               0 :       z[j++] = zFmt[i];
     814                 :     }else{
     815               0 :       i++;
     816               0 :       switch( zFmt[i] ){
     817               0 :         case 'd':  sprintf(&z[j],"%02d",x.D); j+=2; break;
     818                 :         case 'f': {
     819               0 :           double s = x.s;
     820               0 :           if( s>59.999 ) s = 59.999;
     821               0 :           sqlite3_snprintf(7, &z[j],"%06.3f", s);
     822               0 :           j += strlen(&z[j]);
     823               0 :           break;
     824                 :         }
     825               0 :         case 'H':  sprintf(&z[j],"%02d",x.h); j+=2; break;
     826                 :         case 'W': /* Fall thru */
     827                 :         case 'j': {
     828                 :           int nDay;             /* Number of days since 1st day of year */
     829               0 :           DateTime y = x;
     830               0 :           y.validJD = 0;
     831               0 :           y.M = 1;
     832               0 :           y.D = 1;
     833               0 :           computeJD(&y);
     834               0 :           nDay = x.rJD - y.rJD + 0.5;
     835               0 :           if( zFmt[i]=='W' ){
     836                 :             int wd;   /* 0=Monday, 1=Tuesday, ... 6=Sunday */
     837               0 :             wd = ((int)(x.rJD+0.5)) % 7;
     838               0 :             sprintf(&z[j],"%02d",(nDay+7-wd)/7);
     839               0 :             j += 2;
     840                 :           }else{
     841               0 :             sprintf(&z[j],"%03d",nDay+1);
     842               0 :             j += 3;
     843                 :           }
     844               0 :           break;
     845                 :         }
     846               0 :         case 'J':  sprintf(&z[j],"%.16g",x.rJD); j+=strlen(&z[j]); break;
     847               0 :         case 'm':  sprintf(&z[j],"%02d",x.M); j+=2; break;
     848               0 :         case 'M':  sprintf(&z[j],"%02d",x.m); j+=2; break;
     849                 :         case 's': {
     850               0 :           sprintf(&z[j],"%d",(int)((x.rJD-2440587.5)*86400.0 + 0.5));
     851               0 :           j += strlen(&z[j]);
     852               0 :           break;
     853                 :         }
     854               0 :         case 'S':  sprintf(&z[j],"%02d",(int)x.s); j+=2; break;
     855               0 :         case 'w':  z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break;
     856               0 :         case 'Y':  sprintf(&z[j],"%04d",x.Y); j+=strlen(&z[j]); break;
     857               0 :         case '%':  z[j++] = '%'; break;
     858                 :       }
     859                 :     }
     860                 :   }
     861               0 :   z[j] = 0;
     862               0 :   sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
     863               0 :   if( z!=zBuf ){
     864               0 :     sqliteFree(z);
     865                 :   }
     866                 : }
     867                 : 
     868                 : /*
     869                 : ** current_time()
     870                 : **
     871                 : ** This function returns the same value as time('now').
     872                 : */
     873                 : static void ctimeFunc(
     874                 :   sqlite3_context *context,
     875                 :   int argc,
     876                 :   sqlite3_value **argv
     877               0 : ){
     878               0 :   sqlite3_value *pVal = sqlite3ValueNew();
     879               0 :   if( pVal ){
     880               0 :     sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
     881               0 :     timeFunc(context, 1, &pVal);
     882               0 :     sqlite3ValueFree(pVal);
     883                 :   }
     884               0 : }
     885                 : 
     886                 : /*
     887                 : ** current_date()
     888                 : **
     889                 : ** This function returns the same value as date('now').
     890                 : */
     891                 : static void cdateFunc(
     892                 :   sqlite3_context *context,
     893                 :   int argc,
     894                 :   sqlite3_value **argv
     895               0 : ){
     896               0 :   sqlite3_value *pVal = sqlite3ValueNew();
     897               0 :   if( pVal ){
     898               0 :     sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
     899               0 :     dateFunc(context, 1, &pVal);
     900               0 :     sqlite3ValueFree(pVal);
     901                 :   }
     902               0 : }
     903                 : 
     904                 : /*
     905                 : ** current_timestamp()
     906                 : **
     907                 : ** This function returns the same value as datetime('now').
     908                 : */
     909                 : static void ctimestampFunc(
     910                 :   sqlite3_context *context,
     911                 :   int argc,
     912                 :   sqlite3_value **argv
     913               0 : ){
     914               0 :   sqlite3_value *pVal = sqlite3ValueNew();
     915               0 :   if( pVal ){
     916               0 :     sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
     917               0 :     datetimeFunc(context, 1, &pVal);
     918               0 :     sqlite3ValueFree(pVal);
     919                 :   }
     920               0 : }
     921                 : #endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
     922                 : 
     923                 : #ifdef SQLITE_OMIT_DATETIME_FUNCS
     924                 : /*
     925                 : ** If the library is compiled to omit the full-scale date and time
     926                 : ** handling (to get a smaller binary), the following minimal version
     927                 : ** of the functions current_time(), current_date() and current_timestamp()
     928                 : ** are included instead. This is to support column declarations that
     929                 : ** include "DEFAULT CURRENT_TIME" etc.
     930                 : **
     931                 : ** This function uses the C-library functions time(), gmtime()
     932                 : ** and strftime(). The format string to pass to strftime() is supplied
     933                 : ** as the user-data for the function.
     934                 : */
     935                 : static void currentTimeFunc(
     936                 :   sqlite3_context *context,
     937                 :   int argc,
     938                 :   sqlite3_value **argv
     939                 : ){
     940                 :   time_t t;
     941                 :   char *zFormat = (char *)sqlite3_user_data(context);
     942                 :   char zBuf[20];
     943                 : 
     944                 :   time(&t);
     945                 : #ifdef SQLITE_TEST
     946                 :   {
     947                 :     extern int sqlite3_current_time;  /* See os_XXX.c */
     948                 :     if( sqlite3_current_time ){
     949                 :       t = sqlite3_current_time;
     950                 :     }
     951                 :   }
     952                 : #endif
     953                 : 
     954                 : #ifdef HAVE_GMTIME_R
     955                 :   {
     956                 :     struct tm sNow;
     957                 :     gmtime_r(&t, &sNow);
     958                 :     strftime(zBuf, 20, zFormat, &sNow);
     959                 :   }
     960                 : #else
     961                 :   {
     962                 :     struct tm *pTm;
     963                 :     sqlite3OsEnterMutex();
     964                 :     pTm = gmtime(&t);
     965                 :     strftime(zBuf, 20, zFormat, pTm);
     966                 :     sqlite3OsLeaveMutex();
     967                 :   }
     968                 : #endif
     969                 : 
     970                 :   sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
     971                 : }
     972                 : #endif
     973                 : 
     974                 : /*
     975                 : ** This function registered all of the above C functions as SQL
     976                 : ** functions.  This should be the only routine in this file with
     977                 : ** external linkage.
     978                 : */
     979             130 : void sqlite3RegisterDateTimeFunctions(sqlite3 *db){
     980                 : #ifndef SQLITE_OMIT_DATETIME_FUNCS
     981                 :   static const struct {
     982                 :      char *zName;
     983                 :      int nArg;
     984                 :      void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
     985                 :   } aFuncs[] = {
     986                 :     { "julianday", -1, juliandayFunc   },
     987                 :     { "date",      -1, dateFunc        },
     988                 :     { "time",      -1, timeFunc        },
     989                 :     { "datetime",  -1, datetimeFunc    },
     990                 :     { "strftime",  -1, strftimeFunc    },
     991                 :     { "current_time",       0, ctimeFunc      },
     992                 :     { "current_timestamp",  0, ctimestampFunc },
     993                 :     { "current_date",       0, cdateFunc      },
     994                 :   };
     995                 :   int i;
     996                 : 
     997            1170 :   for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
     998            1040 :     sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
     999                 :         SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
    1000                 :   }
    1001                 : #else
    1002                 :   static const struct {
    1003                 :      char *zName;
    1004                 :      char *zFormat;
    1005                 :   } aFuncs[] = {
    1006                 :     { "current_time", "%H:%M:%S" },
    1007                 :     { "current_date", "%Y-%m-%d" },
    1008                 :     { "current_timestamp", "%Y-%m-%d %H:%M:%S" }
    1009                 :   };
    1010                 :   int i;
    1011                 : 
    1012                 :   for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
    1013                 :     sqlite3CreateFunc(db, aFuncs[i].zName, 0, SQLITE_UTF8, 
    1014                 :         aFuncs[i].zFormat, currentTimeFunc, 0, 0);
    1015                 :   }
    1016                 : #endif
    1017             130 : }

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:17 +0000 (5 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.