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
This commit is contained in:
drh 2023-06-13 16:55:24 +00:00
parent d97e0d0e38
commit d34ce81867
4 changed files with 109 additions and 27 deletions

View File

@ -1,5 +1,5 @@
C Initialize\sa\slocal\svariable\sin\sFTS3\sto\savoid\sa\sGCC\scompiler\swarning.
D 2023-06-12T18:22:34.021
C Extended\sthe\stime-diff\sformat\sso\sthat\sit\scan\shave\sa\s5-digit\syear.\s\sThis\senables\ntime\sdifferences\sto\sspan\sthe\sfull\srange\sof\sdates\ssupported\sby\sSQLite.\s\sAlso\nfix\ssome\sinaccuracies\sin\sthe\scomputation\sof\stime\sdifferences\sand\sadd\snew\ntest\scases.
D 2023-06-13T16:55:24.318
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -582,7 +582,7 @@ F src/build.c cb54df6fd018a18e940a251c5e31780ffba8bc6c7a01e670b96a489adcbfb3b4
F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 20507cc0b0a6c19cd882fcd0eaeda32ae6a4229fb4b024cfdf3183043d9b703d
F src/date.c 6e9549239d08957ffeff481bb131d071c969833b230d1dbfb836cf9dab1501b8
F src/date.c 17e090a9cd6355b625a0a242f2ce4b2898171c6c5ff725863ca4ce73f1e99bb1
F src/dbpage.c f3eea5f7ec47e09ee7da40f42b25092ecbe961fc59566b8e5f705f34335b2387
F src/dbstat.c ec92074baa61d883de58c945162d9e666c13cd7cf3a23bc38b4d1c4d0b2c2bef
F src/delete.c 1b00589aa4f2c50beba39f9da5166fc2161234580ea8c0d087b6d5c2c7a17c21
@ -1570,7 +1570,7 @@ F test/threadtest3.c 655bff6c0895ec03f014126aa65e808fac9aae8c5a7a7da58a510cbe8b4
F test/threadtest4.c c1e67136ceb6c7ec8184e56ac61db28f96bd2925
F test/threadtest5.c 9b4d782c58d8915d7e955ff8051f3d03628bda0d33b82971ea8c0f2f2808c421
F test/time-wordcount.sh 8e0b0f8109367827ad5d58f5cc849705731e4b90
F test/timediff1.test 635b0e1857d1a3519382ae1a0aff9580c33e550c5a5cbec600b5edd2e0487018
F test/timediff1.test d982b2b5f1b22f58380c5db94ea5b17518d50ad0c55583cf0ecfa0b176e20888
F test/tkt-02a8e81d44.test 6c80d9c7514e2a42d4918bf87bf6bc54f379110c
F test/tkt-18458b1a.test 6a62cb1ee50fa3c620da59e3a6f531eb38fceaf7e2166203816b724524e6f1d6
F test/tkt-26ff0c2d1e.test c15bec890c4d226c0da2f35ff30f9e84c169cfef90e73a8cb5cec11d723dfa96
@ -2040,8 +2040,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 56d9bb7aa63043f5db4a1e5e8eefe46762dba433145807c6e27a8316f1d03d7a
R 8fa7f071c843431d341c04b5f54d842f
P 7ec4ab327decd6a5ee5e6a53f1489e17e0cdbb297945f9acc532b47d052eb7a9
R f3cf6d8b6e100bd0de96bfa9b873d378
U drh
Z 7056ecfd0821d02702a7f5f171a36595
Z ebd3034b7be8eaa213c6784b968c66ce
# Remove this line to create a well-formed Fossil manifest.

View File

@ -1 +1 @@
7ec4ab327decd6a5ee5e6a53f1489e17e0cdbb297945f9acc532b47d052eb7a9
d57ddbf4eeeb3ccfe31871f098045b9e58634153a3c3030f597cb58c1177218a

View File

@ -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;

View File

