SQLite4
Check-in [fa869b0982]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Remove the use of type 'double' from date.c.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: fa869b0982959bfdcf71b2c0c2b5be37de4bc9f2
User & Date: dan 2013-06-03 19:25:21
Context
2013-06-04
15:16
Fix a few warnings relating to unused variables and functions. check-in: 424d39678b user: dan tags: trunk
2013-06-03
19:25
Remove the use of type 'double' from date.c. check-in: fa869b0982 user: dan tags: trunk
15:23
Merge overflow and rounding fixes for sqlite4_num_to_int64(). check-in: e8db1e81a4 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/date.c.

    52     52   
    53     53   
    54     54   /*
    55     55   ** A structure for holding a single date and time.
    56     56   */
    57     57   typedef struct DateTime DateTime;
    58     58   struct DateTime {
    59         -  sqlite4_uint64 iJD; /* The julian day number times 86400000 */
    60         -  int Y, M, D;       /* Year, month, and day */
    61         -  int h, m;          /* Hour and minutes */
    62         -  int tz;            /* Timezone offset in minutes */
    63         -  double s;          /* Seconds */
    64         -  char validYMD;     /* True (1) if Y,M,D are valid */
    65         -  char validHMS;     /* True (1) if h,m,s are valid */
    66         -  char validJD;      /* True (1) if iJD is valid */
    67         -  char validTZ;      /* True (1) if tz is valid */
           59  +  sqlite4_uint64 iJD;   /* The julian day number times 86400000 */
           60  +  int Y, M, D;          /* Year, month, and day */
           61  +  int h, m;             /* Hour and minutes */
           62  +  int tz;               /* Timezone offset in minutes */
           63  +  sqlite4_num s;        /* Seconds */
           64  +  char validYMD;        /* True (1) if Y,M,D are valid */
           65  +  char validHMS;        /* True (1) if h,m,s are valid */
           66  +  char validJD;         /* True (1) if iJD is valid */
           67  +  char validTZ;         /* True (1) if tz is valid */
    68     68   };
    69     69   
    70     70   
    71     71   /*
    72     72   ** Convert zDate into one or more integers.  Additional arguments
    73     73   ** come in groups of 5 as follows:
    74     74   **
................................................................................
   166    166   ** The HH, MM, and SS must each be exactly 2 digits.  The
   167    167   ** fractional seconds FFFF can be one or more digits.
   168    168   **
   169    169   ** Return 1 if there is a parsing error and 0 on success.
   170    170   */
   171    171   static int parseHhMmSs(const char *zDate, DateTime *p){
   172    172     int h, m, s;
   173         -  double ms = 0.0;
          173  +  sqlite4_num ms = {0,0,0,0};
   174    174     if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
   175    175       return 1;
   176    176     }
   177    177     zDate += 5;
   178    178     if( *zDate==':' ){
   179    179       zDate++;
   180    180       if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
   181    181         return 1;
   182    182       }
   183    183       zDate += 2;
   184         -    if( *zDate=='.' && sqlite4Isdigit(zDate[1]) ){
   185         -      double rScale = 1.0;
   186         -      zDate++;
   187         -      while( sqlite4Isdigit(*zDate) ){
   188         -        ms = ms*10.0 + *zDate - '0';
   189         -        rScale *= 10.0;
   190         -        zDate++;
          184  +
          185  +    if( *zDate=='.' ){
          186  +      int iMs = 0;
          187  +      int nDigit = 1;
          188  +      while( sqlite4Isdigit(zDate[nDigit]) ){
          189  +        iMs = iMs * 10 + (zDate[nDigit] - '0');
          190  +        nDigit++;
   191    191         }
   192         -      ms /= rScale;
          192  +      if( nDigit>1 ){
          193  +        ms = sqlite4_num_from_int64(iMs);
          194  +        assert( ms.e==0 );
          195  +        ms.e += (1-nDigit);
          196  +        zDate += nDigit;
          197  +      }
   193    198       }
   194    199     }else{
   195    200       s = 0;
   196    201     }
   197    202     p->validJD = 0;
   198    203     p->validHMS = 1;
   199    204     p->h = h;
   200    205     p->m = m;
   201         -  p->s = s + ms;
          206  +  p->s = sqlite4_num_add(sqlite4_num_from_int64(s), ms);
   202    207     if( parseTimezone(zDate, p) ) return 1;
   203    208     p->validTZ = (p->tz!=0)?1:0;
   204    209     return 0;
   205    210   }
   206    211   
   207    212   /*
   208    213   ** Convert from YYYY-MM-DD HH:MM:SS to julian day.  We always assume
................................................................................
   230    235     A = Y/100;
   231    236     B = 2 - A + (A/4);
   232    237     X1 = 36525*(Y+4716)/100;
   233    238     X2 = 306001*(M+1)/10000;
   234    239     p->iJD = (sqlite4_int64)((X1 + X2 + D + B - 1524.5 ) * 86400000);
   235    240     p->validJD = 1;
   236    241     if( p->validHMS ){
   237         -    p->iJD += p->h*3600000 + p->m*60000 + (sqlite4_int64)(p->s*1000);
          242  +    p->iJD += p->h*3600000 + p->m*60000;
          243  +    p->iJD += sqlite4_num_to_int64(
          244  +        sqlite4_num_mul(p->s, sqlite4_num_from_int64(1000)), 0
          245  +    );
   238    246       if( p->validTZ ){
   239    247         p->iJD -= p->tz*60000;
   240    248         p->validYMD = 0;
   241    249         p->validHMS = 0;
   242    250         p->validTZ = 0;
   243    251       }
   244    252     }
................................................................................
   319    327   ** as there is a year and date.
   320    328   */
   321    329   static int parseDateOrTime(
   322    330     sqlite4_context *context, 
   323    331     const char *zDate, 
   324    332     DateTime *p
   325    333   ){
   326         -  double r;
   327    334     if( parseYyyyMmDd(zDate,p)==0 ){
   328    335       return 0;
   329    336     }else if( parseHhMmSs(zDate, p)==0 ){
   330    337       return 0;
   331    338     }else if( sqlite4_stricmp(zDate,"now")==0){
   332    339       return setDateTimeToCurrent(context, p);
   333         -  }else if( sqlite4AtoF(zDate, &r, sqlite4Strlen30(zDate), SQLITE4_UTF8) ){
   334         -    p->iJD = (sqlite4_int64)(r*86400000.0 + 0.5);
   335         -    p->validJD = 1;
   336         -    return 0;
          340  +  }else{
          341  +    sqlite4_num num;
          342  +    num = sqlite4_num_from_text(zDate, -1, SQLITE4_IGNORE_WHITESPACE, 0);
          343  +    if( sqlite4_num_isnan(num)==0 ){
          344  +      static const sqlite4_num one_half = {0, 0, -1, 5};
          345  +
          346  +      num = sqlite4_num_mul(num, sqlite4_num_from_int64(86400000));
          347  +      num = sqlite4_num_add(num, one_half);
          348  +      p->iJD = sqlite4_num_to_int64(num, 0);
          349  +      p->validJD = 1;
          350  +      return 0;
          351  +    }
   337    352     }
   338    353     return 1;
   339    354   }
   340    355   
   341    356   /*
   342    357   ** Compute the Year, Month, and Day from the julian day number.
   343    358   */
