SQLite

Check-in [70df32b716]
Login

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

Overview
Comment:Preserve the HH:MM:SS for most date/time modifiers. Ticket #551. (CVS 1163)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 70df32b716b0d6a4f72bb3ae6496431e53733b6a
User & Date: drh 2004-01-07 03:29:16.000
Context
2004-01-07
03:41
Make it safe to call sqliteMalloc() with a request for 0 bytes. Ticket #534. (CVS 1164) (check-in: 6c858db2c0 user: drh tags: trunk)
03:29
Preserve the HH:MM:SS for most date/time modifiers. Ticket #551. (CVS 1163) (check-in: 70df32b716 user: drh tags: trunk)
03:04
Use "long double" to hold intermediate values when doing ascii to binary and binary to ascii conversions of floating point numbers. (CVS 1162) (check-in: 8371f662d2 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/date.c.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** This file contains the C functions that implement date and time
** functions for SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: date.c,v 1.6 2003/12/31 17:25:48 drh Exp $
**
** NOTES:
**
** 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.







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** This file contains the C functions that implement date and time
** functions for SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterDateTimeFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: date.c,v 1.7 2004/01/07 03:29:16 drh Exp $
**
** NOTES:
**
** 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.
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
      }
      break;
    }
    case 'w': {
      /*
      **    weekday N
      **
      ** Move the date to the beginning of the next occurrance of
      ** weekday N where 0==Sunday, 1==Monday, and so forth.  If the
      ** date is already on the appropriate weekday, this is equivalent
      ** to "start of day".
      */
      if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0
                 && (n=r)==r && n>=0 && r<7 ){
        int Z;
        computeYMD(p);
        p->validHMS = 0;
        p->validTZ = 0;
        p->validJD = 0;
        computeJD(p);
        Z = p->rJD + 1.5;
        Z %= 7;
        if( Z>n ) Z -= 7;
        p->rJD += n - Z;







|

|
<





|







490
491
492
493
494
495
496
497
498
499

500
501
502
503
504
505
506
507
508
509
510
511
512
      }
      break;
    }
    case 'w': {
      /*
      **    weekday N
      **
      ** Move the date to the same time on the next occurrance 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.

      */
      if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0
                 && (n=r)==r && n>=0 && r<7 ){
        int Z;
        computeYMD(p);
        computeHMS(p);
        p->validTZ = 0;
        p->validJD = 0;
        computeJD(p);
        Z = p->rJD + 1.5;
        Z %= 7;
        if( Z>n ) Z -= 7;
        p->rJD += n - Z;
577
578
579
580
581
582
583

584
585
586
587
588
589
590
591
592
593
594
595

596
597
598
599
600
601
602
        p->rJD += r/(24.0*60.0);
      }else if( n==6 && strcmp(z,"second")==0 ){
        computeJD(p);
        p->rJD += r/(24.0*60.0*60.0);
      }else if( n==5 && strcmp(z,"month")==0 ){
        int x, y;
        computeYMD(p);

        p->M += r;
        x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
        p->Y += x;
        p->M -= x*12;
        p->validJD = 0;
        computeJD(p);
        y = r;
        if( y!=r ){
          p->rJD += (r - y)*30.0;
        }
      }else if( n==4 && strcmp(z,"year")==0 ){
        computeYMD(p);

        p->Y += r;
        p->validJD = 0;
        computeJD(p);
      }else{
        rc = 1;
      }
      p->validYMD = 0;







>












>







