/ Check-in [70df32b7]
Login
Overview
Comment:Preserve the HH:MM:SS for most date/time modifiers. Ticket #551. (CVS 1163)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:70df32b716b0d6a4f72bb3ae6496431e53733b6a
User & Date: drh 2004-01-07 03:29:16
Context
2004-01-07
03:41
Make it safe to call sqliteMalloc() with a request for 0 bytes. Ticket #534. (CVS 1164) check-in: 6c858db2 user: drh tags: trunk
03:29
Preserve the HH:MM:SS for most date/time modifiers. Ticket #551. (CVS 1163) check-in: 70df32b7 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: 8371f662 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/date.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
...
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
...
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
** 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.
................................................................................
      }
      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;
................................................................................
        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;
................................................................................
          }
          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;







|







 







|

|
<





|







 







>












>







 







|



|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
490
491
492
493
494
495
496
497
498
499

500
501
502
503
504
505
506
507
508
509
510
511
512
...
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
...
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
** 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.
................................................................................
      }
      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;
................................................................................
        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;
................................................................................
          }
          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.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
...
146
147
148
149
150
151
152




153
154
155
156
157
158
159
...
167
168
169
170
171
172
173
174


























175
#    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')"
................................................................................
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
................................................................................
      {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
................................................................................
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







|







 







|







 







>
>
>
>







 








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

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
...
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
...
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
#    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')"
................................................................................
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
................................................................................
      {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
................................................................................
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