extensions/sqlite/sqlite-source/date.c
author David Anderson <dvander@alliedmods.net>
Sun Oct 28 05:48:06 2007 +0000 (2007-10-28)
changeset 1645 27307df4d711
parent 1203 633c25ce6405
permissions -rw-r--r--
updated to sqlite-3.5.1 now that it's stable
used new shared cache functionality (yay)
dvander@1203
     1
/*
dvander@1203
     2
** 2003 October 31
dvander@1203
     3
**
dvander@1203
     4
** The author disclaims copyright to this source code.  In place of
dvander@1203
     5
** a legal notice, here is a blessing:
dvander@1203
     6
**
dvander@1203
     7
**    May you do good and not evil.
dvander@1203
     8
**    May you find forgiveness for yourself and forgive others.
dvander@1203
     9
**    May you share freely, never taking more than you give.
dvander@1203
    10
**
dvander@1203
    11
*************************************************************************
dvander@1203
    12
** This file contains the C functions that implement date and time
dvander@1203
    13
** functions for SQLite.  
dvander@1203
    14
**
dvander@1203
    15
** There is only one exported symbol in this file - the function
dvander@1203
    16
** sqlite3RegisterDateTimeFunctions() found at the bottom of the file.
dvander@1203
    17
** All other code has file scope.
dvander@1203
    18
**
dvander@1203
    19
** $Id$
dvander@1203
    20
**
dvander@1203
    21
** SQLite processes all times and dates as Julian Day numbers.  The
dvander@1203
    22
** dates and times are stored as the number of days since noon
dvander@1203
    23
** in Greenwich on November 24, 4714 B.C. according to the Gregorian
dvander@1203
    24
** calendar system. 
dvander@1203
    25
**
dvander@1203
    26
** 1970-01-01 00:00:00 is JD 2440587.5
dvander@1203
    27
** 2000-01-01 00:00:00 is JD 2451544.5
dvander@1203
    28
**
dvander@1203
    29
** This implemention requires years to be expressed as a 4-digit number
dvander@1203
    30
** which means that only dates between 0000-01-01 and 9999-12-31 can
dvander@1203
    31
** be represented, even though julian day numbers allow a much wider
dvander@1203
    32
** range of dates.
dvander@1203
    33
**
dvander@1203
    34
** The Gregorian calendar system is used for all dates and times,
dvander@1203
    35
** even those that predate the Gregorian calendar.  Historians usually
dvander@1203
    36
** use the Julian calendar for dates prior to 1582-10-15 and for some
dvander@1203
    37
** dates afterwards, depending on locale.  Beware of this difference.
dvander@1203
    38
**
dvander@1203
    39
** The conversion algorithms are implemented based on descriptions
dvander@1203
    40
** in the following text:
dvander@1203
    41
**
dvander@1203
    42
**      Jean Meeus
dvander@1203
    43
**      Astronomical Algorithms, 2nd Edition, 1998
dvander@1203
    44
**      ISBM 0-943396-61-1
dvander@1203
    45
**      Willmann-Bell, Inc
dvander@1203
    46
**      Richmond, Virginia (USA)
dvander@1203
    47
*/
dvander@1203
    48
#include "sqliteInt.h"
dvander@1203
    49
#include <ctype.h>
dvander@1203
    50
#include <stdlib.h>
dvander@1203
    51
#include <assert.h>
dvander@1203
    52
#include <time.h>
dvander@1203
    53
dvander@1203
    54
#ifndef SQLITE_OMIT_DATETIME_FUNCS
dvander@1203
    55
dvander@1203
    56
/*
dvander@1203
    57
** A structure for holding a single date and time.
dvander@1203
    58
*/
dvander@1203
    59
typedef struct DateTime DateTime;
dvander@1203
    60
struct DateTime {
dvander@1203
    61
  double rJD;      /* The julian day number */
dvander@1203
    62
  int Y, M, D;     /* Year, month, and day */
dvander@1203
    63
  int h, m;        /* Hour and minutes */
dvander@1203
    64
  int tz;          /* Timezone offset in minutes */
dvander@1203
    65
  double s;        /* Seconds */
dvander@1203
    66
  char validYMD;   /* True if Y,M,D are valid */
dvander@1203
    67
  char validHMS;   /* True if h,m,s are valid */
dvander@1203
    68
  char validJD;    /* True if rJD is valid */
dvander@1203
    69
  char validTZ;    /* True if tz is valid */
dvander@1203
    70
};
dvander@1203
    71
dvander@1203
    72
dvander@1203
    73
/*
dvander@1203
    74
** Convert zDate into one or more integers.  Additional arguments
dvander@1203
    75
** come in groups of 5 as follows:
dvander@1203
    76
**
dvander@1203
    77
**       N       number of digits in the integer
dvander@1203
    78
**       min     minimum allowed value of the integer
dvander@1203
    79
**       max     maximum allowed value of the integer
dvander@1203
    80
**       nextC   first character after the integer
dvander@1203
    81
**       pVal    where to write the integers value.
dvander@1203
    82
**
dvander@1203
    83
** Conversions continue until one with nextC==0 is encountered.
dvander@1203
    84
** The function returns the number of successful conversions.
dvander@1203
    85
*/
dvander@1203
    86
static int getDigits(const char *zDate, ...){
dvander@1203
    87
  va_list ap;
dvander@1203
    88
  int val;
dvander@1203
    89
  int N;
dvander@1203
    90
  int min;
dvander@1203
    91
  int max;
dvander@1203
    92
  int nextC;
dvander@1203
    93
  int *pVal;
dvander@1203
    94
  int cnt = 0;
dvander@1203
    95
  va_start(ap, zDate);
dvander@1203
    96
  do{
dvander@1203
    97
    N = va_arg(ap, int);
dvander@1203
    98
    min = va_arg(ap, int);
dvander@1203
    99
    max = va_arg(ap, int);
dvander@1203
   100
    nextC = va_arg(ap, int);
dvander@1203
   101
    pVal = va_arg(ap, int*);
dvander@1203
   102
    val = 0;
dvander@1203
   103
    while( N-- ){
dvander@1203
   104
      if( !isdigit(*(u8*)zDate) ){
dvander@1203
   105
        goto end_getDigits;
dvander@1203
   106
      }
dvander@1203
   107
      val = val*10 + *zDate - '0';
dvander@1203
   108
      zDate++;
dvander@1203
   109
    }
dvander@1203
   110
    if( val<min || val>max || (nextC!=0 && nextC!=*zDate) ){
dvander@1203
   111
      goto end_getDigits;
dvander@1203
   112
    }
dvander@1203
   113
    *pVal = val;
dvander@1203
   114
    zDate++;
dvander@1203
   115
    cnt++;
dvander@1203
   116
  }while( nextC );
dvander@1203
   117
end_getDigits:
dvander@1203
   118
  va_end(ap);
dvander@1203
   119
  return cnt;
dvander@1203
   120
}
dvander@1203
   121
