]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
tighter coding of the date and time functions. Better comments. A bug fix. (CVS...
authordrh <drh@noemail.net>
Sun, 10 Aug 2003 01:50:54 +0000 (01:50 +0000)
committerdrh <drh@noemail.net>
Sun, 10 Aug 2003 01:50:54 +0000 (01:50 +0000)
FossilOrigin-Name: 94243edac14b90ef898093b85e1959c20fa23ae9

manifest
manifest.uuid
src/func.c

index 2ed24abefa90ea402503f0952caf999f477dd942..1137fa12c3237e8b36cfd99f80462de2c59bc9c0 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sexperimental\sdate\sand\stime\sfunctions\sbased\son\sjulian\sday\snumber.\s(CVS\s1069)
-D 2003-08-09T21:32:28
+C tighter\scoding\sof\sthe\sdate\sand\stime\sfunctions.\s\sBetter\scomments.\s\sA\sbug\sfix.\s(CVS\s1070)
+D 2003-08-10T01:50:55
 F Makefile.in 9ad23ed4ca97f9670c4496432e3fbd4b3760ebde
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -29,7 +29,7 @@ F src/copy.c 9e47975ea96751c658bcf1a0c4f0bb7c6ee61e73
 F src/delete.c 0f81e6799c089487615d38e042a2de4d2d6192bc
 F src/encode.c 25ea901a9cefb3d93774afa4a06b57cb58acf544
 F src/expr.c 03c321ac66c1e998c2e0faf22184b5a808b559ca
-F src/func.c 67b66803d8a8b33dfea64ef54835d8b1d43c9f20
+F src/func.c 2b196fdca328838c0c02f290ec833d05d63d7a32
 F src/hash.c 058f077c1f36f266581aa16f907a3903abf64aa3
 F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
 F src/insert.c dc200ae04a36bd36e575272a069e20c528b7fbdf
@@ -168,7 +168,7 @@ F www/speed.tcl 2f6b1155b99d39adb185f900456d1d592c4832b3
 F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
 F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
-P 086aa1c9922b7bf399b3ee8b73ba7353d126b119
-R b633d80bd522667187e3193065550fbf
+P a6197e2075fdf9db862484255ac16b2855bbef0a
+R 2c17b8788ba63ebf744e79cd8d1dc806
 U drh
-Z 4776791846cfff06b30527d77321657f
+Z 001852bd03c4d150dde8de11d7257985
index eaf7f93b2fb30c4eb4cfa67f9ad194d387695c51..bf0489fb58c609625695913c333ff49c1104c29a 100644 (file)
@@ -1 +1 @@
-a6197e2075fdf9db862484255ac16b2855bbef0a
\ No newline at end of file
+94243edac14b90ef898093b85e1959c20fa23ae9
\ No newline at end of file
index 10f0e089051cd5fe38b8825feee5c5728341afea..1eb24436dcdb52c61b1e9df6c693a1c2d08a411e 100644 (file)
@@ -16,7 +16,7 @@
 ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
 ** All other code has file scope.
 **
-** $Id: func.c,v 1.27 2003/08/09 21:32:28 drh Exp $
+** $Id: func.c,v 1.28 2003/08/10 01:50:55 drh Exp $
 */
 #include <ctype.h>
 #include <math.h>
@@ -503,14 +503,16 @@ static void minMaxFinalize(sqlite_func *context){
 **
 ** SQLite processes all times and dates as Julian Day numbers.  The
 ** dates and times are stored as the number of days since noon
-** in Greenwich on January 01, 4713 B.C.  (a.k.a -4713-01-01 12:00:00)
+** in Greenwich on November 24, 4714 B.C. according to the Gregorian
+** calendar system.
+**
 ** This implement requires years to be expressed as a 4-digit number
 ** which means that only dates between 0000-01-01 and 9999-12-31 can
 ** be represented, even though julian day numbers allow a much wider
 ** range of dates.
 **
 ** The Gregorian calendar system is used for all dates and times,
-** even those that predate the Gregorian calendar.  Historians often
+** even those that predate the Gregorian calendar.  Historians usually
 ** use the Julian calendar for dates prior to 1582-10-15 and for some
 ** dates afterwards, depending on locale.  Beware of this difference.
 **
@@ -540,7 +542,7 @@ static int getDigits(const char *zDate, int N){
 }
 
 /*
-** Parse dates of the form HH:MM:SS or HH:MM.  Store the
+** Parse times of the form HH:MM:SS or HH:MM.  Store the
 ** result (in days) in *prJD.
 **
 ** Return 1 if there is a parsing error and 0 on success.
@@ -645,160 +647,152 @@ static int parseDateOrTime(const char *zDate, double *prJD){
 }
 
 /*
-** Break up a julian day number into year, month, day, and seconds.
+** A structure for holding date and time.
+*/
+typedef struct DateTime DateTime;
+struct DateTime {
+  double rJD;    /* The julian day number */
+  int Y, M, D;   /* Year, month, and day */
+  int h, m, s;   /* Hour minute and second */
+};
+
+/*
+** Break up a julian day number into year, month, day, hour, minute, second.
 ** This function assume the Gregorian calendar - even for dates prior
 ** to the invention of the Gregorian calendar in 1582.
 **
 ** See Meeus page 63.
+**
+** If mode==1 only the year, month, and day are computed.  If mode==2
+** then only the hour, minute, and second are computed.  If mode==3 then
+** everything is computed.  If mode==0, this routine is a no-op.
+*/
+static void decomposeDate(DateTime *p, int mode){
+  int Z;
+  Z = p->rJD + 0.5;
+  if( mode & 1 ){
+    int A, B, C, D, E, X1;
+    A = (Z - 1867216.25)/36524.25;
+    A = Z + 1 + A - (A/4);
+    B = A + 1524;
+    C = (B - 122.1)/365.25;
+    D = 365.25*C;
+    E = (B-D)/30.6001;
+    X1 = 30.6001*E;
+    p->D = B - D - X1;
+    p->M = E<14 ? E-1 : E-13;
+    p->Y = p->M>2 ? C - 4716 : C - 4715;
+  }
+  if( mode & 2 ){
+    p->s = (p->rJD + 0.5 - Z)*86400.0;
+    p->h = p->s/3600;
+    p->s -= p->h*3600;
+    p->m = p->s/60;
+    p->s -= p->m*60;
+  }
+}
+
+/*
+** Check to see that all arguments are valid date strings.  If any 
+** argument is not a valid date string, return 0.  If all arguments
+** are valid, return 1 and write into *p->rJD the sum of the julian day
+** numbers for all date strings.
+**
+** A "valid" date string is one that is accepted by parseDateOrTime().
+**
+** The mode argument is passed through to decomposeDate() in order to
+** fill in the year, month, day, hour, minute, and second of the *p
+** structure, if desired.
 */
-static void decomposeDate(double JD, int *pY, int *pM, int *pD, int *pS){
-  int Z, A, B, C, D, E, X1;
-  Z = JD + 0.5;
-  A = (Z - 1867216.25)/36524.25;
-  A = Z + 1 + A - (A/4);
-  B = A + 1524;
-  C = (B - 122.1)/365.25;
-  D = 365.25*C;
-  E = (B-D)/30.6001;
-  X1 = 30.6001*E;
-  *pD = B - D - X1;
-  *pM = E<14 ? E-1 : E-13;
-  *pY = *pD>2 ? C - 4716 : C - 4715;
-  *pS = (JD + 0.5 - Z)*86400.0;
-}
-
-/*
-** Check to see that all arguments are valid date strings.  If any is
-** not a valid date string, return 0.  If all are valid, return 1.
-** Write into *prJD the sum of the julian day numbers for all date
-** strings.
-*/
-static int isDate(
-  sqlite_func *context,
-  int argc,
-  const char **argv,
-  double *prJD
-){
+static int isDate(int argc, const char **argv, DateTime *p, int mode){
   double r;
   int i;
-  *prJD = 0.0;
+  p->rJD = 0.0;
   for(i=0; i<argc; i++){
     if( argv[i]==0 ) return 0;
     if( parseDateOrTime(argv[i], &r) ) return 0;
-    *prJD += r;
+    p->rJD += r;
   }
+  decomposeDate(p, mode);
   return 1;
 }
 
+
 /*
 ** The following routines implement the various date and time functions
 ** of SQLite.
 */
 static void juliandayFunc(sqlite_func *context, int argc, const char **argv){
-  double JD;
-  if( isDate(context, argc, argv, &JD) ){
-    sqlite_set_result_double(context, JD);
+  DateTime x;
+  if( isDate(argc, argv, &x, 0) ){
+    sqlite_set_result_double(context, x.rJD);
   }
 }
 static void timestampFunc(sqlite_func *context, int argc, const char **argv){
-  double JD;
-  if( isDate(context, argc, argv, &JD) ){
-    int Y, M, D, h, m, s;
+  DateTime x;
+  if( isDate(argc, argv, &x, 3) ){
     char zBuf[100];
-    decomposeDate(JD, &Y, &M, &D, &s);
-    h = s/3600;
-    s -= h*3600;
-    m = s/60;
-    s -= m*60;
-    sprintf(zBuf, "%04d-%02d-%02d %02d:%02d:%02d", Y, M, D, h, m, s);
+    sprintf(zBuf, "%04d-%02d-%02d %02d:%02d:%02d",x.Y, x.M, x.D, x.h, x.m, x.s);
     sqlite_set_result_string(context, zBuf, -1);
   }
 }
 static void timeFunc(sqlite_func *context, int argc, const char **argv){
-  double JD;
-  if( isDate(context, argc, argv, &JD) ){
-    int Y, M, D, h, m, s;
+  DateTime x;
+  if( isDate(argc, argv, &x, 2) ){
     char zBuf[100];
-    decomposeDate(JD, &Y, &M, &D, &s);
-    h = s/3600;
-    s -= h*3600;
-    m = s/60;
-    s -= m*60;
-    sprintf(zBuf, "%02d:%02d:%02d", h, m, s);
+    sprintf(zBuf, "%02d:%02d:%02d", x.h, x.m, x.s);
     sqlite_set_result_string(context, zBuf, -1);
   }
 }
 static void dateFunc(sqlite_func *context, int argc, const char **argv){
-  double JD;
-  if( isDate(context, argc, argv, &JD) ){
-    int Y, M, D, s;
+  DateTime x;
+  if( isDate(argc, argv, &x, 1) ){
     char zBuf[100];
-    decomposeDate(JD, &Y, &M, &D, &s);
-    sprintf(zBuf, "%04d-%02d-%02d", Y, M, D);
+    sprintf(zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
     sqlite_set_result_string(context, zBuf, -1);
   }
 }
 static void yearFunc(sqlite_func *context, int argc, const char **argv){
-  double JD;
-  if( isDate(context, argc, argv, &JD) ){
-    int Y, M, D, s;
-    decomposeDate(JD, &Y, &M, &D, &s);
-    sqlite_set_result_int(context, Y);
+  DateTime x;
+  if( isDate(argc, argv, &x, 1) ){
+    sqlite_set_result_int(context, x.Y);
   }
 }
 static void monthFunc(sqlite_func *context, int argc, const char **argv){
-  double JD;
-  if( isDate(context, argc, argv, &JD) ){
-    int Y, M, D, s;
-    decomposeDate(JD, &Y, &M, &D, &s);
-    sqlite_set_result_int(context, M);
+  DateTime x;
+  if( isDate(argc, argv, &x, 1) ){
+    sqlite_set_result_int(context, x.M);
   }
 }
 static void dayofweekFunc(sqlite_func *context, int argc, const char **argv){
-  double JD;
-  if( isDate(context, argc, argv, &JD) ){
-    int Z = JD + 1.5;
+  DateTime x;
+  if( isDate(argc, argv, &x, 0) ){
+    int Z = x.rJD + 1.5;
     sqlite_set_result_int(context, Z % 7);
   }
 }
 static void dayofmonthFunc(sqlite_func *context, int argc, const char **argv){
-  double JD;
-  if( isDate(context, argc, argv, &JD) ){
-    int Y, M, D, s;
-    decomposeDate(JD, &Y, &M, &D, &s);
-    sqlite_set_result_int(context, D);
+  DateTime x;
+  if( isDate(argc, argv, &x, 1) ){
+    sqlite_set_result_int(context, x.D);
   }
 }
 static void secondFunc(sqlite_func *context, int argc, const char **argv){
-  double JD;
-  if( isDate(context, argc, argv, &JD) ){
-    int Y, M, D, h, m, s;
-    decomposeDate(JD, &Y, &M, &D, &s);
-    h = s/3600;
-    s -= h*3600;
-    m = s/60;
-    s -= m*60;
-    sqlite_set_result_int(context, s);
+  DateTime x;
+  if( isDate(argc, argv, &x, 2) ){
+    sqlite_set_result_int(context, x.s);
   }
 }
 static void minuteFunc(sqlite_func *context, int argc, const char **argv){
-  double JD;
-  if( isDate(context, argc, argv, &JD) ){
-    int Y, M, D, h, m, s;
-    decomposeDate(JD, &Y, &M, &D, &s);
-    h = s/3600;
-    s -= h*3600;
-    m = s/60;
-    sqlite_set_result_int(context, m);
+  DateTime x;
+  if( isDate(argc, argv, &x, 2) ){
+    sqlite_set_result_int(context, x.m);
   }
 }
 static void hourFunc(sqlite_func *context, int argc, const char **argv){
-  double JD;
-  if( isDate(context, argc, argv, &JD) ){
-    int Y, M, D, h, s;
-    decomposeDate(JD, &Y, &M, &D, &s);
-    h = s/3600;
-    sqlite_set_result_int(context, h);
+  DateTime x;
+  if( isDate(argc, argv, &x, 2) ){
+    sqlite_set_result_int(context, x.h);
   }
 }
 #endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */