From 9df3488964aa2bd9f0356bc773dad354ffd7e180 Mon Sep 17 00:00:00 2001 From: Nuno Cruces Date: Mon, 22 Jan 2024 09:38:39 +0000 Subject: [PATCH] Backport ISO week from 3.46. --- embed/sqlite3.wasm | Bin 1498416 -> 1498944 bytes sqlite3/isoweek.patch | 195 ++++++++++++++++++++++++++++++++----- sqlite3/locking_mode.patch | 2 +- sqlite3/vfs_find.patch | 2 +- tests/time_test.go | 26 +---- 5 files changed, 178 insertions(+), 47 deletions(-) diff --git a/embed/sqlite3.wasm b/embed/sqlite3.wasm index 84f6e818c2c68f6e2772489e9276e929b2d2b09d..f502e2b604c3d569ae0e117b42ba76fe10707514 100755 GIT binary patch delta 5176 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 delta 4729 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 ); ++ jan01.validJD = 0; ++ jan01.M = 1; ++ jan01.D = 1; ++ computeJD(&jan01); ++ return (int)((pDate->iJD-jan01.iJD+43200000)/86400000); ++} ++ ++/* ++** Return the number of days after the most recent Monday. ++** ++** In other words, return the day of the week according ++** to this code: ++** ++** 0=Monday, 1=Tuesday, 2=Wednesday, ..., 6=Sunday. ++*/ ++static int daysAfterMonday(DateTime *pDate){ ++ assert( pDate->validJD ); ++ return (int)((pDate->iJD+43200000)/86400000) % 7; ++} ++ ++/* ++** Return the number of days after the most recent Sunday. ++** ++** In other words, return the day of the week according ++** to this code: ++** ++** 0=Sunday, 1=Monday, 2=Tues, ..., 6=Saturday ++*/ ++static int daysAfterSunday(DateTime *pDate){ ++ assert( pDate->validJD ); ++ return (int)((pDate->iJD+129600000)/86400000) % 7; ++} ++ ++/* + ** strftime( FORMAT, TIMESTRING, MOD, MOD, ...) + ** + ** Return a string described by FORMAT. Conversions as follows: + ** +-** %d day of month ++** %d day of month 01-31 ++** %e day of month 1-31 + ** %f ** fractional seconds SS.SSS ++** %F ISO date. YYYY-MM-DD ++** %G ISO year corresponding to %V 0000-9999. ++** %g 2-digit ISO year corresponding to %V 00-99 + ** %H hour 00-24 +-** %j day of year 000-366 ++** %k hour 0-24 (leading zero converted to space) ++** %I hour 01-12 ++** %j day of year 001-366 + ** %J ** julian day number ++** %l hour 1-12 (leading zero converted to space) + ** %m month 01-12 + ** %M minute 00-59 ++** %p "am" or "pm" ++** %P "AM" or "PM" ++** %R time as HH:MM + ** %s seconds since 1970-01-01 + ** %S seconds 00-59 +-** %w day of week 0-6 Sunday==0 +-** %W week of year 00-53 ++** %T time as HH:MM:SS ++** %u day of week 1-7 Monday==1, Sunday==7 ++** %w day of week 0-6 Sunday==0, Monday==1 ++** %U week of year 00-53 (First Sunday is start of week 01) ++** %V week of year 01-53 (First week containing Thursday is week 01) ++** %W week of year 00-53 (First Monday is start of week 01) + ** %Y year 0000-9999 + ** %% % + */ +@@ -25391,7 +25452,7 @@ + sqlite3_str_appendf(&sRes, cf=='d' ? "%02d" : "%2d", x.D); break; } -+ case 'V': /* Fall thru */ -+ case 'G': { +- case 'f': { ++ case 'f': { /* Fractional seconds. (Non-standard) */ + double s = x.s; + if( s>59.999 ) s = 59.999; + sqlite3_str_appendf(&sRes, "%06.3f", s); +@@ -25401,6 +25462,21 @@ + sqlite3_str_appendf(&sRes, "%04d-%02d-%02d", x.Y, x.M, x.D); + break; + } ++ case 'G': /* Fall thru */ ++ case 'g': { + DateTime y = x; -+ computeJD(&y); ++ assert( y.validJD ); ++ /* Move y so that it is the Thursday in the same week as x */ ++ y.iJD += (3 - daysAfterMonday(&x))*86400000; + y.validYMD = 0; -+ /* Adjust date to Thursday this week: -+ The number in parentheses is 0 for Monday, 3 for Thursday */ -+ y.iJD += (3 - (((y.iJD+43200000)/86400000) % 7))*86400000; + computeYMD(&y); -+ if( cf=='G' ){ -+ sqlite3_str_appendf(&sRes,"%04d",y.Y); ++ if( cf=='g' ){ ++ sqlite3_str_appendf(&sRes, "%02d", y.Y%100); + }else{ -+ int nDay; /* Number of days since 1st day of year */ -+ i64 tJD = y.iJD; -+ y.validJD = 0; -+ y.M = 1; -+ y.D = 1; -+ computeJD(&y); -+ nDay = (int)((tJD-y.iJD+43200000)/86400000); -+ sqlite3_str_appendf(&sRes,"%02d",nDay/7+1); ++ sqlite3_str_appendf(&sRes, "%04d", y.Y); + } + break; + } - case 'Y': { - sqlite3_str_appendf(&sRes,"%04d",x.Y); + case 'H': + case 'k': { + sqlite3_str_appendf(&sRes, cf=='H' ? "%02d" : "%2d", x.h); +@@ -25414,25 +25490,11 @@ + sqlite3_str_appendf(&sRes, cf=='I' ? "%02d" : "%2d", h); break; + } +- case 'W': /* Fall thru */ +- case 'j': { +- int nDay; /* Number of days since 1st day of year */ +- DateTime y = x; +- y.validJD = 0; +- y.M = 1; +- y.D = 1; +- computeJD(&y); +- nDay = (int)((x.iJD-y.iJD+43200000)/86400000); +- if( cf=='W' ){ +- int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */ +- wd = (int)(((x.iJD+43200000)/86400000)%7); +- sqlite3_str_appendf(&sRes,"%02d",(nDay+7-wd)/7); +- }else{ +- sqlite3_str_appendf(&sRes,"%03d",nDay+1); +- } ++ case 'j': { /* Day of year. Jan01==1, Jan02==2, and so forth */ ++ sqlite3_str_appendf(&sRes,"%03d",daysAfterJan01(&x)+1); + break; + } +- case 'J': { ++ case 'J': { /* Julian day number. (Non-standard) */ + sqlite3_str_appendf(&sRes,"%.16g",x.iJD/86400000.0); + break; + } +@@ -25475,11 +25537,31 @@ + sqlite3_str_appendf(&sRes,"%02d:%02d:%02d", x.h, x.m, (int)x.s); + break; + } +- case 'u': /* Fall thru */ +- case 'w': { +- char c = (char)(((x.iJD+129600000)/86400000) % 7) + '0'; ++ case 'u': /* Day of week. 1 to 7. Monday==1, Sunday==7 */ ++ case 'w': { /* Day of week. 0 to 6. Sunday==0, Monday==1 */ ++ char c = (char)daysAfterSunday(&x) + '0'; + if( c=='0' && cf=='u' ) c = '7'; + sqlite3_str_appendchar(&sRes, 1, c); ++ break; ++ } ++ case 'U': { /* Week num. 00-53. First Sun of the year is week 01 */ ++ sqlite3_str_appendf(&sRes,"%02d", ++ (daysAfterJan01(&x)-daysAfterSunday(&x)+7)/7); ++ break; ++ } ++ case 'V': { /* Week num. 01-53. First week with a Thur is week 01 */ ++ DateTime y = x; ++ /* Adjust y so that is the Thursday in the same week as x */ ++ assert( y.validJD ); ++ y.iJD += (3 - daysAfterMonday(&x))*86400000; ++ y.validYMD = 0; ++ computeYMD(&y); ++ sqlite3_str_appendf(&sRes,"%02d", daysAfterJan01(&y)/7+1); ++ break; ++ } ++ case 'W': { /* Week num. 00-53. First Mon of the year is week 01 */ ++ sqlite3_str_appendf(&sRes,"%02d", ++ (daysAfterJan01(&x)-daysAfterMonday(&x)+7)/7); + break; + } + case 'Y': { diff --git a/sqlite3/locking_mode.patch b/sqlite3/locking_mode.patch index 27042b7..ebae0eb 100644 --- a/sqlite3/locking_mode.patch +++ b/sqlite3/locking_mode.patch @@ -1,7 +1,7 @@ # Use exclusive locking mode for WAL databases with v1 VFSes. --- sqlite3.c.orig +++ sqlite3.c -@@ -63210,7 +63210,9 @@ +@@ -64209,7 +64209,9 @@ SQLITE_PRIVATE int sqlite3PagerWalSupported(Pager *pPager){ const sqlite3_io_methods *pMethods = pPager->fd->pMethods; if( pPager->noLock ) return 0; diff --git a/sqlite3/vfs_find.patch b/sqlite3/vfs_find.patch index 8a2d680..8435763 100644 --- a/sqlite3/vfs_find.patch +++ b/sqlite3/vfs_find.patch @@ -1,7 +1,7 @@ # Wrap sqlite3_vfs_find. --- sqlite3.c.orig +++ sqlite3.c -@@ -25394,7 +25394,7 @@ +@@ -26089,7 +26089,7 @@ ** Locate a VFS by name. If no name is given, simply return the ** first VFS on the list. */ diff --git a/tests/time_test.go b/tests/time_test.go index 11963cf..38a439e 100644 --- a/tests/time_test.go +++ b/tests/time_test.go @@ -221,28 +221,6 @@ func TestDB_timeCollation(t *testing.T) { func TestDB_isoWeek(t *testing.T) { t.Parallel() - tests := []time.Time{ - time.Date(1977, 1, 1, 0, 0, 0, 0, time.UTC), - time.Date(1977, 1, 2, 0, 0, 0, 0, time.UTC), - time.Date(1977, 12, 31, 0, 0, 0, 0, time.UTC), - time.Date(1978, 1, 1, 0, 0, 0, 0, time.UTC), - time.Date(1978, 1, 2, 0, 0, 0, 0, time.UTC), - time.Date(1978, 12, 31, 0, 0, 0, 0, time.UTC), - time.Date(1979, 1, 1, 0, 0, 0, 0, time.UTC), - time.Date(1979, 1, 2, 0, 0, 0, 0, time.UTC), - time.Date(1979, 12, 31, 0, 0, 0, 0, time.UTC), - time.Date(1980, 1, 1, 0, 0, 0, 0, time.UTC), - time.Date(1980, 12, 28, 0, 0, 0, 0, time.UTC), - time.Date(1980, 12, 29, 0, 0, 0, 0, time.UTC), - time.Date(1980, 12, 30, 0, 0, 0, 0, time.UTC), - time.Date(1980, 12, 31, 0, 0, 0, 0, time.UTC), - time.Date(1981, 1, 1, 0, 0, 0, 0, time.UTC), - time.Date(1981, 12, 31, 0, 0, 0, 0, time.UTC), - time.Date(1982, 1, 1, 0, 0, 0, 0, time.UTC), - time.Date(1982, 1, 2, 0, 0, 0, 0, time.UTC), - time.Date(1982, 1, 3, 0, 0, 0, 0, time.UTC), - } - db, err := sqlite3.Open(":memory:") if err != nil { t.Fatal(err) @@ -255,7 +233,9 @@ func TestDB_isoWeek(t *testing.T) { } defer stmt.Close() - for _, tm := range tests { + tend := time.Date(2500, 1, 1, 0, 0, 0, 0, time.UTC) + tstart := time.Date(1500, 1, 1, 12, 0, 0, 0, time.UTC) + for tm := tstart; tm.Before(tend); tm = tm.AddDate(0, 0, 1) { stmt.BindTime(1, tm, sqlite3.TimeFormatDefault) if stmt.Step() { y, w := tm.ISOWeek()