dvander@1203
   122
/*
dvander@1203
   123
** Read text from z[] and convert into a floating point number.  Return
dvander@1203
   124
** the number of digits converted.
dvander@1203
   125
*/
dvander@1203
   126
#define getValue sqlite3AtoF
dvander@1203
   127
dvander@1203
   128
/*
dvander@1203
   129
** Parse a timezone extension on the end of a date-time.
dvander@1203
   130
** The extension is of the form:
dvander@1203
   131
**
dvander@1203
   132
**        (+/-)HH:MM
dvander@1203
   133
**
dvander@1203
   134
** If the parse is successful, write the number of minutes
dvander@1203
   135
** of change in *pnMin and return 0.  If a parser error occurs,
dvander@1203
   136
** return 0.
dvander@1203
   137
**
dvander@1203
   138
** A missing specifier is not considered an error.
dvander@1203
   139
*/
dvander@1203
   140
static int parseTimezone(const char *zDate, DateTime *p){
dvander@1203
   141
  int sgn = 0;
dvander@1203
   142
  int nHr, nMn;
dvander@1203
   143
  while( isspace(*(u8*)zDate) ){ zDate++; }
dvander@1203
   144
  p->tz = 0;
dvander@1203
   145
  if( *zDate=='-' ){
dvander@1203
   146
    sgn = -1;
dvander@1203
   147
  }else if( *zDate=='+' ){
dvander@1203
   148
    sgn = +1;
dvander@1203
   149
  }else{
dvander@1203
   150
    return *zDate!=0;
dvander@1203
   151
  }
dvander@1203
   152
  zDate++;
dvander@1203
   153
  if( getDigits(zDate, 2, 0, 14, ':', &nHr, 2, 0, 59, 0, &nMn)!=2 ){
dvander@1203
   154
    return 1;
dvander@1203
   155
  }
dvander@1203
   156
  zDate += 5;
dvander@1203
   157
  p->tz = sgn*(nMn + nHr*60);
dvander@1203
   158
  while( isspace(*(u8*)zDate) ){ zDate++; }
dvander@1203
   159
  return *zDate!=0;
dvander@1203
   160
}
dvander@1203
   161
dvander@1203
   162
/*
dvander@1203
   163
** Parse times of the form HH:MM or HH:MM:SS or HH:MM:SS.FFFF.
dvander@1203
   164
** The HH, MM, and SS must each be exactly 2 digits.  The
dvander@1203
   165
** fractional seconds FFFF can be one or more digits.
dvander@1203
   166
**
dvander@1203
   167
** Return 1 if there is a parsing error and 0 on success.
dvander@1203
   168
*/
dvander@1203
   169
static int parseHhMmSs(const char *zDate, DateTime *p){
dvander@1203
   170
  int h, m, s;
dvander@1203
   171
  double ms = 0.0;
dvander@1203
   172
  if( getDigits(zDate, 2, 0, 24, ':', &h, 2, 0, 59, 0, &m)!=2 ){
dvander@1203
   173
    return 1;
dvander@1203
   174
  }
dvander@1203
   175
  zDate += 5;
dvander@1203
   176
  if( *zDate==':' ){
dvander@1203
   177
    zDate++;
dvander@1203
   178
    if( getDigits(zDate, 2, 0, 59, 0, &s)!=1 ){
dvander@1203
   179
      return 1;
dvander@1203
   180
    }
dvander@1203
   181
    zDate += 2;
dvander@1203
   182
    if( *zDate=='.' && isdigit((u8)zDate[1]) ){
dvander@1203
   183
      double rScale = 1.0;
dvander@1203
   184
      zDate++;
dvander@1203
   185
      while( isdigit(*(u8*)zDate) ){
dvander@1203
   186
        ms = ms*10.0 + *zDate - '0';
dvander@1203
   187
        rScale *= 10.0;
dvander@1203
   188
        zDate++;
dvander@1203
   189
      }
dvander@1203
   190
      ms /= rScale;
dvander@1203
   191
    }
dvander@1203
   192
  }else{
dvander@1203
   193
    s = 0;
dvander@1203
   194
  }
dvander@1203
   195
  p->validJD = 0;
dvander@1203
   196
  p->validHMS = 1;
dvander@1203
   197
  p->h = h;
dvander@1203
   198
  p->m = m;
dvander@1203
   199
  p->s = s + ms;
dvander@1203
   200
  if( parseTimezone(zDate, p) ) return 1;
dvander@1203
   201
  p->validTZ = p->tz!=0;
dvander@1203
   202
  return 0;
dvander@1203
   203
}
dvander@1203
   204
dvander@1203
   205
/*
dvander@1203
   206
** Convert from YYYY-MM-DD HH:MM:SS to julian day.  We always assume
dvander@1203
   207
** that the YYYY-MM-DD is according to the Gregorian calendar.
dvander@1203
   208
**
dvander@1203
   209
** Reference:  Meeus page 61
dvander@1203
   210
*/
dvander@1203
   211
static void computeJD(DateTime *p){
dvander@1203
   212
  int Y, M, D, A, B, X1, X2;
dvander@1203
   213
dvander@1203
   214
  if( p->validJD ) return;
dvander@1203
   215
  if( p->validYMD ){
dvander@1203
   216
    Y = p->Y;
dvander@1203
   217
    M = p->M;
dvander@1203
   218
    D = p->D;
dvander@1203
   219
  }else{
dvander@1203
   220
    Y = 2000;  /* If no YMD specified, assume 2000-Jan-01 */
dvander@1203
   221
    M = 1;
dvander@1203
   222
    D = 1;
dvander@1203
   223
  }
dvander@1203
   224
  if( M<=2 ){
dvander@1203
   225
    Y--;
dvander@1203
   226
    M += 12;
dvander@1203
   227
  }
dvander@1203
   228
  A = Y/100;
dvander@1203
   229
  B = 2 - A + (A/4);
dvander@1203
   230
  X1 = 365.25*(Y+4716);
dvander@1203
   231
  X2 = 30.6001*(M+1);
dvander@1203
   232
  p->rJD = X1 + X2 + D + B - 1524.5;
dvander@1203
   233
  p->validJD = 1;
dvander@1203
   234
  if( p->validHMS ){
dvander@1203
   235
    p->rJD += (p->h*3600.0 + p->m*60.0 + p->s)/86400.0;
dvander@1203
   236
    if( p->validTZ ){
dvander@1203
   237
      p->rJD -= p->tz*60/86400.0;
dvander@1203
   238
      p->validYMD = 0;
dvander@1203
   239
      p->validHMS = 0;
dvander@1203
   240
      p->validTZ = 0;
dvander@1203
   241
    }
dvander@1203
   242
  }
dvander@1203
   243
}
dvander@1203
   244
dvander@1203
   245
