aboutsummaryrefslogtreecommitdiff
path: root/src/date.c
diff options
context:
space:
mode:
authordrh <>2023-06-13 16:55:24 +0000
committerdrh <>2023-06-13 16:55:24 +0000
commitd34ce818676003c31ae59f643336756665a1d9cc (patch)
tree6c6a36c4abf06d11d8a1e150e13cf131fb9840de /src/date.c
parentd97e0d0e389448b08b7a875e31e6c2bdb4242b09 (diff)
downloadsqlite-d34ce818676003c31ae59f643336756665a1d9cc.tar.gz
sqlite-d34ce818676003c31ae59f643336756665a1d9cc.zip
Extended the time-diff format so that it can have a 5-digit year. This enables
time differences to span the full range of dates supported by SQLite. Also fix some inaccuracies in the computation of time differences and add new test cases. FossilOrigin-Name: d57ddbf4eeeb3ccfe31871f098045b9e58634153a3c3030f597cb58c1177218a
Diffstat (limited to 'src/date.c')
-rw-r--r--src/date.c33
1 files changed, 21 insertions, 12 deletions
diff --git a/src/date.c b/src/date.c
index b56df143d..b7391c2c0 100644
--- a/src/date.c
+++ b/src/date.c
@@ -110,8 +110,8 @@ struct DateTime {
*/
static int getDigits(const char *zDate, const char *zFormat, ...){
/* The aMx[] array translates the 3rd character of each format
- ** spec into a max size: a b c d e f */
- static const u16 aMx[] = { 12, 14, 24, 31, 59, 9999 };
+ ** spec into a max size: a b c d e f */
+ static const u16 aMx[] = { 12, 14, 24, 31, 59, 14712 };
va_list ap;
int cnt = 0;
char nextC;
@@ -872,10 +872,14 @@ static int parseModifier(
int i;
int Y,M,D,h,m,x;
const char *z2 = z;
+ char z0 = z[0];
for(n=1; z[n]; n++){
if( z[n]==':' ) break;
if( sqlite3Isspace(z[n]) ) break;
- if( z[n]=='-' && n==5 && getDigits(&z[1], "40f", &Y)==1 ) break;
+ if( z[n]=='-' ){
+ if( n==5 && getDigits(&z[1], "40f", &Y)==1 ) break;
+ if( n==6 && getDigits(&z[1], "50f", &Y)==1 ) break;
+ }
}
if( sqlite3AtoF(z, &r, n, SQLITE_UTF8)<=0 ){
rc = 1;
@@ -886,14 +890,19 @@ static int parseModifier(
** specified number of years, months, and days. MM is limited to
** the range 0-11 and DD is limited to 0-30.
*/
- if( z[0]!='+' && z[0]!='-' ) break; /* Must start with +/- */
- if( NEVER(n!=5) ) break; /* Must be 4-digit YYYY */
- if( getDigits(&z[1], "40f-20a-20d", &Y, &M, &D)!=3 ) break;
+ if( z0!='+' && z0!='-' ) break; /* Must start with +/- */
+ if( n==5 ){
+ if( getDigits(&z[1], "40f-20a-20d", &Y, &M, &D)!=3 ) break;
+ }else{
+ assert( n==6 );
+ if( getDigits(&z[1], "50f-20a-20d", &Y, &M, &D)!=3 ) break;
+ z++;
+ }
if( M>=12 ) break; /* M range 0..11 */
if( D>=31 ) break; /* D range 0..30 */
computeYMD_HMS(p);
p->validJD = 0;
- if( z[0]=='-' ){
+ if( z0=='-' ){
p->Y -= Y;
p->M -= M;
D = -D;
@@ -937,7 +946,7 @@ static int parseModifier(
tx.iJD -= 43200000;
day = tx.iJD/86400000;
tx.iJD -= day*86400000;
- if( z[0]=='-' ) tx.iJD = -tx.iJD;
+ if( z0=='-' ) tx.iJD = -tx.iJD;
computeJD(p);
clearYMD_HMS_TZ(p);
p->iJD += tx.iJD;
@@ -1404,7 +1413,7 @@ static void timediffFunc(
int Y, M;
DateTime d1, d2;
sqlite3_str sRes;
- if( isDate(context, 1, argv, &d1) ) return;
+ if( isDate(context, 1, &argv[0], &d1) ) return;
if( isDate(context, 1, &argv[1], &d2) ) return;
computeYMD_HMS(&d1);
computeYMD_HMS(&d2);
@@ -1426,7 +1435,7 @@ static void timediffFunc(
d2.validJD = 0;
computeJD(&d2);
}
- if( d1.iJD<d2.iJD ){
+ while( d1.iJD<d2.iJD ){
M--;
if( M<0 ){
M = 11;
@@ -1442,7 +1451,7 @@ static void timediffFunc(
}
d1.iJD -= d2.iJD;
d1.iJD += 148699540800000;
- }else{
+ }else /* d1<d2 */{
sign = '-';
Y = d2.Y - d1.Y;
if( Y ){
@@ -1460,7 +1469,7 @@ static void timediffFunc(
d2.validJD = 0;
computeJD(&d2);
}
- if( d1.iJD>d2.iJD ){
+ while( d1.iJD>d2.iJD ){
M--;
if( M<0 ){
M = 11;