................................................................................
   368    383   ** Compute the Hour, Minute, and Seconds from the julian day number.
   369    384   */
   370    385   static void computeHMS(DateTime *p){
   371    386     int s;
   372    387     if( p->validHMS ) return;
   373    388     computeJD(p);
   374    389     s = (int)((p->iJD + 43200000) % 86400000);
   375         -  p->s = s/1000.0;
   376         -  s = (int)p->s;
   377         -  p->s -= s;
          390  +  p->s = sqlite4_num_div(
          391  +      sqlite4_num_from_int64(s), sqlite4_num_from_int64(1000)
          392  +  );
          393  +  s = (int)sqlite4_num_to_int64(p->s, 0);
          394  +  p->s = sqlite4_num_sub(p->s, sqlite4_num_from_int64(s));
   378    395     p->h = s/3600;
   379    396     s -= p->h*3600;
   380    397     p->m = s/60;
   381         -  p->s += s - p->m*60;
          398  +  p->s = sqlite4_num_add(p->s, sqlite4_num_from_int64(s - p->m*60));
   382    399     p->validHMS = 1;
   383    400   }
   384    401   
   385    402   /*
   386    403   ** Compute both YMD and HMS
   387    404   */
   388    405   static void computeYMD_HMS(DateTime *p){
................................................................................
   511    528     y.validJD = 0;
   512    529     y.validTZ = 0;
   513    530     computeJD(&y);
   514    531     *pRc = SQLITE4_OK;
   515    532     return y.iJD - x.iJD;
   516    533   }
   517    534   #endif /* SQLITE4_OMIT_LOCALTIME */
          535  +
          536  +static sqlite4_int64 multiplyAndRound(sqlite4_num a, i64 b){
          537  +  static const sqlite4_num aRnd[2] = { {0, 0, -1, 5}, {1, 0, -1, 5} };
          538  +  sqlite4_num res;
          539  +
          540  +  res = sqlite4_num_mul(a, sqlite4_num_from_int64(b));
          541  +  assert( res.sign==0 || res.sign==1 );
          542  +  res = sqlite4_num_add(res, aRnd[res.sign]);
          543  +  return sqlite4_num_to_int64(res, 0);
          544  +}
   518    545   
   519    546   /*
   520    547   ** Process a modifier to a date-time stamp.  The modifiers are
   521    548   ** as follows:
   522    549   **
   523    550   **     NNN days
   524    551   **     NNN hours
................................................................................
   536    563   **     utc
   537    564   **
   538    565   ** Return 0 on success and 1 if there is any kind of error. If the error
   539    566   ** is in a system call (i.e. localtime()), then an error message is written
   540    567   ** to context pCtx. If the error is an unrecognized modifier, no error is
   541    568   ** written to pCtx.
   542    569   */
   543         -static int parseModifier(sqlite4_context *pCtx, const char *zMod, DateTime *p){
          570  +static int parseModifier(
          571  +  sqlite4_context *pCtx,          /* Leave error message here */
          572  +  const char *zMod,               /* date-time modifier */
          573  +  DateTime *p                     /* Update the value this points to */
          574  +){
   544    575     int rc = 1;
   545    576     int n;
   546         -  double r;
   547    577     char *z, zBuf[30];
   548    578     z = zBuf;
   549    579     for(n=0; n<ArraySize(zBuf)-1 && zMod[n]; n++){
   550    580       z[n] = (char)sqlite4UpperToLower[(u8)zMod[n]];
   551    581     }
   552    582     z[n] = 0;
   553    583     switch( z[0] ){
................................................................................
   596    626         /*
   597    627         **    weekday N
   598    628         **
   599    629         ** Move the date to the same time on the next occurrence of
   600    630         ** weekday N where 0==Sunday, 1==Monday, and so forth.  If the
   601    631         ** date is already on the appropriate weekday, this is a no-op.
   602    632         */
   603         -      if( strncmp(z, "weekday ", 8)==0
   604         -               && sqlite4AtoF(&z[8], &r, sqlite4Strlen30(&z[8]), SQLITE4_UTF8)
   605         -               && (n=(int)r)==r && n>=0 && r<7 ){
          633  +      if( strncmp(z, "weekday ", 8)==0 ){
          634  +        int bLossy;
          635  +        int iWeekday;
   606    636           sqlite4_int64 Z;
          637  +        sqlite4_num w;
          638  +        int n;
          639  +
          640  +        for(n=8; sqlite4Isspace(z[n]); n++);
          641  +        if( z[n]==0 ) break;
          642  +        w = sqlite4_num_from_text(&z[8], -1, SQLITE4_IGNORE_WHITESPACE, 0);
          643  +        if( sqlite4_num_isnan(w) ) break;
          644  +        iWeekday = (int)sqlite4_num_to_int64(w, &bLossy);
          645  +        if( bLossy || iWeekday<0 || iWeekday>6 ) break;
          646  +
   607    647           computeYMD_HMS(p);
   608    648           p->validTZ = 0;
   609    649           p->validJD = 0;
   610    650           computeJD(p);
   611    651           Z = ((p->iJD + 129600000)/86400000) % 7;
   612         -        if( Z>n ) Z -= 7;
   613         -        p->iJD += (n - Z)*86400000;
          652  +        if( Z>iWeekday ) Z -= 7;
          653  +        p->iJD += (iWeekday - Z)*86400000;
   614    654           clearYMD_HMS_TZ(p);
   615    655           rc = 0;
   616    656         }
   617    657         break;
   618    658       }
   619    659       case 's': {
   620    660         /*
................................................................................
   624    664         ** or month or year.
   625    665         */
   626    666         if( strncmp(z, "start of ", 9)!=0 ) break;
   627    667         z += 9;
   628    668         computeYMD(p);
   629    669         p->validHMS = 1;
   630    670         p->h = p->m = 0;
   631         -      p->s = 0.0;
          671  +      memset(&p->s, 0, sizeof(sqlite4_num));
   632    672         p->validTZ = 0;
   633    673         p->validJD = 0;
   634    674         if( strcmp(z,"month")==0 ){
   635    675           p->D = 1;
   636    676           rc = 0;
   637    677         }else if( strcmp(z,"year")==0 ){
   638    678           computeYMD(p);
................................................................................
   652    692       case '3':
   653    693       case '4':
   654    694       case '5':
   655    695       case '6':
   656    696       case '7':
   657    697       case '8':
   658    698       case '9': {
   659         -      double rRounder;
          699  +      sqlite4_num num;
          700  +
   660    701         for(n=1; z[n] && z[n]!=':' && !sqlite4Isspace(z[n]); n++){}
   661         -      if( !sqlite4AtoF(z, &r, n, SQLITE4_UTF8) ){
          702  +      num = sqlite4_num_from_text(z, n, SQLITE4_IGNORE_WHITESPACE, 0);
          703  +      if( sqlite4_num_isnan(num) ){
   662    704           rc = 1;
   663    705           break;
   664    706         }
          707  +
   665    708         if( z[n]==':' ){
   666    709           /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
   667    710           ** specified number of hours, minutes, seconds, and fractional seconds
   668    711           ** to the time.  The ".FFF" may be omitted.  The ":SS.FFF" may be
   669    712           ** omitted.
   670    713           */
   671    714           const char *z2 = z;
................................................................................
   681    724           if( z[0]=='-' ) tx.iJD = -tx.iJD;
   682    725           computeJD(p);
   683    726           clearYMD_HMS_TZ(p);
   684    727           p->iJD += tx.iJD;
   685    728           rc = 0;
   686    729           break;
   687    730         }
          731  +
   688    732         z += n;
   689    733         while( sqlite4Isspace(*z) ) z++;
   690    734         n = sqlite4Strlen30(z);
   691    735         if( n>10 || n<3 ) break;
   692    736         if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
   693    737         computeJD(p);
   694    738         rc = 0;
   695         -      rRounder = r<0 ? -0.5 : +0.5;
          739  +
   696    740         if( n==3 && strcmp(z,"day")==0 ){
   697         -        p->iJD += (sqlite4_int64)(r*86400000.0 + rRounder);
          741  +        p->iJD += multiplyAndRound(num, 86400000);
   698    742         }else if( n==4 && strcmp(z,"hour")==0 ){
   699         -        p->iJD += (sqlite4_int64)(r*(86400000.0/24.0) + rRounder);
          743  +        p->iJD += multiplyAndRound(num, 86400000 / 24);
   700    744         }else if( n==6 && strcmp(z,"minute")==0 ){
   701         -        p->iJD += (sqlite4_int64)(r*(86400000.0/(24.0*60.0)) + rRounder);
          745  +        p->iJD += multiplyAndRound(num, 86400000 / (24 * 60));
   702    746         }else if( n==6 && strcmp(z,"second")==0 ){
   703         -        p->iJD += (sqlite4_int64)(r*(86400000.0/(24.0*60.0*60.0)) + rRounder);
          747  +        p->iJD += multiplyAndRound(num, 86400000 / (24 * 60 * 60));
   704    748         }else if( n==5 && strcmp(z,"month")==0 ){
   705         -        int x, y;
          749  +        int bLossy;
          750  +        int nMonth;
          751  +        int x;
          752  +        nMonth = sqlite4_num_to_int64(num, &bLossy);
   706    753           computeYMD_HMS(p);
   707         -        p->M += (int)r;
          754  +        p->M += nMonth;
   708    755           x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
   709    756           p->Y += x;
   710    757           p->M -= x*12;
   711    758           p->validJD = 0;
   712    759           computeJD(p);
   713         -        y = (int)r;
   714         -        if( y!=r ){
   715         -          p->iJD += (sqlite4_int64)((r - y)*30.0*86400000.0 + rRounder);
          760  +        if( bLossy ){
          761  +          num = sqlite4_num_sub(num, sqlite4_num_from_int64(nMonth));
          762  +          p->iJD += multiplyAndRound(num, (i64)30*86400000);
   716    763           }
   717    764         }else if( n==4 && strcmp(z,"year")==0 ){
   718         -        int y = (int)r;
          765  +        int bLossy;
          766  +        int nYear;
          767  +        nYear = sqlite4_num_to_int64(num, &bLossy);
   719    768           computeYMD_HMS(p);
   720         -        p->Y += y;
          769  +        p->Y += nYear;
   721    770           p->validJD = 0;
   722    771           computeJD(p);
   723         -        if( y!=r ){
   724         -          p->iJD += (sqlite4_int64)((r - y)*365.0*86400000.0 + rRounder);
          772  +        if( bLossy ){
          773  +          num = sqlite4_num_sub(num, sqlite4_num_from_int64(nYear));
          774  +          p->iJD += multiplyAndRound(num, (i64)365*86400000);
   725    775           }
   726    776         }else{
   727    777           rc = 1;
   728    778         }
   729    779         clearYMD_HMS_TZ(p);
   730    780         break;
   731    781       }
................................................................................
   747    797   */
   748    798   static int isDate(
   749    799     sqlite4_context *context, 
   750    800     int argc, 
   751    801     sqlite4_value **argv, 
   752    802     DateTime *p
   753    803   ){
          804  +  static const sqlite4_num ms_per_day = {0, 0, 0, 86400000};
          805  +
   754    806     int i;
   755    807     const char *z;
   756    808     int eType;
   757    809     memset(p, 0, sizeof(*p));
   758    810     if( argc==0 ){
   759    811       return setDateTimeToCurrent(context, p);
   760    812     }
   761         -  if( (eType = sqlite4_value_type(argv[0]))==SQLITE4_FLOAT
   762         -                   || eType==SQLITE4_INTEGER ){
   763         -    p->iJD = (sqlite4_int64)(sqlite4_value_double(argv[0])*86400000.0 + 0.5);
          813  +  eType = sqlite4_value_type(argv[0]);
          814  +  if( eType==SQLITE4_FLOAT || eType==SQLITE4_INTEGER ){
          815  +    sqlite4_num jd = sqlite4_num_mul(sqlite4_value_num(argv[0]), ms_per_day);
          816  +    p->iJD = sqlite4_num_to_int64(sqlite4_num_round(jd, 0), 0);
   764    817       p->validJD = 1;
   765    818     }else{
   766    819       z = sqlite4_value_text(argv[0], 0);
   767    820       if( !z || parseDateOrTime(context, z, p) ){
   768    821         return 1;
   769    822       }
   770    823     }
................................................................................
   787    840   ** Return the julian day number of the date specified in the arguments
   788    841   */
   789    842   static void juliandayFunc(
   790    843     sqlite4_context *context,
   791    844     int argc,
   792    845     sqlite4_value **argv
   793    846   ){
          847  +  static const sqlite4_num ms_per_day = {0, 0, 0, 86400000};
   794    848     DateTime x;
          849  +
   795    850     if( isDate(context, argc, argv, &x)==0 ){
   796    851       computeJD(&x);
   797         -    sqlite4_result_double(context, x.iJD/86400000.0);
          852  +    sqlite4_result_num(context, 
          853  +        sqlite4_num_div(sqlite4_num_from_int64(x.iJD), ms_per_day)
          854  +    );
   798    855     }
   799    856   }
   800    857   
   801    858   /*
   802    859   **    datetime( TIMESTRING, MOD, MOD, ...)
   803    860   **
   804    861   ** Return YYYY-MM-DD HH:MM:SS
................................................................................
   809    866     sqlite4_value **argv
   810    867   ){
   811    868     DateTime x;
   812    869     if( isDate(context, argc, argv, &x)==0 ){
   813    870       char zBuf[100];
   814    871       computeYMD_HMS(&x);
   815    872       sqlite4_snprintf(zBuf,sizeof(zBuf), "%04d-%02d-%02d %02d:%02d:%02d",
   816         -                     x.Y, x.M, x.D, x.h, x.m, (int)(x.s));
          873  +        x.Y, x.M, x.D, x.h, x.m, (int)(sqlite4_num_to_int64(x.s,0))
          874  +    );
   817    875       sqlite4_result_text(context, zBuf, -1, SQLITE4_TRANSIENT, 0);
   818    876     }
   819    877   }
   820    878   
   821    879   /*
   822    880   **    time( TIMESTRING, MOD, MOD, ...)
   823    881   **
................................................................................
   828    886     int argc,
   829    887     sqlite4_value **argv
   830    888   ){
   831    889     DateTime x;
   832    890     if( isDate(context, argc, argv, &x)==0 ){
   833    891       char zBuf[100];
   834    892       computeHMS(&x);
   835         -    sqlite4_snprintf(zBuf,sizeof(zBuf), "%02d:%02d:%02d", x.h, x.m, (int)x.s);
          893  +    sqlite4_snprintf(zBuf,sizeof(zBuf), "%02d:%02d:%02d", x.h, x.m, 
          894  +        (int)(sqlite4_num_to_int64(x.s,0))
          895  +    );
   836    896       sqlite4_result_text(context, zBuf, -1, SQLITE4_TRANSIENT, 0);
   837    897     }
   838    898   }
   839    899   
   840    900   /*
   841    901   **    date( TIMESTRING, MOD, MOD, ...)
   842    902   **
................................................................................
   944   1004       if( zFmt[i]!='%' ){
   945   1005         z[j++] = zFmt[i];
   946   1006       }else{
   947   1007         i++;
   948   1008         switch( zFmt[i] ){
   949   1009           case 'd':  sqlite4_snprintf(&z[j],3,"%02d",x.D); j+=2; break;
   950   1010           case 'f': {
   951         -          double s = x.s;
   952         -          if( s>59.999 ) s = 59.999;
   953         -          j += sqlite4_snprintf(&z[j],7,"%06.3f", s);
         1011  +          sqlite4_num rnd = x.s;
         1012  +          int i1;
         1013  +          rnd.e += 3;
         1014  +          i1 = sqlite4_num_to_int64(rnd, 0);
         1015  +          j += sqlite4_snprintf(&z[j], 7, "%02d.%03d", i1 / 1000, i1 % 1000);
   954   1016             break;
   955   1017           }
   956   1018           case 'H':  sqlite4_snprintf(&z[j],3,"%02d",x.h); j+=2; break;
   957   1019           case 'W': /* Fall thru */
   958   1020           case 'j': {
   959   1021             int nDay;             /* Number of days since 1st day of year */
   960   1022             DateTime y = x;
................................................................................
   981   1043           case 'm':  sqlite4_snprintf(&z[j],3,"%02d",x.M); j+=2; break;
   982   1044           case 'M':  sqlite4_snprintf(&z[j],3,"%02d",x.m); j+=2; break;
   983   1045           case 's': {
   984   1046             j += sqlite4_snprintf(&z[j],30,"%lld",
   985   1047                                   (i64)(x.iJD/1000 - 21086676*(i64)10000));
   986   1048             break;
   987   1049           }
   988         -        case 'S':  sqlite4_snprintf(&z[j],3,"%02d",(int)x.s); j+=2; break;
         1050  +        case 'S':  
         1051  +          sqlite4_snprintf(&z[j], 3, "%02d", (int)sqlite4_num_to_int64(x.s, 0));
         1052  +          j+=2; 
         1053  +          break;
   989   1054           case 'w': {
   990   1055             z[j++] = (char)(((x.iJD+129600000)/86400000) % 7) + '0';
   991   1056             break;
   992   1057           }
   993   1058           case 'Y': {
   994   1059             sqlite4_snprintf(&z[j],5,"%04d",x.Y); j+=sqlite4Strlen30(&z[j]);
   995   1060             break;

Changes to src/func.c.

   266    266       if( SQLITE4_NULL==sqlite4_value_type(argv[1]) ) return;
   267    267       n = sqlite4_value_int(argv[1]);
   268    268       if( n>30 ) n = 30;
   269    269       if( n<0 ) n = 0;
   270    270     }
   271    271     if( sqlite4_value_type(argv[0])==SQLITE4_NULL ) return;
   272    272   
   273         -  num = sqlite4_value_num(argv[0]);
   274         -  p10 = (num.e*-1) - n;
   275         -  if( p10>0 ){
   276         -    int rnd;
   277         -    int i;
   278         -    u64 div = 1;
   279         -    for(i=0; i<p10; i++) div = div * 10;
   280         -    rnd = (num.m % div) >= (div/2);
   281         -    num.m = ((num.m / div) + rnd) * div;
   282         -  }
   283         -  num.approx = 0;
   284         -  sqlite4_result_num(context, num);
          273  +  sqlite4_result_num(context, sqlite4_num_round(sqlite4_value_num(argv[0]), n));
   285    274   }
   286    275   
   287    276   /*
   288    277   ** Allocate nByte bytes of space using sqlite4_malloc(). If the
   289    278   ** allocation fails, call sqlite4_result_error_nomem() to notify
   290    279   ** the database handle that malloc() has failed and return NULL.
   291    280   ** If nByte is larger than the maximum string or blob length, then

Changes to src/os.c.

    24     24   /*
    25     25   ** The following variable, if set to a non-zero value, is interpreted as
    26     26   ** the number of seconds since 1970 and is used to set the result of
    27     27   ** sqlite4OsCurrentTime() during testing.
    28     28   */
    29     29   unsigned int sqlite4_current_time = 0; /* Fake system time */
    30     30   int sqlite4OsCurrentTime(sqlite4_env *pEnv, sqlite4_uint64 *pTimeOut){
           31  +  static const sqlite4_uint64 unixEpoch = 24405875*(sqlite4_int64)8640000;
    31     32     int rc = SQLITE4_OK;
    32     33     if( sqlite4_current_time ){
    33         -    *pTimeOut = (sqlite4_uint64)sqlite4_current_time * 1000;
           34  +    *pTimeOut = unixEpoch + (sqlite4_uint64)sqlite4_current_time * 1000;
    34     35       return SQLITE4_OK;
    35     36     }
    36     37   #if SQLITE4_OS_UNIX
    37         -  static const sqlite4_int64 unixEpoch = 24405875*(sqlite4_int64)8640000;
    38     38     struct timeval sNow;
    39     39     if( gettimeofday(&sNow, 0)==0 ){
    40     40       *pTimeOut = unixEpoch + 1000*(sqlite4_int64)sNow.tv_sec + sNow.tv_usec/1000;
    41     41     }else{
    42     42       rc = SQLITE4_ERROR;
    43     43     }
    44     44     UNUSED_PARAMETER(pEnv);

Changes to test/date.test.

    65     65   datetest 1.23b julianday('12345.6') 12345.6
    66     66   datetest 1.24 {julianday('2001-01-01 12:00:00 bogus')} NULL
    67     67   datetest 1.25 {julianday('2001-01-01 bogus')} NULL
    68     68   datetest 1.26 {julianday('2001-01-01 12:60:00')} NULL
    69     69   datetest 1.27 {julianday('2001-01-01 12:59:60')} NULL
    70     70   datetest 1.28 {julianday('2001-00-01')} NULL
    71     71   datetest 1.29 {julianday('2001-01-00')} NULL
    72         -
    73     72   datetest 2.1 datetime(0,'unixepoch') {1970-01-01 00:00:00}
    74     73   datetest 2.1b datetime(0,'unixepoc') NULL
    75     74   datetest 2.1c datetime(0,'unixepochx') NULL
    76     75   datetest 2.1d datetime('2003-10-22','unixepoch') NULL
    77     76   datetest 2.2 datetime(946684800,'unixepoch') {2000-01-01 00:00:00}
    78     77   datetest 2.2b datetime('946684800','unixepoch') {2000-01-01 00:00:00}
    79     78   for {set i 0} {$i<1000} {incr i} {
................................................................................
   490    489   
   491    490   datetest 13.30 {date('2000-01-01','+1.5 years')} {2001-07-02}
   492    491   datetest 13.31 {date('2001-01-01','+1.5 years')} {2002-07-02}
   493    492   datetest 13.32 {date('2002-01-01','+1.5 years')} {2003-07-02}
   494    493   datetest 13.33 {date('2002-01-01','-1.5 years')} {2000-07-02}
   495    494   datetest 13.34 {date('2001-01-01','-1.5 years')} {1999-07-02}
   496    495   
   497         -# Test for issues reported by BareFeet (list.sql at tandb.com.au)
   498         -# on mailing list on 2008-06-12.
   499         -#
   500         -# Put a floating point number in the database so that we can manipulate
   501         -# raw bits using the hexio interface.
   502         -#
   503         -if {0==[sqlite4 -has-codec]} {
   504         -  do_test date-14.1 {
   505         -    execsql {
   506         -      PRAGMA auto_vacuum=OFF;
   507         -      PRAGMA page_size = 1024;
   508         -      CREATE TABLE t1(x);
   509         -      INSERT INTO t1 VALUES(1.1);
   510         -    }
   511         -    db close
   512         -    hexio_write test.db 2040 4142ba32bffffff9
   513         -    sqlite4 db test.db
   514         -    db eval {SELECT * FROM t1}
   515         -  } {2454629.5}
   516         -  
   517         -  # Changing the least significant byte of the floating point value between
   518         -  # 00 and FF should always generate a time of either 23:59:59 or 00:00:00,
   519         -  # never 24:00:00
   520         -  #
   521         -  for {set i 0} {$i<=255} {incr i} {
   522         -    db close
   523         -    hexio_write test.db 2047 [format %02x $i]
   524         -    sqlite4 db test.db
   525         -    do_test date-14.2.$i {
   526         -      set date [db one {SELECT datetime(x) FROM t1}]
   527         -      expr {$date eq "2008-06-12 00:00:00" || $date eq "2008-06-11 23:59:59"}
   528         -    } {1}
   529         -  }
   530         -}
   531    496   finish_test

Changes to test/permutations.test.

   156    156     coalesce.test 
   157    157     collate1.test collate2.test collate3.test collate4.test collate5.test
   158    158     collate6.test collate7.test collate8.test collate9.test collateA.test
   159    159     conflict.test 
   160    160     count.test
   161    161     cse.test
   162    162     ctime.test
          163  +  date.test
   163    164     delete.test delete2.test
   164    165     distinct.test distinctagg.test
   165    166     exists.test
   166    167     e_droptrigger.test e_dropview.test
   167    168     e_resolve.test e_dropview.test
   168    169     e_select2.test
   169    170     enc4.test