/*
dvander@1203
   246
** Parse dates of the form
dvander@1203
   247
**
dvander@1203
   248
**     YYYY-MM-DD HH:MM:SS.FFF
dvander@1203
   249
**     YYYY-MM-DD HH:MM:SS
dvander@1203
   250
**     YYYY-MM-DD HH:MM
dvander@1203
   251
**     YYYY-MM-DD
dvander@1203
   252
**
dvander@1203
   253
** Write the result into the DateTime structure and return 0
dvander@1203
   254
** on success and 1 if the input string is not a well-formed
dvander@1203
   255
** date.
dvander@1203
   256
*/
dvander@1203
   257
static int parseYyyyMmDd(const char *zDate, DateTime *p){
dvander@1203
   258
  int Y, M, D, neg;
dvander@1203
   259
dvander@1203
   260
  if( zDate[0]=='-' ){
dvander@1203
   261
    zDate++;
dvander@1203
   262
    neg = 1;
dvander@1203
   263
  }else{
dvander@1203
   264
    neg = 0;
dvander@1203
   265
  }
dvander@1203
   266
  if( getDigits(zDate,4,0,9999,'-',&Y,2,1,12,'-',&M,2,1,31,0,&D)!=3 ){
dvander@1203
   267
    return 1;
dvander@1203
   268
  }
dvander@1203
   269
  zDate += 10;
dvander@1203
   270
  while( isspace(*(u8*)zDate) || 'T'==*(u8*)zDate ){ zDate++; }
dvander@1203
   271
  if( parseHhMmSs(zDate, p)==0 ){
dvander@1203
   272
    /* We got the time */
dvander@1203
   273
  }else if( *zDate==0 ){
dvander@1203
   274
    p->validHMS = 0;
dvander@1203
   275
  }else{
dvander@1203
   276
    return 1;
dvander@1203
   277
  }
dvander@1203
   278
  p->validJD = 0;
dvander@1203
   279
  p->validYMD = 1;
dvander@1203
   280
  p->Y = neg ? -Y : Y;
dvander@1203
   281
  p->M = M;
dvander@1203
   282
  p->D = D;
dvander@1203
   283
  if( p->validTZ ){
dvander@1203
   284
    computeJD(p);
dvander@1203
   285
  }
dvander@1203
   286
  return 0;
dvander@1203
   287
}
dvander@1203
   288
dvander@1203
   289
/*
dvander@1203
   290
** Attempt to parse the given string into a Julian Day Number.  Return
dvander@1203
   291
** the number of errors.
dvander@1203
   292
**
dvander@1203
   293
** The following are acceptable forms for the input string:
dvander@1203
   294
**
dvander@1203
   295
**      YYYY-MM-DD HH:MM:SS.FFF  +/-HH:MM
dvander@1203
   296
**      DDDD.DD 
dvander@1203
   297
**      now
dvander@1203
   298
**
dvander@1203
   299
** In the first form, the +/-HH:MM is always optional.  The fractional
dvander@1203
   300
** seconds extension (the ".FFF") is optional.  The seconds portion
dvander@1203
   301
** (":SS.FFF") is option.  The year and date can be omitted as long
dvander@1203
   302
** as there is a time string.  The time string can be omitted as long
dvander@1203
   303
** as there is a year and date.
dvander@1203
   304
*/
dvander@1645
   305
static int parseDateOrTime(
dvander@1645
   306
  sqlite3_context *context, 
dvander@1645
   307
  const char *zDate, 
dvander@1645
   308
  DateTime *p
dvander@1645
   309
){
dvander@1203
   310
  memset(p, 0, sizeof(*p));
dvander@1203
   311
  if( parseYyyyMmDd(zDate,p)==0 ){
dvander@1203
   312
    return 0;
dvander@1203
   313
  }else if( parseHhMmSs(zDate, p)==0 ){
dvander@1203
   314
    return 0;
dvander@1203
   315
  }else if( sqlite3StrICmp(zDate,"now")==0){
dvander@1203
   316
    double r;
dvander@1645
   317
    sqlite3OsCurrentTime((sqlite3_vfs *)sqlite3_user_data(context), &r);
dvander@1203
   318
    p->rJD = r;
dvander@1203
   319
    p->validJD = 1;
dvander@1203
   320
    return 0;
dvander@1203
   321
  }else if( sqlite3IsNumber(zDate, 0, SQLITE_UTF8) ){
dvander@1203
   322
    getValue(zDate, &p->rJD);
dvander@1203
   323
    p->validJD = 1;
dvander@1203
   324
    return 0;
dvander@1203
   325
  }
dvander@1203
   326
  return 1;
dvander@1203
   327
}
dvander@1203
   328
dvander@1203
   329
/*
dvander@1203
   330
** Compute the Year, Month, and Day from the julian day number.
dvander@1203
   331
*/
dvander@1203
   332
static void computeYMD(DateTime *p){
dvander@1203
   333
  int Z, A, B, C, D, E, X1;
dvander@1203
   334
  if( p->validYMD ) return;
dvander@1203
   335
  if( !p->validJD ){
dvander@1203
   336
    p->Y = 2000;
dvander@1203
   337
    p->M = 1;
dvander@1203
   338
    p->D = 1;
dvander@1203
   339
  }else{
dvander@1203
   340
    Z = p->rJD + 0.5;
dvander@1203
   341
    A = (Z - 1867216.25)/36524.25;
dvander@1203
   342
    A = Z + 1 + A - (A/4);
dvander@1203
   343
    B = A + 1524;
dvander@1203
   344
    C = (B - 122.1)/365.25;
dvander@1203
   345
    D = 365.25*C;
dvander@1203
   346
    E = (B-D)/30.6001;
dvander@1203
   347
    X1 = 30.6001*E;
dvander@1203
   348
    p->D = B - D - X1;
dvander@1203
   349
    p->M = E<14 ? E-1 : E-13;
dvander@1203
   350
    p->Y = p->M>2 ? C - 4716 : C - 4715;
dvander@1203
   351
  }
dvander@1203
   352
  p->validYMD = 1;
dvander@1203
   353
}
dvander@1203
   354
dvander@1203
   355
/*
dvander@1203
   356
** Compute the Hour, Minute, and Seconds from the julian day number.
dvander@1203
   357
*/
dvander@1203
   358
static void computeHMS(DateTime *p){
dvander@1203
   359
  int Z, s;
dvander@1203
   360
  if( p->validHMS ) return;
dvander@1203
   361
  computeJD(p);
dvander@1203
   362
  Z = p->rJD + 0.5;
dvander@1203
   363
  s = (p->rJD + 0.5 - Z)*86400000.0 + 0.5;
dvander@1203
   364
  p->s = 0.001*s;
dvander@1203
   365
  s = p->s;
dvander@1203
   366
  p->s -= s;
dvander@1203
   367
  p->h = s/3600;
dvander@1203
   368
  s -= p->h*3600;
dvander@1203
   369
  p->m = s/60;
dvander@1203
   370
  p->s += s - p->m*60;
dvander@1203
   371
  p->validHMS = 1;
dvander@1203
   372
}
dvander@1203
   373
