1
0
mirror of https://github.com/sqlite/sqlite.git synced 2026-10-28 10:57:26 +03:00

Enhancements to date/time functions: The "weekday -N" modifier moves

the date backward in time.  The "end of day/month/year" modifiers added.

FossilOrigin-Name: 88901fffcd445ccb97e4e379ea15d8b06d87b8170cad0f717c909944ff21851f
This commit is contained in:
drh
2026-07-01 12:11:41 +00:00
4 changed files with 141 additions and 29 deletions

View File

@@ -1,5 +1,5 @@
C Add\snew\sassert()s\sto\shelp\sstatic\sanalyzers\srealize\sthat\sthe\scode\sis\scorrect.
D 2026-06-29T15:11:58.186
C Enhancements\sto\sdate/time\sfunctions:\s\sThe\s"weekday\s-N"\smodifier\smoves\nthe\sdate\sbackward\sin\stime.\s\sThe\s"end\sof\sday/month/year"\smodifiers\sadded.
D 2026-07-01T12:11:41.802
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -686,7 +686,7 @@ F src/build.c 86e97b26600535ab9dffd780ecbdb1560362e81bd2e9bcb179b52b2050c3302b
F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804ad
F src/carray.c 3efe3982d5fb323334c29328a4e189ccaef6b95612a6084ad5fa124fd5db1179
F src/complete.c f216b970ce99c5a657556cf1f17e7ddd494515d3beb63df426bf59ff43bd3d9a
F src/date.c 86d9530729eeb5b3d833e7403de495f4d4b79f3d5f7e74bcc8abda237f5aeafb
F src/date.c 46a518e94cd9c6d0ba1cc4d9af50bcd112a1e24a942e82a35235701731e9b042
F src/dbpage.c c6a9de13b0a01f0bc94a41e16213ab1ecd15ccfe86df7255ced40fda9446257d
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 59eeca3fb88c29329afc41bb803ee568b120d9dd7470b5f38ab55cc38390b451
@@ -1036,7 +1036,7 @@ F test/ctime.test 340f362f41f92972bbd71f44e10569a5cc694062b692231bd08aa6fe6c1c47
F test/cursorhint.test d8b93ac48dfdb2cf4284142710d63e860b6497afff2e9c525daf752a229e5b97
F test/cursorhint2.test a10f29c0c52d4d73c19cf639f3c33cccbf5024bcf950fa48f2a8cdc14628b985
F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68ccf2a7bb8
F test/date.test 328ed63091d34c8a6e8dcec4f999a031ce310f24395b8f0f67f07eaf36cbfd1f
F test/date.test 0c362a642cf3520a14eed6098faa454cd5def17c592c8dd4aa06894ca7e7ad5a
F test/date2.test 7e12ec14aaf4d5e6294b4ba140445b0eca06ea50062a9c3a69c4ee13d0b6f8b1
F test/date3.test a1b77abf05c6772fe5ca2337cac1398892f2a41e62bce7e6be0f4a08a0e64ae5
F test/date4.test b5ad22baf7394e008ac59383840159daedd45be31dcf74a3b2450ec0e28955ce
@@ -2210,8 +2210,9 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
P 3e80958a7052a123f4599d64baa8cc31a761e5a58d04c75ca38f2a375d247808
R 6e225e2a5b21c61670a4cf3bac94cdef
P 007f0496619e571092382a3668b6bbcc17919908895dc4be71f8d1b6ec2aeeed 2c4cb3223c6c56d05fe91b8d19b60eac26a274e41f34a2d8f2cf911927581932
R 1e8cc3c2fef8cd515a643be551bc5111
T +closed 2c4cb3223c6c56d05fe91b8d19b60eac26a274e41f34a2d8f2cf911927581932
U drh
Z 2f447aaf8cc29ef8d2182c61654b2dfa
Z 72253f088d1bca64ce0c9a09dc87f11f
# Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
007f0496619e571092382a3668b6bbcc17919908895dc4be71f8d1b6ec2aeeed
88901fffcd445ccb97e4e379ea15d8b06d87b8170cad0f717c909944ff21851f

View File