576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
        p->rJD += r/(24.0*60.0);
      }else if( n==6 && strcmp(z,"second")==0 ){
        computeJD(p);
        p->rJD += r/(24.0*60.0*60.0);
      }else if( n==5 && strcmp(z,"month")==0 ){
        int x, y;
        computeYMD(p);
        computeHMS(p);
        p->M += r;
        x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
        p->Y += x;
        p->M -= x*12;
        p->validJD = 0;
        computeJD(p);
        y = r;
        if( y!=r ){
          p->rJD += (r - y)*30.0;
        }
      }else if( n==4 && strcmp(z,"year")==0 ){
        computeYMD(p);
        computeHMS(p);
        p->Y += r;
        p->validJD = 0;
        computeJD(p);
      }else{
        rc = 1;
      }
      p->validYMD = 0;
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
          }
          break;
        }
        case 'J':  sprintf(&z[j],"%.16g",x.rJD); j+=strlen(&z[j]); break;
        case 'm':  sprintf(&z[j],"%02d",x.M); j+=2; break;
        case 'M':  sprintf(&z[j],"%02d",x.m); j+=2; break;
        case 's': {
          sprintf(&z[j],"%d",(int)((x.rJD-2440587.5)*86400.0));
          j += strlen(&z[j]);
          break;
        }
        case 'S':  sprintf(&z[j],"%02d",(int)x.s); j+=2; break;
        case 'w':  z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break;
        case 'Y':  sprintf(&z[j],"%04d",x.Y); j+=strlen(&z[j]); break;
        case '%':  z[j++] = '%'; break;
      }
    }
  }
  z[j] = 0;







|



|







795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
          }
          break;
        }
        case 'J':  sprintf(&z[j],"%.16g",x.rJD); j+=strlen(&z[j]); break;
        case 'm':  sprintf(&z[j],"%02d",x.M); j+=2; break;
        case 'M':  sprintf(&z[j],"%02d",x.m); j+=2; break;
        case 's': {
          sprintf(&z[j],"%d",(int)((x.rJD-2440587.5)*86400.0 + 0.5));
          j += strlen(&z[j]);
          break;
        }
        case 'S':  sprintf(&z[j],"%02d",(int)(x.s+0.5)); j+=2; break;
        case 'w':  z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break;
        case 'Y':  sprintf(&z[j],"%04d",x.Y); j+=strlen(&z[j]); break;
        case '%':  z[j++] = '%'; break;
      }
    }
  }
  z[j] = 0;
Changes to test/date.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2003 October 31
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing date and time functions.
#
# $Id: date.test,v 1.4 2004/01/02 15:08:43 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