dvander@1203
   374
/*
dvander@1203
   375
** Compute both YMD and HMS
dvander@1203
   376
*/
dvander@1203
   377
static void computeYMD_HMS(DateTime *p){
dvander@1203
   378
  computeYMD(p);
dvander@1203
   379
  computeHMS(p);
dvander@1203
   380
}
dvander@1203
   381
dvander@1203
   382
/*
dvander@1203
   383
** Clear the YMD and HMS and the TZ
dvander@1203
   384
*/
dvander@1203
   385
static void clearYMD_HMS_TZ(DateTime *p){
dvander@1203
   386
  p->validYMD = 0;
dvander@1203
   387
  p->validHMS = 0;
dvander@1203
   388
  p->validTZ = 0;
dvander@1203
   389
}
dvander@1203
   390
dvander@1203
   391
/*
dvander@1203
   392
** Compute the difference (in days) between localtime and UTC (a.k.a. GMT)
dvander@1203
   393
** for the time value p where p is in UTC.
dvander@1203
   394
*/
dvander@1203
   395
static double localtimeOffset(DateTime *p){
dvander@1203
   396
  DateTime x, y;
dvander@1203
   397
  time_t t;
dvander@1203
   398
  x = *p;
dvander@1203
   399
  computeYMD_HMS(&x);
dvander@1203
   400
  if( x.Y<1971 || x.Y>=2038 ){
dvander@1203
   401
    x.Y = 2000;
dvander@1203
   402
    x.M = 1;
dvander@1203
   403
    x.D = 1;
dvander@1203
   404
    x.h = 0;
dvander@1203
   405
    x.m = 0;
dvander@1203
   406
    x.s = 0.0;
dvander@1203
   407
  } else {
dvander@1203
   408
    int s = x.s + 0.5;
dvander@1203
   409
    x.s = s;
dvander@1203
   410
  }
dvander@1203
   411
  x.tz = 0;
dvander@1203
   412
  x.validJD = 0;
dvander@1203
   413
  computeJD(&x);
dvander@1203
   414
  t = (x.rJD-2440587.5)*86400.0 + 0.5;
dvander@1203
   415
#ifdef HAVE_LOCALTIME_R
dvander@1203
   416
  {
dvander@1203
   417
    struct tm sLocal;
dvander@1203
   418
    localtime_r(&t, &sLocal);
dvander@1203
   419
    y.Y = sLocal.tm_year + 1900;
dvander@1203
   420
    y.M = sLocal.tm_mon + 1;
dvander@1203
   421
    y.D = sLocal.tm_mday;
dvander@1203
   422
    y.h = sLocal.tm_hour;
dvander@1203
   423
    y.m = sLocal.tm_min;
dvander@1203
   424
    y.s = sLocal.tm_sec;
dvander@1203
   425
  }
dvander@1203
   426
#else
dvander@1203
   427
  {
dvander@1203
   428
    struct tm *pTm;
dvander@1645
   429
    sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
dvander@1203
   430
    pTm = localtime(&t);
dvander@1203
   431
    y.Y = pTm->tm_year + 1900;
dvander@1203
   432
    y.M = pTm->tm_mon + 1;
dvander@1203
   433
    y.D = pTm->tm_mday;
dvander@1203
   434
    y.h = pTm->tm_hour;
dvander@1203
   435
    y.m = pTm->tm_min;
dvander@1203
   436
    y.s = pTm->tm_sec;
dvander@1645
   437
    sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
dvander@1203
   438
  }
dvander@1203
   439
#endif
dvander@1203
   440
  y.validYMD = 1;
dvander@1203
   441
  y.validHMS = 1;
dvander@1203
   442
  y.validJD = 0;
dvander@1203
   443
  y.validTZ = 0;
dvander@1203
   444
  computeJD(&y);
dvander@1203
   445
  return y.rJD - x.rJD;
dvander@1203
   446
}
dvander@1203
   447
dvander@1203
   448
/*
dvander@1203
   449
** Process a modifier to a date-time stamp.  The modifiers are
dvander@1203
   450
** as follows:
dvander@1203
   451
**
dvander@1203
   452
**     NNN days
dvander@1203
   453
**     NNN hours
dvander@1203
   454
**     NNN minutes
dvander@1203
   455
**     NNN.NNNN seconds
dvander@1203
   456
**     NNN months
dvander@1203
   457
**     NNN years
dvander@1203
   458
**     start of month
dvander@1203
   459
**     start of year
dvander@1203
   460
**     start of week
dvander@1203
   461
**     start of day
dvander@1203
   462
**     weekday N
dvander@1203
   463
**     unixepoch
dvander@1203
   464
**     localtime
dvander@1203
   465
**     utc
dvander@1203
   466
**
dvander@1203
   467
** Return 0 on success and 1 if there is any kind of error.
dvander@1203
   468
*/
dvander@1203
   469