@ -79,13 +79,16 @@ datetest 3.4 {timediff('1999-01-31','2000-03-02')} {-0001-01-02 00:00:00.000}
unset -nocomplain p1
unset -nocomplain p2
set p1 {
1 {0000-01-01 12:34:56}
2 {1776-07-04 13:00:00}
3 {1969-07-20 20:17}
4 {2440587.5}
5 {2000-05-29 14:26}
6 {2023-05-29 18:11}
7 {2050-05-29 14:26}
0 {-4713-11-24 12:00:00}
1 {-2000-04-30 05:19:26}
2 {0000-01-01 12:34:56}
3 {1776-07-04 13:00:00}
4 {1969-07-20 20:17}
5 {2440587.5}
6 {2000-05-29 14:26}
7 {2023-05-29 18:11}
8 {2050-05-29 14:26}
9 {4796-02-29 11:23:55.46}
}
set p2 {
A {1066-10-14}
@ -102,6 +105,8 @@ set p2 {
K {2006-06-30 01:23:45}
L {2007-12-31 02:00}
M {2008-01-01 01:59}
N {3152-07-04 12:00}
P {9999-12-31 23:59:59}
}
foreach {x1 d1} $p1 {
@ -144,6 +149,74 @@ datetest 5-18 {datetime('2000-01-01','+0001-02-03 01:02:03.500')} \
datetest 5-19 {datetime('2000-01-01','+0001-02-03 01:02:03.500x')} {NULL}
datetest 5-20 {datetime('2000-01-01','+0001-02-03 01:02:03.500 x')} {NULL}
unset -nocomplain p1
unset -nocomplain p2
set p1 {
a {2000-01-01 00:00:00}
b {2000-01-31 23:59:59}
c {2000-02-01 00:00:00}
d {2000-02-29 23:59:59}
e {2000-03-01 00:00:00}
f {2000-03-31 23:59:59}
g {2000-04-01 00:00:00}
h {2000-04-30 23:59:59}
i {2000-05-01 00:00:00}
j {2000-05-31 23:59:59}
k {2000-06-01 00:00:00}
l {2000-06-30 23:59:59}
m {2000-07-01 00:00:00}
n {2000-07-31 23:59:59}
o {2000-08-01 00:00:00}
p {2000-08-31 23:59:59}
q {2000-09-01 00:00:00}
r {2000-09-30 23:59:59}
s {2000-10-01 00:00:00}
t {2000-10-31 23:59:59}
u {2000-11-01 00:00:00}
v {2000-11-30 23:59:59}
w {2000-12-01 00:00:00}
x {2000-12-31 23:59:59}
}
set p2 {
A {2001-01-01 00:00:00}
B {2001-01-31 23:59:59}
C {2001-02-01 00:00:00}
D {2001-02-28 23:59:59}
E {2001-03-01 00:00:00}
F {2001-03-31 23:59:59}
G {2001-04-01 00:00:00}
H {2001-04-30 23:59:59}
I {2001-05-01 00:00:00}
J {2001-05-31 23:59:59}
K {2001-06-01 00:00:00}
L {2001-06-30 23:59:59}
M {2001-07-01 00:00:00}
N {2001-07-31 23:59:59}
O {2001-08-01 00:00:00}
P {2001-08-31 23:59:59}
Q {2001-09-01 00:00:00}
R {2001-09-30 23:59:59}
S {2001-10-01 00:00:00}
T {2001-10-31 23:59:59}
U {2001-11-01 00:00:00}
V {2001-11-30 23:59:59}
W {2001-12-01 00:00:00}
X {2001-12-31 23:59:59}
}
foreach {x1 d1} $p1 {
foreach {x2 d2} $p2 {
set r1 [db one {SELECT datetime($d1)}]
do_execsql_test timediff-6-$x1$x2 {
SELECT datetime($d2, timediff($d1,$d2));
} [list $r1]
set r2 [db one {SELECT datetime($d2)}]
do_execsql_test timediff-6-$x2$x1 {
SELECT datetime($d1, timediff($d2,$d1));
} [list $r2]
}
}
finish_test