/ Check-in [94243eda]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:tighter coding of the date and time functions. Better comments. A bug fix. (CVS 1070)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 94243edac14b90ef898093b85e1959c20fa23ae9
User & Date: drh 2003-08-10 01:50:55
Context
2003-08-10
16:16
Make the sqliteOsCurrentTime() function work for Windows. Code contributed by "e4liberty" on the mailing list. (CVS 1071) check-in: 02fac304 user: drh tags: trunk
01:50
tighter coding of the date and time functions. Better comments. A bug fix. (CVS 1070) check-in: 94243eda user: drh tags: trunk
2003-08-09
21:32
Add experimental date and time functions based on julian day number. (CVS 1069) check-in: a6197e20 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/func.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
499
500
501
502
503
504
505
506


507
508
509
510
511
512
513
514
515
516
517
518
519
520
...
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
...
641
642
643
644
645
646
647










648
649
650
651
652




653
654



655
656
657
658
659
660
661
662
663
664
665
666


667




668
669

670
671
672

673
674






675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

690
691

692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** 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 $
*/
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "sqliteInt.h"
#include "os.h"
................................................................................
}

/****************************************************************************
** Time and date functions.
**
** 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)


** 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
** use the Julian calendar for dates prior to 1582-10-15 and for some
** dates afterwards, depending on locale.  Beware of this difference.
**
** The conversion algorithms are implemented based on descriptions
** in the following text:
**
**      Jean Meeus
................................................................................
    val = val*10 + *zDate - '0';
    zDate++;
  }
  return val;
}

/*
** Parse dates 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.
*/
static int parseHhMmSs(const char *zDate, double *prJD){
  int h, m, s;
  h = getDigits(zDate, 2);
................................................................................
    *prJD = atof(zDate);
    return 0;
  }
  return 1;
}

/*










** Break up a julian day number into year, month, day, and seconds.
** This function assume the Gregorian calendar - even for dates prior
** to the invention of the Gregorian calendar in 1582.
**
** See Meeus page 63.




*/
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
){
  double r;
  int i;
  *prJD = 0.0;
  for(i=0; i<argc; i++){
    if( argv[i]==0 ) return 0;
    if( parseDateOrTime(argv[i], &r) ) return 0;
    *prJD += r;
  }

  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);
  }
}
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;
    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);
    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;
    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);
    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;
    char zBuf[100];
    decomposeDate(JD, &Y, &M, &D, &s);
    sprintf(zBuf, "%04d-%02d-%02d", Y, M, 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);
  }
}
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);
  }
}
static void dayofweekFunc(sqlite_func *context, int argc, const char **argv){
  double JD;
  if( isDate(context, argc, argv, &JD) ){
    int Z = JD + 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);
  }
}
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);
  }
}
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);
  }
}
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);
  }
}
#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
/***************************************************************************/

/*
** This function registered all of the above C functions as SQL







|







 







|
>
>






|







 







|







 







>
>
>
>
>
>
>
>
>
>
|




>
>
>
>

|
>
>
>
|
<
|
|
|
|
|
|
|
|
|
|
>
>
|
>
>
>
>
|
|
>

|
|
>
|
<
>
>
>
>
>
>

|
<
<
<
<
<


|



|

>


>






|
|
|



|
|
<

<
<
<
<
<
|




|
|
<

<
<
<
<
<
|




|
|
<

<
|




|
|
<
<
|



|
|
<
<
|



|
|
|




|
|
<
<
|



|
|
<
<
<
<
<
<
|



|
|
<
<
<
<
<
|



|
|
<
<
<
|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
...
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
...
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674

675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699

700
701
702
703
704
705
706
707





708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733

734





735
736
737
738
739
740
741

742





743
744
745
746
747
748
749

750

751
752
753
754
755
756
757


758
759
760
761
762
763


764
765
766
767
768
769
770
771
772
773
774
775
776


777
778
779
780
781
782






783
784
785
786
787
788





789
790
791
792
793
794



795
796
797
798
799
800
801
802
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.28 2003/08/10 01:50:55 drh Exp $
*/
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "sqliteInt.h"
#include "os.h"
................................................................................
}

/****************************************************************************
** Time and date functions.
**
** 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 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 usually
** use the Julian calendar for dates prior to 1582-10-15 and for some
** dates afterwards, depending on locale.  Beware of this difference.
**
** The conversion algorithms are implemented based on descriptions
** in the following text:
**
**      Jean Meeus
................................................................................
    val = val*10 + *zDate - '0';
    zDate++;
  }
  return val;
}

/*
** 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.
*/
static int parseHhMmSs(const char *zDate, double *prJD){
  int h, m, s;
  h = getDigits(zDate, 2);
................................................................................
    *prJD = atof(zDate);
    return 0;
  }
  return 1;
}

/*
** 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 int isDate(int argc, const char **argv, DateTime *p, int mode){





  double r;
  int i;
  p->rJD = 0.0;
  for(i=0; i<argc; i++){
    if( argv[i]==0 ) return 0;
    if( parseDateOrTime(argv[i], &r) ) return 0;
    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){
  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){
  DateTime x;
  if( isDate(argc, argv, &x, 3) ){

    char zBuf[100];





    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){
  DateTime x;
  if( isDate(argc, argv, &x, 2) ){

    char zBuf[100];





    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){
  DateTime x;
  if( isDate(argc, argv, &x, 1) ){

    char zBuf[100];

    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){
  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){
  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){
  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){
  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){
  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){
  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){
  DateTime x;
  if( isDate(argc, argv, &x, 2) ){



    sqlite_set_result_int(context, x.h);
  }
}
#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
/***************************************************************************/

/*
** This function registered all of the above C functions as SQL