static int parseModifier(const char *zMod, DateTime *p){
dvander@1203
   470
  int rc = 1;
dvander@1203
   471
  int n;
dvander@1203
   472
  double r;
dvander@1203
   473
  char *z, zBuf[30];
dvander@1203
   474
  z = zBuf;
dvander@1203
   475
  for(n=0; n<sizeof(zBuf)-1 && zMod[n]; n++){
dvander@1203
   476
    z[n] = tolower(zMod[n]);
dvander@1203
   477
  }
dvander@1203
   478
  z[n] = 0;
dvander@1203
   479
  switch( z[0] ){
dvander@1203
   480
    case 'l': {
dvander@1203
   481
      /*    localtime
dvander@1203
   482
      **
dvander@1203
   483
      ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
dvander@1203
   484
      ** show local time.
dvander@1203
   485
      */
dvander@1203
   486
      if( strcmp(z, "localtime")==0 ){
dvander@1203
   487
        computeJD(p);
dvander@1203
   488
        p->rJD += localtimeOffset(p);
dvander@1203
   489
        clearYMD_HMS_TZ(p);
dvander@1203
   490
        rc = 0;
dvander@1203
   491
      }
dvander@1203
   492
      break;
dvander@1203
   493
    }
dvander@1203
   494
    case 'u': {
dvander@1203
   495
      /*
dvander@1203
   496
      **    unixepoch
dvander@1203
   497
      **
dvander@1203
   498
      ** Treat the current value of p->rJD as the number of
dvander@1203
   499
      ** seconds since 1970.  Convert to a real julian day number.
dvander@1203
   500
      */
dvander@1203
   501
      if( strcmp(z, "unixepoch")==0 && p->validJD ){
dvander@1203
   502
        p->rJD = p->rJD/86400.0 + 2440587.5;
dvander@1203
   503
        clearYMD_HMS_TZ(p);
dvander@1203
   504
        rc = 0;
dvander@1203
   505
      }else if( strcmp(z, "utc")==0 ){
dvander@1203
   506
        double c1;
dvander@1203
   507
        computeJD(p);
dvander@1203
   508
        c1 = localtimeOffset(p);
dvander@1203
   509
        p->rJD -= c1;
dvander@1203
   510
        clearYMD_HMS_TZ(p);
dvander@1203
   511
        p->rJD += c1 - localtimeOffset(p);
dvander@1203
   512
        rc = 0;
dvander@1203
   513
      }
dvander@1203
   514
      break;
dvander@1203
   515
    }
dvander@1203
   516
    case 'w': {
dvander@1203
   517
      /*
dvander@1203
   518
      **    weekday N
dvander@1203
   519
      **
dvander@1203
   520
      ** Move the date to the same time on the next occurrence of
dvander@1203
   521
      ** weekday N where 0==Sunday, 1==Monday, and so forth.  If the
dvander@1203
   522
      ** date is already on the appropriate weekday, this is a no-op.
dvander@1203
   523
      */
dvander@1203
   524
      if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0
dvander@1203
   525
                 && (n=r)==r && n>=0 && r<7 ){
dvander@1203
   526
        int Z;
dvander@1203
   527
        computeYMD_HMS(p);
dvander@1203
   528
        p->validTZ = 0;
dvander@1203
   529
        p->validJD = 0;
dvander@1203
   530
        computeJD(p);
dvander@1203
   531
        Z = p->rJD + 1.5;
dvander@1203
   532
        Z %= 7;
dvander@1203
   533
        if( Z>n ) Z -= 7;
dvander@1203
   534
        p->rJD += n - Z;
dvander@1203
   535
        clearYMD_HMS_TZ(p);
dvander@1203
   536
        rc = 0;
dvander@1203
   537
      }
dvander@1203
   538
      break;
dvander@1203
   539
    }
dvander@1203
   540
    case 's': {
dvander@1203
   541
      /*
dvander@1203
   542
      **    start of TTTTT
dvander@1203
   543
      **
dvander@1203
   544
      ** Move the date backwards to the beginning of the current day,
dvander@1203
   545
      ** or month or year.
dvander@1203
   546
      */
dvander@1203
   547
      if( strncmp(z, "start of ", 9)!=0 ) break;
dvander@1203
   548
      z += 9;
dvander@1203
   549
      computeYMD(p);
dvander@1203
   550
      p->validHMS = 1;
dvander@1203
   551
      p->h = p->m = 0;
dvander@1203
   552
      p->s = 0.0;
dvander@1203
   553
      p->validTZ = 0;
dvander@1203
   554
      p->validJD = 0;
dvander@1203
   555
      if( strcmp(z,"month")==0 ){
dvander@1203
   556
        p->D = 1;
dvander@1203
   557
        rc = 0;
dvander@1203
   558
      }else if( strcmp(z,"year")==0 ){
dvander@1203
   559
        computeYMD(p);
dvander@1203
   560
        p->M = 1;
dvander@1203
   561
        p->D = 1;
dvander@1203
   562
        rc = 0;
dvander@1203
   563
      }else if( strcmp(z,"day")==0 ){
dvander@1203
   564
        rc = 0;
dvander@1203
   565
      }
dvander@1203
   566
      break;
dvander@1203
   567
    }
dvander@1203
   568
    case '+':
dvander@1203
   569
    case '-':
dvander@1203
   570
    case '0':
dvander@1203
   571
    case '1':
dvander@1203
   572
    case '2':
dvander@1203
   573
    case '3':
dvander@1203
   574
    case '4':
dvander@1203
   575
    case '5':
dvander@1203
   576
    case '6':
dvander@1203
   577
    case '7':
dvander@1203
   578
    case '8':
dvander@1203
   579
    case '9': {
dvander@1203
   580
      n = getValue(z, &r);
dvander@1203
   581
      assert( n>=1 );
dvander@1203
   582
      if( z[n]==':' ){
dvander@1203
   583
        /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the
dvander@1203
   584
        ** specified number of hours, minutes, seconds, and fractional seconds
dvander@1203
   585
        ** to the time.  The ".FFF" may be omitted.  The ":SS.FFF" may be
dvander@1203
   586
        ** omitted.
dvander@1203
   587
        */
dvander@1203
   588
        const char *z2 = z;
dvander@1203
   589
        DateTime tx;
dvander@1203
   590
        int day;
dvander@1203
   591
        if( !isdigit(*(u8*)z2) ) z2++;
dvander@1203
   592
        memset(&tx, 0, sizeof(tx));
dvander@1203
   593
        if( parseHhMmSs(z2, &tx) ) break;
dvander@1203
   594
        computeJD(&tx);
dvander@1203
   595
        tx.rJD -= 0.5;
dvander@1203
   596
        day = (int)tx.rJD;
dvander@1203
   597
        tx.rJD -= day;
dvander@1203
   598
        if( z[0]=='-' ) tx.rJD = -tx.rJD;
dvander@1203
   599
        computeJD(p);
dvander@1203
   600
        clearYMD_HMS_TZ(p);
dvander@1203
   601
        p->rJD += tx.rJD;
dvander@1203
   602
        rc = 0;
dvander@1203
   603
        break;
dvander@1203
   604
      }
dvander@1203
   605
      z += n;
dvander@1203
   606
      while( isspace(*(u8*)z) ) z++;
dvander@1203
   607
      n = strlen(z);
dvander@1203
   608
      if( n>10 || n<3 ) break;
dvander@1203
   609
      if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
dvander@1203
   610
      computeJD(p);
dvander@1203
   611
      rc = 0;
dvander@1203
   612
      if( n==3 && strcmp(z,"day")==0 ){
dvander@1203
   613
        p->rJD += r;
dvander@1203
   614
      }else if( n==4 && strcmp(z,"hour")==0 ){
dvander@1203
   615
        p->rJD += r/24.0;
dvander@1203
   616
      }else if( n==6 && strcmp(z,"minute")==0 ){
dvander@1203
   617
        p->rJD += r/(24.0*60.0);
dvander@1203
   618
      }else if( n==6 && strcmp(z,"second")==0 ){
dvander@1203
   619
        p->rJD += r/(24.0*60.0*60.0);
dvander@1203
   620
      }else if( n==5 && strcmp(z,"month")==0 ){
dvander@1203
   621
        int x, y;
dvander@1203
   622
        computeYMD_HMS(p);
dvander@1203
   623
        p->M += r;
dvander@1203
   624
        x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
dvander@1203
   625
        p->Y += x;
dvander@1203
   626
        p->M -= x*12;
dvander@1203
   627
        p->validJD = 0;
dvander@1203
   628
        computeJD(p);
dvander@1203
   629
        y = r;
dvander@1203
   630
        if( y!=r ){
dvander@1203
   631
          p->rJD += (r - y)*30.0;
dvander@1203
   632
        }
dvander@1203
   633
      }else if( n==4 && strcmp(z,"year")==0 ){
dvander@1203
   634
        computeYMD_HMS(p);
dvander@1203
   635
        p->Y += r;
dvander@1203
   636
        p->validJD = 0;
dvander@1203
   637
        computeJD(p);
dvander@1203
   638
      }else{
dvander@1203
   639
        rc = 1;
dvander@1203
   640
      }
dvander@1203
   641
      clearYMD_HMS_TZ(p);
dvander@1203
   642
      break;
dvander@1203
   643
    }
dvander@1203
   644
    default: {
dvander@1203
   645
      break;
dvander@1203
   646
    }
dvander@1203
   647
  }
