]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Extended the time-diff format so that it can have a 5-digit year. This enables
authordrh <>
Tue, 13 Jun 2023 16:55:24 +0000 (16:55 +0000)
committerdrh <>
Tue, 13 Jun 2023 16:55:24 +0000 (16:55 +0000)
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

manifest
manifest.uuid
src/date.c
test/timediff1.test

index 2ce07468a7f7464a4a249d3f374e43ab8dc32719..5b5233e0049959755b1e46440c0b8356f0789d7f 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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.
index 5c659b28a738f75a1ebd88e9775331dcd2a755f7..eaac64c495d9becd3e4d857427a7cee11fc99cee 100644 (file)
@@ -1 +1 @@
-7ec4ab327decd6a5ee5e6a53f1489e17e0cdbb297945f9acc532b47d052eb7a9
\ No newline at end of file
+d57ddbf4eeeb3ccfe31871f098045b9e58634153a3c3030f597cb58c1177218a
\ No newline at end of file
index b56df143dcaac19b682b1a2fc72cb19687f63a8b..b7391c2c03a0ebe8f364e0baa57f01c77d613861 100644 (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;
index 79000af1d4aa0689323c4eb8faad37446690b26c..f8176d8810824b6b4880f85917713b0e6a62cab2 100644 (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