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 - sqlite/libsqlite/src - date.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 407
Code covered: 1.5 % Executed lines: 6
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                 : ** sqliteRegisterDateTimeFunctions() found at the bottom of the file.
      17                 : ** All other code has file scope.
      18                 : **
      19                 : ** $Id: date.c 278364 2009-04-07 11:45:50Z kalle $
      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 "os.h"
      51                 : #include "sqliteInt.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(*zDate) ){
     111               0 :         return cnt;
     112                 :       }
     113               0 :       val = val*10 + *zDate - '0';
     114               0 :       zDate++;
     115                 :     }
     116               0 :     if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){
     117               0 :       return cnt;
     118                 :     }
     119               0 :     *pVal = val;
     120               0 :     zDate++;
     121               0 :     cnt++;
     122               0 :   }while( nextC );
     123               0 :   return cnt;
     124                 : }
     125                 : 
     126                 : /*
     127                 : ** Read text from z[] and convert into a floating point number.  Return
     128                 : ** the number of digits converted.
     129                 : */
     130               0 : static int getValue(const char *z, double *pR){
     131                 :   const char *zEnd;
     132               0 :   *pR = sqliteAtoF(z, &zEnd);
     133               0 :   return zEnd - z;
     134                 : }
     135                 : 
     136                 : /*
     137                 : ** Parse a timezone extension on the end of a date-time.
     138                 : ** The extension is of the form:
     139                 : **
     140                 : **        (+/-)HH:MM
     141                 : **
     142                 : ** If the parse is successful, write the number of minutes
     143                 : ** of change in *pnMin and return 0.  If a parser error occurs,
     144                 : ** return 0.
     145                 : **
     146                 : ** A missing specifier is not considered an error.
     147                 : */
     148               0 : static int parseTimezone(const char *zDate, DateTime *p){
     149               0 :   int sgn = 0;
     150                 :   int nHr, nMn;
     151               0 :   while( isspace(*zDate) ){ zDate++; }
     152               0 :   p->tz = 0;
     153               0 :   if( *zDate=='-' ){
     154               0 :     sgn = -1;
     155               0 :   }else if( *zDate=='+' ){
     156               0 :     sgn = +1;
     157                 :   }else{
     158               0 :     return *zDate!=0;
     159                 :   }
     160               0 :   zDate++;
     161               0 :   if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){
     162               0 :     return 1;
     163                 :   }
     164               0 :   zDate += 5;
     165               0 :   p->tz = sgn*(nMn + nHr*60);
     166               0 :   while( isspace(*zDate) ){ zDate++; }
     167               0 :   return *zDate!=0;
     168                 : }
     169                 : 
     170                 : /*
     171                 : ** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF.
     172                 : ** The HH, MM, and SS must each be exactly 2 digits.  The
     173                 : ** fractional seconds FFFF can be one or more digits.
     174                 : **
     175                 : ** Return 1 if there is a parsing error and 0 on success.
     176                 : */
     177               0 : static int parseHhMmSs(const char *zDate, DateTime *p){
     178                 :   int h, m, s;
     179               0 :   double ms = 0.0;
     180               0 :   if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
     181               0 :     return 1;
     182                 :   }
     183               0 :   zDate += 5;
     184               0 :   if( *zDate==':' ){
     185               0 :     zDate++;
     186               0 :     if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
     187               0 :       return 1;
     188                 :     }
     189               0 :     zDate += 2;
     190               0 :     if( *zDate=='.' && isdigit(zDate[1]) ){
     191               0 :       double rScale = 1.0;
     192               0 :       zDate++;
     193               0 :       while( isdigit(*zDate) ){
     194               0 :         ms = ms*10.0 + *zDate - '0';
     195               0 :         rScale *= 10.0;
     196               0 :         zDate++;
     197                 :       }
     198               0 :       ms /= rScale;
     199                 :     }
     200                 :   }else{
     201               0 :     s = 0;
     202                 :   }
     203               0 :   p->validJD = 0;
     204               0 :   p->validHMS = 1;
     205               0 :   p->h = h;
     206               0 :   p->m = m;
     207               0 :   p->s = s + ms;
     208               0 :   if( parseTimezone(zDate, p) ) return 1;
     209               0 :   p->validTZ = p->tz!=0;
     210               0 :   return 0;
     211                 : }
     212                 : 
     213                 : /*
     214                 : ** Convert from YYYY-MM-DD HH:MM:SS to julian day.  We always assume
     215                 : ** that the YYYY-MM-DD is according to the Gregorian calendar.
     216                 : **
     217                 : ** Reference:  Meeus page 61
     218                 : */
     219               0 : static void computeJD(DateTime *p){
     220                 :   int Y, M, D, A, B, X1, X2;
     221                 : 
     222               0 :   if( p->validJD ) return;
     223               0 :   if( p->validYMD ){
     224               0 :     Y = p->Y;
     225               0 :     M = p->M;
     226               0 :     D = p->D;
     227                 :   }else{
     228               0 :     Y = 2000;  /* If no YMD specified, assume 2000-Jan-01 */
     229               0 :     M = 1;
     230               0 :     D = 1;
     231                 :   }
     232               0 :   if( M<=2 ){
     233               0 :     Y--;
     234               0 :     M += 12;
     235                 :   }
     236               0 :   A = Y/100;
     237               0 :   B = 2 - A + (A/4);
     238               0 :   X1 = 365.25*(Y+4716);
     239               0 :   X2 = 30.6001*(M+1);
     240               0 :   p->rJD = X1 + X2 + D + B - 1524.5;
     241               0 :   p->validJD = 1;
     242               0 :   p->validYMD = 0;
     243               0 :   if( p->validHMS ){
     244               0 :     p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0;
     245               0 :     if( p->validTZ ){
     246               0 :       p->rJD += p->tz*60/86400.0;
     247               0 :       p->validHMS = 0;
     248               0 :       p->validTZ = 0;
     249                 :     }
     250                 :   }
     251                 : }
     252                 : 
     253                 : /*
     254                 : ** Parse dates of the form
     255                 : **
     256                 : **     YYYY-MM-DD HH:MM:SS.FFF
     257                 : **     YYYY-MM-DD HH:MM:SS
     258                 : **     YYYY-MM-DD HH:MM
     259                 : **     YYYY-MM-DD
     260                 : **
     261                 : ** Write the result into the DateTime structure and return 0
     262                 : ** on success and 1 if the input string is not a well-formed
     263                 : ** date.
     264                 : */
     265               0 : static int parseYyyyMmDd(const char *zDate, DateTime *p){
     266                 :   int Y, M, D, neg;
     267                 : 
     268               0 :   if( zDate[0]=='-' ){
     269               0 :     zDate++;
     270               0 :     neg = 1;
     271                 :   }else{
     272               0 :     neg = 0;
     273                 :   }
     274               0 :   if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){
     275               0 :     return 1;
     276                 :   }
     277               0 :   zDate += 10;
     278               0 :   while( isspace(*zDate) ){ zDate++; }
     279               0 :   if( parseHhMmSs(zDate, p)==0 ){
     280                 :     /* We got the time */
     281               0 :   }else if( *zDate==0 ){
     282               0 :     p->validHMS = 0;
     283                 :   }else{
     284               0 :     return 1;
     285                 :   }
     286               0 :   p->validJD = 0;
     287               0 :   p->validYMD = 1;
     288               0 :   p->Y = neg ? -Y : Y;
     289               0 :   p->M = M;
     290               0 :   p->D = D;
     291               0 :   if( p->validTZ ){
     292               0 :     computeJD(p);
     293                 :   }
     294               0 :   return 0;
     295                 : }
     296                 : 
     297                 : /*
     298                 : ** Attempt to parse the given string into a Julian Day Number.  Return
     299                 : ** the number of errors.
     300                 : **
     301                 : ** The following are acceptable forms for the input string:
     302                 : **
     303                 : **      YYYY-MM-DD HH:MM:SS.FFF  +/-HH:MM
     304                 : **      DDDD.DD 
     305                 : **      now
     306                 : **
     307                 : ** In the first form, the +/-HH:MM is always optional.  The fractional
     308                 : ** seconds extension (the ".FFF") is optional.  The seconds portion
     309                 : ** (":SS.FFF") is option.  The year and date can be omitted as long
     310                 : ** as there is a time string.  The time string can be omitted as long
     311                 : ** as there is a year and date.
     312                 : */
     313               0 : static int parseDateOrTime(const char *zDate, DateTime *p){
     314               0 :   memset(p, 0, sizeof(*p));
     315               0 :   if( parseYyyyMmDd(zDate,p)==0 ){
     316               0 :     return 0;
     317               0 :   }else if( parseHhMmSs(zDate, p)==0 ){
     318               0 :     return 0;
     319               0 :   }else if( sqliteStrICmp(zDate,"now")==0){
     320                 :     double r;
     321               0 :     if( sqliteOsCurrentTime(&r)==0 ){
     322               0 :       p->rJD = r;
     323               0 :       p->validJD = 1;
     324               0 :       return 0;
     325                 :     }
     326               0 :     return 1;
     327               0 :   }else if( sqliteIsNumber(zDate) ){
     328               0 :     p->rJD = sqliteAtoF(zDate, 0);
     329               0 :     p->validJD = 1;
     330               0 :     return 0;
     331                 :   }
     332               0 :   return 1;
     333                 : }
     334                 : 
     335                 : /*
     336                 : ** Compute the Year, Month, and Day from the julian day number.
     337                 : */
     338               0 : static void computeYMD(DateTime *p){
     339                 :   int Z, A, B, C, D, E, X1;
     340               0 :   if( p->validYMD ) return;
     341               0 :   if( !p->validJD ){
     342               0 :     p->Y = 2000;
     343               0 :     p->M = 1;
     344               0 :     p->D = 1;
     345                 :   }else{
     346               0 :     Z = p->rJD + 0.5;
     347               0 :     A = (Z - 1867216.25)/36524.25;
     348               0 :     A = Z + 1 + A - (A/4);
     349               0 :     B = A + 1524;
     350               0 :     C = (B - 122.1)/365.25;
     351               0 :     D = 365.25*C;
     352               0 :     E = (B-D)/30.6001;
     353               0 :     X1 = 30.6001*E;
     354               0 :     p->D = B - D - X1;
     355               0 :     p->M = E<14 ? E-1 : E-13;
     356               0 :     p->Y = p->M>2 ? C - 4716 : C - 4715;
     357                 :   }
     358               0 :   p->validYMD = 1;
     359                 : }
     360                 : 
     361                 : /*
     362                 : ** Compute the Hour, Minute, and Seconds from the julian day number.
     363                 : */
     364               0 : static void computeHMS(DateTime *p){
     365                 :   int Z, s;
     366               0 :   if( p->validHMS ) return;
     367               0 :   Z = p->rJD + 0.5;
     368               0 :   s = (p->rJD + 0.5 - Z)*86400000.0 + 0.5;
     369               0 :   p->s = 0.001*s;
     370               0 :   s = p->s;
     371               0 :   p->s -= s;
     372               0 :   p->h = s/3600;
     373               0 :   s -= p->h*3600;
     374               0 :   p->m = s/60;
     375               0 :   p->s += s - p->m*60;
     376               0 :   p->validHMS = 1;
     377                 : }
     378                 : 
     379                 : /*
     380                 : ** Compute both YMD and HMS
     381                 : */
     382               0 : static void computeYMD_HMS(DateTime *p){
     383               0 :   computeYMD(p);
     384               0 :   computeHMS(p);
     385               0 : }
     386                 : 
     387                 : /*
     388                 : ** Clear the YMD and HMS and the TZ
     389                 : */
     390               0 : static void clearYMD_HMS_TZ(DateTime *p){
     391               0 :   p->validYMD = 0;
     392               0 :   p->validHMS = 0;
     393               0 :   p->validTZ = 0;
     394               0 : }
     395                 : 
     396                 : /*
     397                 : ** Compute the difference (in days) between localtime and UTC (a.k.a. GMT)
     398                 : ** for the time value p where p is in UTC.
     399                 : */
     400               0 : static double localtimeOffset(DateTime *p){
     401                 :   DateTime x, y;
     402                 :   time_t t;
     403                 :   struct tm *pTm, tmbuf;
     404               0 :   x = *p;
     405               0 :   computeYMD_HMS(&x);
     406               0 :   if( x.Y<1971 || x.Y>=2038 ){
     407               0 :     x.Y = 2000;
     408               0 :     x.M = 1;
     409               0 :     x.D = 1;
     410               0 :     x.h = 0;
     411               0 :     x.m = 0;
     412               0 :     x.s = 0.0;
     413                 :   } else {
     414               0 :     int s = x.s + 0.5;
     415               0 :     x.s = s;
     416                 :   }
     417               0 :   x.tz = 0;
     418               0 :   x.validJD = 0;
     419               0 :   computeJD(&x);
     420               0 :   t = (x.rJD-2440587.5)*86400.0 + 0.5;
     421               0 :   sqliteOsEnterMutex();
     422               0 :   pTm = php_localtime_r(&t, &tmbuf);
     423               0 :   if (!pTm) {
     424               0 :           return 0;
     425                 :   }
     426               0 :   y.Y = pTm->tm_year + 1900;
     427               0 :   y.M = pTm->tm_mon + 1;
     428               0 :   y.D = pTm->tm_mday;
     429               0 :   y.h = pTm->tm_hour;
     430               0 :   y.m = pTm->tm_min;
     431               0 :   y.s = pTm->tm_sec;
     432               0 :   sqliteOsLeaveMutex();
     433               0 :   y.validYMD = 1;
     434               0 :   y.validHMS = 1;
     435               0 :   y.validJD = 0;
     436               0 :   y.validTZ = 0;
     437               0 :   computeJD(&y);
     438               0 :   return y.rJD - x.rJD;
     439                 : }
     440                 : 
     441                 : /*
     442                 : ** Process a modifier to a date-time stamp.  The modifiers are
     443                 : ** as follows:
     444                 : **
     445                 : **     NNN days
     446                 : **     NNN hours
     447                 : **     NNN minutes
     448                 : **     NNN.NNNN seconds
     449                 : **     NNN months
     450                 : **     NNN years
     451                 : **     start of month
     452                 : **     start of year
     453                 : **     start of week
     454                 : **     start of day
     455                 : **     weekday N
     456                 : **     unixepoch
     457                 : **     localtime
     458                 : **     utc
     459                 : **
     460                 : ** Return 0 on success and 1 if there is any kind of error.
     461                 : */
     462               0 : static int parseModifier(const char *zMod, DateTime *p){
     463               0 :   int rc = 1;
     464                 :   int n;
     465                 :   double r;
     466                 :   char *z, zBuf[30];
     467               0 :   z = zBuf;
     468               0 :   for(n=0; n<sizeof(zBuf)-1 && zMod[n]; n++){
     469               0 :     z[n] = tolower(zMod[n]);
     470                 :   }
     471               0 :   z[n] = 0;
     472               0 :   switch( z[0] ){
     473                 :     case 'l': {
     474                 :       /*    localtime
     475                 :       **
     476                 :       ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
     477                 :       ** show local time.
     478                 :       */
     479               0 :       if( strcmp(z, "localtime")==0 ){
     480               0 :         computeJD(p);
     481               0 :         p->rJD += localtimeOffset(p);
     482               0 :         clearYMD_HMS_TZ(p);
     483               0 :         rc = 0;
     484                 :       }
     485               0 :       break;
     486                 :     }
     487                 :     case 'u': {
     488                 :       /*
     489                 :       **    unixepoch
     490                 :       **
     491                 :       ** Treat the current value of p->rJD as the number of
     492                 :       ** seconds since 1970.  Convert to a real julian day number.
     493                 :       */
     494               0 :       if( strcmp(z, "unixepoch")==0 && p->validJD ){
     495               0 :         p->rJD = p->rJD/86400.0 + 2440587.5;
     496               0 :         clearYMD_HMS_TZ(p);
     497               0 :         rc = 0;
     498               0 :       }else if( strcmp(z, "utc")==0 ){
     499                 :         double c1;
     500               0 :         computeJD(p);
     501               0 :         c1 = localtimeOffset(p);
     502               0 :         p->rJD -= c1;
     503               0 :         clearYMD_HMS_TZ(p);
     504               0 :         p->rJD += c1 - localtimeOffset(p);
     505               0 :         rc = 0;
     506                 :       }
     507               0 :       break;
     508                 :     }
     509                 :     case 'w': {
     510                 :       /*
     511                 :       **    weekday N
     512                 :       **
     513                 :       ** Move the date to the same time on the next occurrance of
     514                 :       ** weekday N where 0==Sunday, 1==Monday, and so forth.  If the
     515                 :       ** date is already on the appropriate weekday, this is a no-op.
     516                 :       */
     517               0 :       if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0
     518                 :                  && (n=r)==r && n>=0 && r<7 ){
     519                 :         int Z;
     520               0 :         computeYMD_HMS(p);
     521               0 :         p->validTZ = 0;
     522               0 :         p->validJD = 0;
     523               0 :         computeJD(p);
     524               0 :         Z = p->rJD + 1.5;
     525               0 :         Z %= 7;
     526               0 :         if( Z>n ) Z -= 7;
     527               0 :         p->rJD += n - Z;
     528               0 :         clearYMD_HMS_TZ(p);
     529               0 :         rc = 0;
     530                 :       }
     531               0 :       break;
     532                 :     }
     533                 :     case 's': {
     534                 :       /*
     535                 :       **    start of TTTTT
     536                 :       **
     537                 :       ** Move the date backwards to the beginning of the current day,
     538                 :       ** or month or year.
     539                 :       */
     540               0 :       if( strncmp(z, "start of ", 9)!=0 ) break;
     541               0 :       z += 9;
     542               0 :       computeYMD(p);
     543               0 :       p->validHMS = 1;
     544               0 :       p->h = p->m = 0;
     545               0 :       p->s = 0.0;
     546               0 :       p->validTZ = 0;
     547               0 :       p->validJD = 0;
     548               0 :       if( strcmp(z,"month")==0 ){
     549               0 :         p->D = 1;
     550               0 :         rc = 0;
     551               0 :       }else if( strcmp(z,"year")==0 ){
     552               0 :         computeYMD(p);
     553               0 :         p->M = 1;
     554               0 :         p->D = 1;
     555               0 :         rc = 0;
     556               0 :       }else if( strcmp(z,"day")==0 ){
     557               0 :         rc = 0;
     558                 :       }
     559               0 :       break;
     560                 :     }
     561                 :     case '+':
     562                 :     case '-':
     563                 :     case '0':
     564                 :     case '1':
     565                 :     case '2':
     566                 :     case '3':
     567                 :     case '4':
     568                 :     case '5':
     569                 :     case '6':
     570                 :     case '7':
     571                 :     case '8':
     572                 :     case '9': {
     573               0 :       n = getValue(z, &r);
     574               0 :       if( n<=0 ) break;
     575               0 :       if( z[n]==':' ){
     576                 :         /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
     577                 :         ** specified number of hours, minutes, seconds, and fractional seconds
     578                 :         ** to the time.  The ".FFF" may be omitted.  The ":SS.FFF" may be
     579                 :         ** omitted.
     580                 :         */
     581               0 :         const char *z2 = z;
     582                 :         DateTime tx;
     583                 :         int day;
     584               0 :         if( !isdigit(*z2) ) z2++;
     585               0 :         memset(&tx, 0, sizeof(tx));
     586               0 :         if( parseHhMmSs(z2, &tx) ) break;
     587               0 :         computeJD(&tx);
     588               0 :         tx.rJD -= 0.5;
     589               0 :         day = (int)tx.rJD;
     590               0 :         tx.rJD -= day;
     591               0 :         if( z[0]=='-' ) tx.rJD = -tx.rJD;
     592               0 :         computeJD(p);
     593               0 :         clearYMD_HMS_TZ(p);
     594               0 :        p->rJD += tx.rJD;
     595               0 :         rc = 0;
     596               0 :         break;
     597                 :       }
     598               0 :       z += n;
     599               0 :       while( isspace(z[0]) ) z++;
     600               0 :       n = strlen(z);
     601               0 :       if( n>10 || n<3 ) break;
     602               0 :       if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
     603               0 :       computeJD(p);
     604               0 :       rc = 0;
     605               0 :       if( n==3 && strcmp(z,"day")==0 ){
     606               0 :         p->rJD += r;
     607               0 :       }else if( n==4 && strcmp(z,"hour")==0 ){
     608               0 :         p->rJD += r/24.0;
     609               0 :       }else if( n==6 && strcmp(z,"minute")==0 ){
     610               0 :         p->rJD += r/(24.0*60.0);
     611               0 :       }else if( n==6 && strcmp(z,"second")==0 ){
     612               0 :         p->rJD += r/(24.0*60.0*60.0);
     613               0 :       }else if( n==5 && strcmp(z,"month")==0 ){
     614                 :         int x, y;
     615               0 :         computeYMD_HMS(p);
     616               0 :         p->M += r;
     617               0 :         x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
     618               0 :         p->Y += x;
     619               0 :         p->M -= x*12;
     620               0 :         p->validJD = 0;
     621               0 :         computeJD(p);
     622               0 :         y = r;
     623               0 :         if( y!=r ){
     624               0 :           p->rJD += (r - y)*30.0;
     625                 :         }
     626               0 :       }else if( n==4 && strcmp(z,"year")==0 ){
     627               0 :         computeYMD_HMS(p);
     628               0 :         p->Y += r;
     629               0 :         p->validJD = 0;
     630               0 :         computeJD(p);
     631                 :       }else{
     632               0 :         rc = 1;
     633                 :       }
     634               0 :       clearYMD_HMS_TZ(p);
     635                 :       break;
     636                 :     }
     637                 :     default: {
     638                 :       break;
     639                 :     }
     640                 :   }
     641               0 :   return rc;
     642                 : }
     643                 : 
     644                 : /*
     645                 : ** Process time function arguments.  argv[0] is a date-time stamp.
     646                 : ** argv[1] and following are modifiers.  Parse them all and write
     647                 : ** the resulting time into the DateTime structure p.  Return 0
     648                 : ** on success and 1 if there are any errors.
     649                 : */
     650               0 : static int isDate(int argc, const char **argv, DateTime *p){
     651                 :   int i;
     652               0 :   if( argc==0 ) return 1;
     653               0 :   if( argv[0]==0 || parseDateOrTime(argv[0], p) ) return 1;
     654               0 :   for(i=1; i<argc; i++){
     655               0 :     if( argv[i]==0 || parseModifier(argv[i], p) ) return 1;
     656                 :   }
     657               0 :   return 0;
     658                 : }
     659                 : 
     660                 : 
     661                 : /*
     662                 : ** The following routines implement the various date and time functions
     663                 : ** of SQLite.
     664                 : */
     665                 : 
     666                 : /*
     667                 : **    julianday( TIMESTRING, MOD, MOD, ...)
     668                 : **
     669                 : ** Return the julian day number of the date specified in the arguments
     670                 : */
     671               0 : static void juliandayFunc(sqlite_func *context, int argc, const char **argv){
     672                 :   DateTime x;
     673               0 :   if( isDate(argc, argv, &x)==0 ){
     674               0 :     computeJD(&x);
     675               0 :     sqlite_set_result_double(context, x.rJD);
     676                 :   }
     677               0 : }
     678                 : 
     679                 : /*
     680                 : **    datetime( TIMESTRING, MOD, MOD, ...)
     681                 : **
     682                 : ** Return YYYY-MM-DD HH:MM:SS
     683                 : */
     684               0 : static void datetimeFunc(sqlite_func *context, int argc, const char **argv){
     685                 :   DateTime x;
     686               0 :   if( isDate(argc, argv, &x)==0 ){
     687                 :     char zBuf[100];
     688               0 :     computeYMD_HMS(&x);
     689               0 :     sprintf(zBuf, "%04d-%02d-%02d %02d:%02d:%02d",x.Y, x.M, x.D, x.h, x.m,
     690                 :            (int)(x.s));
     691               0 :     sqlite_set_result_string(context, zBuf, -1);
     692                 :   }
     693               0 : }
     694                 : 
     695                 : /*
     696                 : **    time( TIMESTRING, MOD, MOD, ...)
     697                 : **
     698                 : ** Return HH:MM:SS
     699                 : */
     700               0 : static void timeFunc(sqlite_func *context, int argc, const char **argv){
     701                 :   DateTime x;
     702               0 :   if( isDate(argc, argv, &x)==0 ){
     703                 :     char zBuf[100];
     704               0 :     computeHMS(&x);
     705               0 :     sprintf(zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
     706               0 :     sqlite_set_result_string(context, zBuf, -1);
     707                 :   }
     708               0 : }
     709                 : 
     710                 : /*
     711                 : **    date( TIMESTRING, MOD, MOD, ...)
     712                 : **
     713                 : ** Return YYYY-MM-DD
     714                 : */
     715               0 : static void dateFunc(sqlite_func *context, int argc, const char **argv){
     716                 :   DateTime x;
     717               0 :   if( isDate(argc, argv, &x)==0 ){
     718                 :     char zBuf[100];
     719               0 :     computeYMD(&x);
     720               0 :     sprintf(zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
     721               0 :     sqlite_set_result_string(context, zBuf, -1);
     722                 :   }
     723               0 : }
     724                 : 
     725                 : /*
     726                 : **    strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
     727                 : **
     728                 : ** Return a string described by FORMAT.  Conversions as follows:
     729                 : **
     730                 : **   %d  day of month
     731                 : **   %f  ** fractional seconds  SS.SSS
     732                 : **   %H  hour 00-24
     733                 : **   %j  day of year 000-366
     734                 : **   %J  ** Julian day number
     735                 : **   %m  month 01-12
     736                 : **   %M  minute 00-59
     737                 : **   %s  seconds since 1970-01-01
     738                 : **   %S  seconds 00-59
     739                 : **   %w  day of week 0-6  sunday==0
     740                 : **   %W  week of year 00-53
     741                 : **   %Y  year 0000-9999
     742                 : **   %%  %
     743                 : */
     744               0 : static void strftimeFunc(sqlite_func *context, int argc, const char **argv){
     745                 :   DateTime x;
     746                 :   int n, i, j;
     747                 :   char *z;
     748               0 :   const char *zFmt = argv[0];
     749                 :   char zBuf[100];
     750               0 :   if( argv[0]==0 || isDate(argc-1, argv+1, &x) ) return;
     751               0 :   for(i=0, n=1; zFmt[i]; i++, n++){
     752               0 :     if( zFmt[i]=='%' ){
     753               0 :       switch( zFmt[i+1] ){
     754                 :         case 'd':
     755                 :         case 'H':
     756                 :         case 'm':
     757                 :         case 'M':
     758                 :         case 'S':
     759                 :         case 'W':
     760               0 :           n++;
     761                 :           /* fall thru */
     762                 :         case 'w':
     763                 :         case '%':
     764               0 :           break;
     765                 :         case 'f':
     766               0 :           n += 8;
     767               0 :           break;
     768                 :         case 'j':
     769               0 :           n += 3;
     770               0 :           break;
     771                 :         case 'Y':
     772               0 :           n += 8;
     773               0 :           break;
     774                 :         case 's':
     775                 :         case 'J':
     776               0 :           n += 50;
     777               0 :           break;
     778                 :         default:
     779               0 :           return;  /* ERROR.  return a NULL */
     780                 :       }
     781               0 :       i++;
     782                 :     }
     783                 :   }
     784               0 :   if( n<sizeof(zBuf) ){
     785               0 :     z = zBuf;
     786                 :   }else{
     787               0 :     z = sqliteMalloc( n );
     788               0 :     if( z==0 ) return;
     789                 :   }
     790               0 :   computeJD(&x);
     791               0 :   computeYMD_HMS(&x);
     792               0 :   for(i=j=0; zFmt[i]; i++){
     793               0 :     if( zFmt[i]!='%' ){
     794               0 :       z[j++] = zFmt[i];
     795                 :     }else{
     796               0 :       i++;
     797               0 :       switch( zFmt[i] ){
     798               0 :         case 'd':  sprintf(&z[j],"%02d",x.D); j+=2; break;
     799                 :         case 'f': {
     800               0 :           int s = x.s;
     801               0 :           int ms = (x.s - s)*1000.0;
     802               0 :           sprintf(&z[j],"%02d.%03d",s,ms);
     803               0 :           j += strlen(&z[j]);
     804               0 :           break;
     805                 :         }
     806               0 :         case 'H':  sprintf(&z[j],"%02d",x.h); j+=2; break;
     807                 :         case 'W': /* Fall thru */
     808                 :         case 'j': {
     809                 :           int n;             /* Number of days since 1st day of year */
     810               0 :           DateTime y = x;
     811               0 :           y.validJD = 0;
     812               0 :           y.M = 1;
     813               0 :           y.D = 1;
     814               0 :           computeJD(&y);
     815               0 :           n = x.rJD - y.rJD;
     816               0 :           if( zFmt[i]=='W' ){
     817                 :             int wd;   /* 0=Monday, 1=Tuesday, ... 6=Sunday */
     818               0 :             wd = ((int)(x.rJD+0.5)) % 7;
     819               0 :             sprintf(&z[j],"%02d",(n+7-wd)/7);
     820               0 :             j += 2;
     821                 :           }else{
     822               0 :             sprintf(&z[j],"%03d",n+1);
     823               0 :             j += 3;
     824                 :           }
     825               0 :           break;
     826                 :         }
     827               0 :         case 'J':  sprintf(&z[j],"%.16g",x.rJD); j+=strlen(&z[j]); break;
     828               0 :         case 'm':  sprintf(&z[j],"%02d",x.M); j+=2; break;
     829               0 :         case 'M':  sprintf(&z[j],"%02d",x.m); j+=2; break;
     830                 :         case 's': {
     831               0 :           sprintf(&z[j],"%d",(int)((x.rJD-2440587.5)*86400.0 + 0.5));
     832               0 :           j += strlen(&z[j]);
     833               0 :           break;
     834                 :         }
     835               0 :         case 'S':  sprintf(&z[j],"%02d",(int)(x.s+0.5)); j+=2; break;
     836               0 :         case 'w':  z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break;
     837               0 :         case 'Y':  sprintf(&z[j],"%04d",x.Y); j+=strlen(&z[j]); break;
     838               0 :         case '%':  z[j++] = '%'; break;
     839                 :       }
     840                 :     }
     841                 :   }
     842               0 :   z[j] = 0;
     843               0 :   sqlite_set_result_string(context, z, -1);
     844               0 :   if( z!=zBuf ){
     845               0 :     sqliteFree(z);
     846                 :   }
     847                 : }
     848                 : 
     849                 : 
     850                 : #endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
     851                 : 
     852                 : /*
     853                 : ** This function registered all of the above C functions as SQL
     854                 : ** functions.  This should be the only routine in this file with
     855                 : ** external linkage.
     856                 : */
     857             150 : void sqliteRegisterDateTimeFunctions(sqlite *db){
     858                 : #ifndef SQLITE_OMIT_DATETIME_FUNCS
     859                 :   static struct {
     860                 :      char *zName;
     861                 :      int nArg;
     862                 :      int dataType;
     863                 :      void (*xFunc)(sqlite_func*,int,const char**);
     864                 :   } aFuncs[] = {
     865                 :     { "julianday", -1, SQLITE_NUMERIC, juliandayFunc   },
     866                 :     { "date",      -1, SQLITE_TEXT,    dateFunc        },
     867                 :     { "time",      -1, SQLITE_TEXT,    timeFunc        },
     868                 :     { "datetime",  -1, SQLITE_TEXT,    datetimeFunc    },
     869                 :     { "strftime",  -1, SQLITE_TEXT,    strftimeFunc    },
     870                 :   };
     871                 :   int i;
     872                 : 
     873             900 :   for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
     874             750 :     sqlite_create_function(db, aFuncs[i].zName,
     875                 :            aFuncs[i].nArg, aFuncs[i].xFunc, 0);
     876             750 :     if( aFuncs[i].xFunc ){
     877             750 :       sqlite_function_type(db, aFuncs[i].zName, aFuncs[i].dataType);
     878                 :     }
     879                 :   }
     880                 : #endif
     881             150 : }

Generated by: LTP GCOV extension version 1.5

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

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