dvander@1203
   648
  return rc;
dvander@1203
   649
}
dvander@1203
   650
dvander@1203
   651
/*
dvander@1203
   652
** Process time function arguments.  argv[0] is a date-time stamp.
dvander@1203
   653
** argv[1] and following are modifiers.  Parse them all and write
dvander@1203
   654
** the resulting time into the DateTime structure p.  Return 0
dvander@1203
   655
** on success and 1 if there are any errors.
dvander@1203
   656
*/
dvander@1645
   657
static int isDate(
dvander@1645
   658
  sqlite3_context *context, 
dvander@1645
   659
  int argc, 
dvander@1645
   660
  sqlite3_value **argv, 
dvander@1645
   661
  DateTime *p
dvander@1645
   662
){
dvander@1203
   663
  int i;
dvander@1203
   664
  const unsigned char *z;
dvander@1203
   665
  if( argc==0 ) return 1;
dvander@1645
   666
  z = sqlite3_value_text(argv[0]);
dvander@1645
   667
  if( !z || parseDateOrTime(context, (char*)z, p) ){
dvander@1203
   668
    return 1;
dvander@1203
   669
  }
dvander@1203
   670
  for(i=1; i<argc; i++){
dvander@1203
   671
    if( (z = sqlite3_value_text(argv[i]))==0 || parseModifier((char*)z, p) ){
dvander@1203
   672
      return 1;
dvander@1203
   673
    }
dvander@1203
   674
  }
dvander@1203
   675
  return 0;
dvander@1203
   676
}
dvander@1203
   677
dvander@1203
   678
dvander@1203
   679
/*
dvander@1203
   680
** The following routines implement the various date and time functions
dvander@1203
   681
** of SQLite.
dvander@1203
   682
*/
dvander@1203
   683
dvander@1203
   684
/*
dvander@1203
   685
**    julianday( TIMESTRING, MOD, MOD, ...)
dvander@1203
   686
**
dvander@1203
   687
** Return the julian day number of the date specified in the arguments
dvander@1203
   688
*/
dvander@1203
   689
static void juliandayFunc(
dvander@1203
   690
  sqlite3_context *context,
dvander@1203
   691
  int argc,
dvander@1203
   692
  sqlite3_value **argv
dvander@1203
   693
){
dvander@1203
   694
  DateTime x;
dvander@1645
   695
  if( isDate(context, argc, argv, &x)==0 ){
dvander@1203
   696
    computeJD(&x);
dvander@1203
   697
    sqlite3_result_double(context, x.rJD);
dvander@1203
   698
  }
dvander@1203
   699
}
dvander@1203
   700
dvander@1203
   701
/*
dvander@1203
   702
**    datetime( TIMESTRING, MOD, MOD, ...)
dvander@1203
   703
**
dvander@1203
   704
** Return YYYY-MM-DD HH:MM:SS
dvander@1203
   705
*/
dvander@1203
   706
static void datetimeFunc(
dvander@1203
   707
  sqlite3_context *context,
dvander@1203
   708
  int argc,
dvander@1203
   709
  sqlite3_value **argv
dvander@1203
   710
){
dvander@1203
   711
  DateTime x;
dvander@1645
   712
  if( isDate(context, argc, argv, &x)==0 ){
dvander@1203
   713
    char zBuf[100];
dvander@1203
   714
    computeYMD_HMS(&x);
dvander@1203
   715
    sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d",
dvander@1203
   716
                     x.Y, x.M, x.D, x.h, x.m, (int)(x.s));
dvander@1203
   717
    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
dvander@1203
   718
  }
dvander@1203
   719
}
dvander@1203
   720
dvander@1203
   721
/*
dvander@1203
   722
**    time( TIMESTRING, MOD, MOD, ...)
dvander@1203
   723
**
dvander@1203
   724
** Return HH:MM:SS
dvander@1203
   725
*/
dvander@1203
   726
static void timeFunc(
dvander@1203
   727
  sqlite3_context *context,
dvander@1203
   728
  int argc,
dvander@1203
   729
  sqlite3_value **argv
dvander@1203
   730
){
dvander@1203
   731
  DateTime x;
dvander@1645
   732
  if( isDate(context, argc, argv, &x)==0 ){
dvander@1203
   733
    char zBuf[100];
dvander@1203
   734
    computeHMS(&x);
dvander@1203
   735
    sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s);
dvander@1203
   736
    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
dvander@1203
   737
  }
dvander@1203
   738
}
dvander@1203
   739
dvander@1203
   740
/*
dvander@1203
   741
**    date( TIMESTRING, MOD, MOD, ...)
dvander@1203
   742
**
dvander@1203
   743
** Return YYYY-MM-DD
dvander@1203
   744
*/
dvander@1203
   745
static void dateFunc(
dvander@1203
   746
  sqlite3_context *context,
dvander@1203
   747
  int argc,
dvander@1203
   748
  sqlite3_value **argv
dvander@1203
   749
){
dvander@1203
   750
  DateTime x;
dvander@1645
   751
  if( isDate(context, argc, argv, &x)==0 ){
dvander@1203
   752
    char zBuf[100];
dvander@1203
   753
    computeYMD(&x);
dvander@1203
   754
    sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D);
dvander@1203
   755
    sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
dvander@1203
   756
  }
dvander@1203
   757
}
dvander@1203
   758
dvander@1203
   759
/*
dvander@1203
   760
**    strftime( FORMAT, TIMESTRING, MOD, MOD, ...)
dvander@1203
   761
**
dvander@1203
   762
** Return a string described by FORMAT.  Conversions as follows:
dvander@1203
   763
**
dvander@1203
   764
**   %d  day of month
dvander@1203
   765
**   %f  ** fractional seconds  SS.SSS
dvander@1203
   766
**   %H  hour 00-24
dvander@1203
   767
**   %j  day of year 000-366
dvander@1203
   768
**   %J  ** Julian day number
dvander@1203
   769
**   %m  month 01-12
dvander@1203
   770
**   %M  minute 00-59
dvander@1203
   771
**   %s  seconds since 1970-01-01
dvander@1203
   772
**   %S  seconds 00-59
dvander@1203
   773
**   %w  day of week 0-6  sunday==0
dvander@1203
   774
**   %W  week of year 00-53
dvander@1203
   775
**   %Y  year 0000-9999
dvander@1203
   776
**   %%  %
dvander@1203
   777
*/
dvander@1203
   778