proc datetest {tnum expr result} {
  do_test date-$tnum [subst {
    execsql "SELECT coalesce($expr,'NULL')"













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2003 October 31
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing date and time functions.
#
# $Id: date.test,v 1.5 2004/01/07 03:29:16 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

proc datetest {tnum expr result} {
  do_test date-$tnum [subst {
    execsql "SELECT coalesce($expr,'NULL')"
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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.12 {datetime('2003-10-22 12:34','weekday 0')} {2003-10-26 00:00:00}
datetest 2.13 {datetime('2003-10-22 12:34','start of month')} \
   {2003-10-01 00:00:00}
datetest 2.14 {datetime('2003-10-22 12:34','start of year')} \
   {2003-01-01 00:00:00}
datetest 2.15 {datetime('2003-10-22 12:34','start of day')} \
   {2003-10-22 00:00:00}
datetest 2.16 time('12:34:56.43') 12:34:56







|







55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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.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.14 {datetime('2003-10-22 12:34','start of year')} \
   {2003-01-01 00:00:00}
datetest 2.15 {datetime('2003-10-22 12:34','start of day')} \
   {2003-10-22 00:00:00}
datetest 2.16 time('12:34:56.43') 12:34:56
146
147
148
149
150
151
152




153
154
155
156
157
158
159
      {2039-01-01 07:00:00}
  datetest 6.13 {datetime('2000-07-01 12:00:00','localtime')} \
      {2000-07-01 08:00:00}
  datetest 6.14 {datetime('1969-07-01 12:00:00','localtime')} \
      {1969-07-01 07:00:00}
  datetest 6.15 {datetime('2039-07-01 12:00:00','localtime')} \
      {2039-07-01 07:00:00}




}

# Date-time functions that contain NULL arguments return a NULL
# result.
#
datetest 7.1 {datetime(null)} NULL
datetest 7.2 {datetime('now',null)} NULL







>
>
>
>







146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
      {2039-01-01 07:00:00}
  datetest 6.13 {datetime('2000-07-01 12:00:00','localtime')} \
      {2000-07-01 08:00:00}
  datetest 6.14 {datetime('1969-07-01 12:00:00','localtime')} \
      {1969-07-01 07:00:00}
  datetest 6.15 {datetime('2039-07-01 12:00:00','localtime')} \
      {2039-07-01 07:00:00}
  set sqlite_current_time \
     [db eval {SELECT strftime('%s','2000-07-01 12:34:56')}]
  datetest 6.16 {datetime('now','localtime')} {2000-07-01 08:34:56}
  set sqlite_current_time 0
}

# Date-time functions that contain NULL arguments return a NULL
# result.
#
datetest 7.1 {datetime(null)} NULL
datetest 7.2 {datetime('now',null)} NULL
167
168
169
170
171
172
173
174


























175
datetest 7.10 {julianday(null)} NULL
datetest 7.11 {julianday('now',null)} NULL
datetest 7.12 {julianday('now','localtime',null)} NULL
datetest 7.13 {strftime(null,'now')} NULL
datetest 7.14 {strftime('%s',null)} NULL
datetest 7.15 {strftime('%s','now',null)} NULL
datetest 7.16 {strftime('%s','now','localtime',null)} NULL



























finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
datetest 7.10 {julianday(null)} NULL
datetest 7.11 {julianday('now',null)} NULL
datetest 7.12 {julianday('now','localtime',null)} NULL
datetest 7.13 {strftime(null,'now')} NULL
datetest 7.14 {strftime('%s',null)} NULL
datetest 7.15 {strftime('%s','now',null)} NULL
datetest 7.16 {strftime('%s','now','localtime',null)} NULL

# Test modifiers when the date begins as a julian day number - to
# make sure the HH:MM:SS is preserved.  Ticket #551.
#
set sqlite_current_time [db eval {SELECT strftime('%s','2003-10-22 12:34:00')}]
datetest 8.1 {datetime('now','weekday 0')} {2003-10-26 12:34:00}
datetest 8.2 {datetime('now','weekday 1')} {2003-10-27 12:34:00}
datetest 8.3 {datetime('now','weekday 2')} {2003-10-28 12:34:00}
datetest 8.4 {datetime('now','weekday 3')} {2003-10-22 12:34:00}
datetest 8.5 {datetime('now','start of month')} {2003-10-01 00:00:00}
datetest 8.6 {datetime('now','start of year')} {2003-01-01 00:00:00}
datetest 8.7 {datetime('now','start of day')} {2003-10-22 00:00:00}
datetest 8.8 {datetime('now','1 day')} {2003-10-23 12:34:00}
datetest 8.9 {datetime('now','+1 day')} {2003-10-23 12:34:00}
datetest 8.10 {datetime('now','+1.25 day')} {2003-10-23 18:34:00}
datetest 8.11 {datetime('now','-1.0 day')} {2003-10-21 12:34:00}
datetest 8.12 {datetime('now','1 month')} {2003-11-22 12:34:00}
datetest 8.13 {datetime('now','11 month')} {2004-09-22 12:34:00}
datetest 8.14 {datetime('now','-13 month')} {2002-09-22 12:34:00}
datetest 8.15 {datetime('now','1.5 months')} {2003-12-07 12:34:00}
datetest 8.16 {datetime('now','-5 years')} {1998-10-22 12:34:00}
datetest 8.17 {datetime('now','+10.5 minutes')} {2003-10-22 12:44:30}
datetest 8.18 {datetime('now','-1.25 hours')} {2003-10-22 11:19:00}
datetest 8.19 {datetime('now','11.25 seconds')} {2003-10-22 12:34:11}
set sqlite_current_time 0


finish_test