@@ -767,6 +767,49 @@ static int parseModifier(
}
break;
}
case 'e': {
/*
** end of day
** end of month
** end of year
**
** Move the date forwards to the last millisecond of the current
** day, month or year.
*/
if( sqlite3_strnicmp(z, "end of ", 7)!=0 ){
break;
}
if( !p->validJD && !p->validYMD && !p->validHMS ) break;
z += 7;
computeYMD(p);
p->validHMS = 1;
p->h = 23;
p->m = 59;
p->s = 59.999;
p->rawS = 0;
p->tz = 0;
p->validJD = 0;
if( sqlite3_stricmp(z,"month")==0 ){
p->D = 1;
p->M++;
if( p->M>12 ){
p->Y++;
p->M = 1;
}
computeFloor(p);
computeJD(p);
p->iJD -= (p->nFloor+1)*86400000;
clearYMD_HMS_TZ(p);
rc = 0;
}else if( sqlite3_stricmp(z,"year")==0 ){
p->M = 12;
p->D = 31;
rc = 0;
}else if( sqlite3_stricmp(z,"day")==0 ){
rc = 0;
}
break;
}
case 'f': {
/*
** floor
@@ -869,22 +912,30 @@ static int parseModifier(
case 'w': {
/*
** weekday N
** weekday -N
**
** Move the date to the same time on the next occurrence of
** weekday N where 0==Sunday, 1==Monday, and so forth. If the
** date is already on the appropriate weekday, this is a no-op.
** Move the date forward (for N>=0) or backward (for N<=-0) to the
** same time on the next/previous occurrence of weekday abs(N)
** where 0==Sunday, 1==Monday, and so forth. If the date is already
** on the appropriate weekday, this is a no-op.
*/
if( sqlite3_strnicmp(z, "weekday ", 8)==0
&& sqlite3AtoF(&z[8], &r)>0
&& r>=0.0 && r<7.0 && (n=(int)r)==r ){
&& sqlite3AtoF(&z[8], &r)>0
&& r>=-6.0 && r<=6.0
&& (n=(int)r)==r
){
sqlite3_int64 Z;
computeYMD_HMS(p);
p->tz = 0;
p->validJD = 0;
computeJD(p);
Z = ((p->iJD + 129600000)/86400000) % 7;
if( Z>n ) Z -= 7;
p->iJD += (n - Z)*86400000;
if( n<0 ) n = -n;
if( Z!=n ){
if( Z>n ) Z -= 7;
p->iJD += (n - Z)*86400000;
if( strchr(z+8,'-')!=0 ) p->iJD -= 7*86400000;
}
clearYMD_HMS_TZ(p);
rc = 0;
}
@@ -892,7 +943,9 @@ static int parseModifier(
}
case 's': {
/*
** start of TTTTT
** start of day
** start of month
** start of year
**
** Move the date backwards to the beginning of the current day,
** or month or year.

View File

@@ -81,29 +81,51 @@ for {set i 0} {$i<1000} {incr i} {
set res [format {06:28:00.%03d} $i]
datetest 2.2c-$i $sql $res
}
datetest 2.3 {date('2003-10-22','weekday 0')} 2003-10-26
datetest 2.4 {date('2003-10-22','weekday 1')} 2003-10-27
datetest 2.3 {date('2003-10-22','weekday 0')} 2003-10-26
datetest 2.3b {date('2003-10-22','weekday -0')} 2003-10-19
datetest 2.4 {date('2003-10-22','weekday 1')} 2003-10-27
datetest 2.4a {date('2003-10-22','weekday 1')} 2003-10-27
datetest 2.4b {date('2003-10-22','weekday 1x')} NULL
datetest 2.4c {date('2003-10-22','weekday -1')} NULL
datetest 2.4d {date('2003-10-22','weakday 1x')} NULL
datetest 2.4c {date('2003-10-22','weekday -1')} 2003-10-20
datetest 2.4d {date('2003-10-22','weakday -1x')} NULL
datetest 2.4e {date('2003-10-22','weekday ')} NULL
datetest 2.5 {date('2003-10-22','weekday 2')} 2003-10-28
datetest 2.6 {date('2003-10-22','weekday 3')} 2003-10-22
datetest 2.7 {date('2003-10-22','weekday 4')} 2003-10-23
datetest 2.8 {date('2003-10-22','weekday 5')} 2003-10-24
datetest 2.9 {date('2003-10-22','weekday 6')} 2003-10-25
datetest 2.10 {date('2003-10-22','weekday 7')} NULL
datetest 2.11 {date('2003-10-22','weekday 5.5')} NULL
datetest 2.5 {date('2003-10-22','weekday 2')} 2003-10-28
datetest 2.5b {date('2003-10-22','weekday -2')} 2003-10-21
datetest 2.5c {date('2003-10-23','weekday 2')} 2003-10-28
datetest 2.5d {date('2003-10-24','weekday 2')} 2003-10-28
datetest 2.5e {date('2003-10-25','weekday 2')} 2003-10-28
datetest 2.5f {date('2003-10-26','weekday 2')} 2003-10-28
datetest 2.5g {date('2003-10-27','weekday 2')} 2003-10-28
datetest 2.5h {date('2003-10-28','weekday 2')} 2003-10-28
datetest 2.6 {date('2003-10-22','weekday 3')} 2003-10-22
datetest 2.6b {date('2003-10-22','weekday -3')} 2003-10-22
datetest 2.7 {date('2003-10-22','weekday 4')} 2003-10-23
datetest 2.7b {date('2003-10-22','weekday -4')} 2003-10-16
datetest 2.8 {date('2003-10-22','weekday 5')} 2003-10-24
datetest 2.8b {date('2003-10-22','weekday -5')} 2003-10-17
datetest 2.9 {date('2003-10-22','weekday 6')} 2003-10-25
datetest 2.9b {date('2003-10-22','weekday -6')} 2003-10-18
datetest 2.10 {date('2003-10-22','weekday 7')} NULL
datetest 2.10b {date('2003-10-22','weekday -7')} NULL
datetest 2.11 {date('2003-10-22','weekday 5.5')} NULL
datetest 2.11b {date('2003-10-22','weekday -5.5')} NULL
datetest 2.12 {datetime('2003-10-22 12:34','weekday 0')} {2003-10-26 12:34:00}
datetest 2.13 {datetime('2003-10-22 12:34','start of month')} \
{2003-10-01 00:00:00}
datetest 2.13b {datetime('2003-10-22 12:34','end of month')} \
{2003-10-31 23:59:59}
datetest 2.14 {datetime('2003-10-22 12:34','start of year')} \
{2003-01-01 00:00:00}
datetest 2.14b {datetime('2003-10-22 12:34','end of year')} \
{2003-12-31 23:59:59}
datetest 2.15 {datetime('2003-10-22 12:34','start of day')} \
{2003-10-22 00:00:00}
datetest 2.15a {datetime('2003-10-22 12:34','start of')} NULL
datetest 2.15b {datetime('2003-10-22 12:34','start of bogus')} NULL
datetest 2.15b {datetime('2003-10-22 12:34','end of day','subsec')} \
{2003-10-22 23:59:59.999}
datetest 2.15c {datetime('2003-10-22 12:34','start of')} NULL
datetest 2.15d {datetime('2003-10-22 12:34','start of bogus')} NULL
datetest 2.15e {datetime('2003-10-22 12:34','end of')} NULL
datetest 2.15f {datetime('2003-10-22 12:34','end of bogus')} NULL
datetest 2.16 time('12:34:56.43') 12:34:56
datetest 2.17 {datetime('2003-10-22 12:34','1 day')} {2003-10-23 12:34:00}
datetest 2.18 {datetime('2003-10-22 12:34','+1 day')} {2003-10-23 12:34:00}
@@ -680,4 +702,40 @@ datetest 20.2 {datetime('2024-12-31 23:59:59.9999999999999')} \
datetest 20.3 {datetime('2024-12-31 23:59:59.9995')} {2024-12-31 23:59:59}
datetest 20.4 {datetime('2024-12-31 23:59:58.9995')} {2024-12-31 23:59:58}
# 2026-07-01
# Additional tests for the new "weekday -N" and "end of ..." modifiers.
#
datetest 21.1 {date('2026-07-04','weekday +0')} {2026-07-05}
datetest 21.2 {date('2026-07-05','weekday -0')} {2026-07-05}
datetest 21.3 {date('2026-07-04','weekday -0')} {2026-06-28}
datetest 21.4 {date('2026-07-03','weekday -0')} {2026-06-28}
datetest 21.5 {date('2026-07-02','weekday -0')} {2026-06-28}
datetest 21.6 {date('2026-07-01','weekday -0')} {2026-06-28}
datetest 21.7 {date('2026-06-30','weekday -0')} {2026-06-28}
datetest 21.8 {date('2026-06-29','weekday -0')} {2026-06-28}
datetest 21.9 {date('2026-06-28','weekday -0')} {2026-06-28}
datetest 21.10 {date('2026-07-05','weekday +0')} {2026-07-05}
datetest 21.11 {date('2026-07-04','weekday +0')} {2026-07-05}
datetest 21.12 {date('2026-07-03','weekday +0')} {2026-07-05}
datetest 21.13 {date('2026-07-02','weekday +0')} {2026-07-05}
datetest 21.14 {date('2026-07-01','weekday +0')} {2026-07-05}
datetest 21.15 {date('2026-06-30','weekday +0')} {2026-07-05}
datetest 21.16 {date('2026-06-29','weekday +0')} {2026-07-05}
datetest 21.17 {date('2026-06-28','weekday +0')} {2026-06-28}
datetest 22.1 {datetime('2026-02-17 12:34','end of day','subsec')} \
{2026-02-17 23:59:59.999}
datetest 22.2 {datetime('2026-02-17 12:34','end of month','subsec')} \
{2026-02-28 23:59:59.999}
datetest 22.3 {datetime('2024-02-17 12:34','end of month','subsec')} \
{2024-02-29 23:59:59.999}
datetest 22.4 {datetime('1900-02-17 12:34','end of month','subsec')} \
{1900-02-28 23:59:59.999}
datetest 22.5 {datetime('2026-12-17 12:34','end of month','subsec')} \
{2026-12-31 23:59:59.999}
datetest 22.6 {datetime('2026-02-17 12:34','end of year','subsec')} \
{2026-12-31 23:59:59.999}
datetest 22.7 {datetime('2026-02-17 12:34','end of time','subsec')} {NULL}
finish_test