static void strftimeFunc(
dvander@1203
   779
  sqlite3_context *context,
dvander@1203
   780
  int argc,
dvander@1203
   781
  sqlite3_value **argv
dvander@1203
   782
){
dvander@1203
   783
  DateTime x;
dvander@1203
   784
  u64 n;
dvander@1203
   785
  int i, j;
dvander@1203
   786
  char *z;
dvander@1203
   787
  const char *zFmt = (const char*)sqlite3_value_text(argv[0]);
dvander@1203
   788
  char zBuf[100];
dvander@1645
   789
  if( zFmt==0 || isDate(context, argc-1, argv+1, &x) ) return;
dvander@1203
   790
  for(i=0, n=1; zFmt[i]; i++, n++){
dvander@1203
   791
    if( zFmt[i]=='%' ){
dvander@1203
   792
      switch( zFmt[i+1] ){
dvander@1203
   793
        case 'd':
dvander@1203
   794
        case 'H':
dvander@1203
   795
        case 'm':
dvander@1203
   796
        case 'M':
dvander@1203
   797
        case 'S':
dvander@1203
   798
        case 'W':
dvander@1203
   799
          n++;
dvander@1203
   800
          /* fall thru */
dvander@1203
   801
        case 'w':
dvander@1203
   802
        case '%':
dvander@1203
   803
          break;
dvander@1203
   804
        case 'f':
dvander@1203
   805
          n += 8;
dvander@1203
   806
          break;
dvander@1203
   807
        case 'j':
dvander@1203
   808
          n += 3;
dvander@1203
   809
          break;
dvander@1203
   810
        case 'Y':
dvander@1203
   811
          n += 8;
dvander@1203
   812
          break;
dvander@1203
   813
        case 's':
dvander@1203
   814
        case 'J':
dvander@1203
   815
          n += 50;
dvander@1203
   816
          break;
dvander@1203
   817
        default:
dvander@1203
   818
          return;  /* ERROR.  return a NULL */
dvander@1203
   819
      }
dvander@1203
   820
      i++;
dvander@1203
   821
    }
dvander@1203
   822
  }
dvander@1203
   823
  if( n<sizeof(zBuf) ){
dvander@1203
   824
    z = zBuf;
dvander@1203
   825
  }else if( n>SQLITE_MAX_LENGTH ){
dvander@1203
   826
    sqlite3_result_error_toobig(context);
dvander@1203
   827
    return;
dvander@1203
   828
  }else{
dvander@1645
   829
    z = sqlite3_malloc( n );
dvander@1203
   830
    if( z==0 ) return;
dvander@1203
   831
  }
dvander@1203
   832
  computeJD(&x);
dvander@1203
   833
  computeYMD_HMS(&x);
dvander@1203
   834
  for(i=j=0; zFmt[i]; i++){
dvander@1203
   835
    if( zFmt[i]!='%' ){
dvander@1203
   836
      z[j++] = zFmt[i];
dvander@1203
   837
    }else{
dvander@1203
   838
      i++;
dvander@1203
   839
      switch( zFmt[i] ){
dvander@1203
   840
        case 'd':  sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break;
dvander@1203
   841
        case 'f': {
dvander@1203
   842
          double s = x.s;
dvander@1203
   843
          if( s>59.999 ) s = 59.999;
dvander@1203
   844
          sqlite3_snprintf(7, &z[j],"%06.3f", s);
dvander@1203
   845
          j += strlen(&z[j]);
dvander@1203
   846
          break;
dvander@1203
   847
        }
dvander@1203
   848
        case 'H':  sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break;
dvander@1203
   849
        case 'W': /* Fall thru */
dvander@1203
   850
        case 'j': {
dvander@1203
   851
          int nDay;             /* Number of days since 1st day of year */
dvander@1203
   852
          DateTime y = x;
dvander@1203
   853
          y.validJD = 0;
dvander@1203
   854
          y.M = 1;
dvander@1203
   855
          y.D = 1;
dvander@1203
   856
          computeJD(&y);
dvander@1203
   857
          nDay = x.rJD - y.rJD + 0.5;
dvander@1203
   858
          if( zFmt[i]=='W' ){
dvander@1203
   859
            int wd;   /* 0=Monday, 1=Tuesday, ... 6=Sunday */
dvander@1203
   860
            wd = ((int)(x.rJD+0.5)) % 7;
dvander@1203
   861
            sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7);
dvander@1203
   862
            j += 2;
dvander@1203
   863
          }else{
dvander@1203
   864
            sqlite3_snprintf(4, &z[j],"%03d",nDay+1);
dvander@1203
   865
            j += 3;
dvander@1203
   866
          }
dvander@1203
   867
          break;
dvander@1203
   868
        }
dvander@1203
   869
        case 'J': {
dvander@1203
   870
          sqlite3_snprintf(20, &z[j],"%.16g",x.rJD);
dvander@1203
   871
          j+=strlen(&z[j]);
dvander@1203
   872
          break;
dvander@1203
   873
        }
dvander@1203
   874
        case 'm':  sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
dvander@1203
   875
        case 'M':  sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;
dvander@1203
   876
        case 's': {
dvander@1203
   877
          sqlite3_snprintf(30,&z[j],"%d",
dvander@1203
   878
                           (int)((x.rJD-2440587.5)*86400.0 + 0.5));
dvander@1203
   879
          j += strlen(&z[j]);
dvander@1203
   880
          break;
dvander@1203
   881
        }
dvander@1203
   882
        case 'S':  sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break;
dvander@1203
   883
        case 'w':  z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break;
dvander@1203
   884
        case 'Y':  sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=strlen(&z[j]);break;
dvander@1203
   885
        case '%':  z[j++] = '%'; break;
dvander@1203
   886
      }
dvander@1203
   887
    }
dvander@1203
   888
  }
dvander@1203
   889
  z[j] = 0;
dvander@1203
   890
  sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT);
dvander@1203
   891
  if( z!=zBuf ){
dvander@1645
   892
    sqlite3_free(z);
dvander@1203
   893
  }
dvander@1203
   894
}
dvander@1203
   895
dvander@1203
   896
/*
dvander@1203
   897
** current_time()
dvander@1203
   898
**
dvander@1203
   899
** This function returns the same value as time('now').
dvander@1203
   900
*/
dvander@1203
   901
static void ctimeFunc(
dvander@1203
   902
  sqlite3_context *context,
dvander@1203
   903
  int argc,
dvander@1203
   904
  sqlite3_value **argv
dvander@1203
   905
){
dvander@1645
   906
  sqlite3_value *pVal = sqlite3ValueNew(0);
dvander@1203
   907
  if( pVal ){
dvander@1203
   908
    sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
dvander@1203
   909
    timeFunc(context, 1, &pVal);
dvander@1203
   910
    sqlite3ValueFree(pVal);
dvander@1203
   911
  }
dvander@1203
   912
}
dvander@1203
   913
dvander@1203
   914
/*
dvander@1203
   915
** current_date()
dvander@1203
   916
**
dvander@1203
   917
** This function returns the same value as date('now').
dvander@1203
   918
*/
dvander@1203
   919
static void cdateFunc(
dvander@1203
   920
  sqlite3_context *context,
dvander@1203
   921
  int argc,
dvander@1203
   922
  sqlite3_value **argv
dvander@1203
   923
){
dvander@1645
   924
  sqlite3_value *pVal = sqlite3ValueNew(0);
dvander@1203
   925
  if( pVal ){
dvander@1203
   926
    sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
dvander@1203
   927
    dateFunc(context, 1, &pVal);
dvander@1203
   928
    sqlite3ValueFree(pVal);
dvander@1203
   929
  }
dvander@1203
   930
}
dvander@1203
   931
dvander@1203
   932
/*
dvander@1203
   933
** current_timestamp()
dvander@1203
   934
**
dvander@1203
   935
** This function returns the same value as datetime('now').
dvander@1203
   936
*/
dvander@1203
   937
static void ctimestampFunc(
dvander@1203
   938
  sqlite3_context *context,
dvander@1203
   939
  int argc,
dvander@1203
   940
  sqlite3_value **argv
dvander@1203
   941
){
dvander@1645
   942
  sqlite3_value *pVal = sqlite3ValueNew(0);
dvander@1203
   943
  if( pVal ){
dvander@1203
   944
    sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC);
dvander@1203
   945
    datetimeFunc(context, 1, &pVal);
dvander@1203
   946
    sqlite3ValueFree(pVal);
dvander@1203
   947
  }
dvander@1203
   948
}
dvander@1203
   949
#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */
dvander@1203
   950
dvander@1203
   951
#ifdef SQLITE_OMIT_DATETIME_FUNCS
dvander@1203
   952
/*
dvander@1203
   953
** If the library is compiled to omit the full-scale date and time
dvander@1203
   954
** handling (to get a smaller binary), the following minimal version
dvander@1203
   955
** of the functions current_time(), current_date() and current_timestamp()
dvander@1203
   956
** are included instead. This is to support column declarations that
dvander@1203
   957
** include "DEFAULT CURRENT_TIME" etc.
dvander@1203
   958
**
dvander@1203
   959
** This function uses the C-library functions time(), gmtime()
dvander@1203
   960
** and strftime(). The format string to pass to strftime() is supplied
dvander@1203
   961
** as the user-data for the function.
dvander@1203
   962
*/
dvander@1203
   963
static void currentTimeFunc(
dvander@1203
   964
  sqlite3_context *context,
dvander@1203
   965
  int argc,
dvander@1203
   966
  sqlite3_value **argv
dvander@1203
   967
){
dvander@1203
   968
  time_t t;
dvander@1203
   969
  char *zFormat = (char *)sqlite3_user_data(context);
dvander@1203
   970
  char zBuf[20];
dvander@1203
   971
dvander@1203
   972
  time(&t);
dvander@1203
   973
#ifdef SQLITE_TEST
dvander@1203
   974
  {
dvander@1203
   975
    extern int sqlite3_current_time;  /* See os_XXX.c */
dvander@1203
   976
    if( sqlite3_current_time ){
dvander@1203
   977
      t = sqlite3_current_time;
dvander@1203
   978
    }
dvander@1203
   979
  }
dvander@1203
   980
#endif
dvander@1203
   981
dvander@1203
   982
#ifdef HAVE_GMTIME_R
dvander@1203
   983
  {
dvander@1203
   984
    struct tm sNow;
dvander@1203
   985
    gmtime_r(&t, &sNow);
dvander@1203
   986
    strftime(zBuf, 20, zFormat, &sNow);
dvander@1203
   987
  }
dvander@1203
   988
#else
dvander@1203
   989
  {
dvander@1203
   990
    struct tm *pTm;
dvander@1645
   991
    sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
dvander@1203
   992
    pTm = gmtime(&t);
dvander@1203
   993
    strftime(zBuf, 20, zFormat, pTm);
dvander@1645
   994
    sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER));
dvander@1203
   995
  }
dvander@1203
   996
#endif
dvander@1203
   997
dvander@1203
   998
  sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);
dvander@1203
   999
}
dvander@1203
  1000
#endif
dvander@1203
  1001
dvander@1203
  1002
/*
dvander@1203
  1003
** This function registered all of the above C functions as SQL
dvander@1203
  1004
** functions.  This should be the only routine in this file with
dvander@1203
  1005
** external linkage.
dvander@1203
  1006
*/
dvander@1203
  1007
void sqlite3RegisterDateTimeFunctions(sqlite3 *db){
dvander@1203
  1008
#ifndef SQLITE_OMIT_DATETIME_FUNCS
dvander@1203
  1009
  static const struct {
dvander@1203
  1010
     char *zName;
dvander@1203
  1011
     int nArg;
dvander@1203
  1012
     void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
dvander@1203
  1013
  } aFuncs[] = {
dvander@1203
  1014
    { "julianday", -1, juliandayFunc   },
dvander@1203
  1015
    { "date",      -1, dateFunc        },
dvander@1203
  1016
    { "time",      -1, timeFunc        },
dvander@1203
  1017
    { "datetime",  -1, datetimeFunc    },
dvander@1203
  1018
    { "strftime",  -1, strftimeFunc    },
dvander@1203
  1019
    { "current_time",       0, ctimeFunc      },
dvander@1203
  1020
    { "current_timestamp",  0, ctimestampFunc },
dvander@1203
  1021
    { "current_date",       0, cdateFunc      },
dvander@1203
  1022
  };
dvander@1203
  1023
  int i;
dvander@1203
  1024
dvander@1203
  1025
  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
dvander@1203
  1026
    sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
dvander@1645
  1027
        SQLITE_UTF8, (void *)(db->pVfs), aFuncs[i].xFunc, 0, 0);
dvander@1203
  1028
  }
dvander@1203
  1029
#else
dvander@1203
  1030
  static const struct {
dvander@1203
  1031
     char *zName;
dvander@1203
  1032
     char *zFormat;
dvander@1203
  1033
  } aFuncs[] = {
dvander@1203
  1034
    { "current_time", "%H:%M:%S" },
dvander@1203
  1035
    { "current_date", "%Y-%m-%d" },
dvander@1203
  1036
    { "current_timestamp", "%Y-%m-%d %H:%M:%S" }
dvander@1203
  1037
  };
dvander@1203
  1038
  int i;
dvander@1203
  1039
dvander@1203
  1040
  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
dvander@1203
  1041
    sqlite3CreateFunc(db, aFuncs[i].zName, 0, SQLITE_UTF8, 
dvander@1203
  1042
        aFuncs[i].zFormat, currentTimeFunc, 0, 0);
dvander@1203
  1043
  }
dvander@1203
  1044
#endif
dvander@1203
  1045
}