📄 date.c
字号:
*/ if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0 && (n=r)==r && n>=0 && r<7 ){ int Z; computeYMD_HMS(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; clearYMD_HMS_TZ(p); rc = 0; } break; } case 's': { /* ** start of TTTTT ** ** Move the date backwards to the beginning of the current day, ** or month or year. */ if( strncmp(z, "start of ", 9)!=0 ) break; z += 9; computeYMD(p); p->validHMS = 1; p->h = p->m = 0; p->s = 0.0; p->validTZ = 0; p->validJD = 0; if( strcmp(z,"month")==0 ){ p->D = 1; rc = 0; }else if( strcmp(z,"year")==0 ){ computeYMD(p); p->M = 1; p->D = 1; rc = 0; }else if( strcmp(z,"day")==0 ){ rc = 0; } break; } case '+': case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { n = getValue(z, &r); assert( n>=1 ); if( z[n]==':' ){ /* A modifier of the form (+|-)HH:MM:SS.FFF adds (or subtracts) the ** specified number of hours, minutes, seconds, and fractional seconds ** to the time. The ".FFF" may be omitted. The ":SS.FFF" may be ** omitted. */ const char *z2 = z; DateTime tx; int day; if( !isdigit(*(u8*)z2) ) z2++; memset(&tx, 0, sizeof(tx)); if( parseHhMmSs(z2, &tx) ) break; computeJD(&tx); tx.rJD -= 0.5; day = (int)tx.rJD; tx.rJD -= day; if( z[0]=='-' ) tx.rJD = -tx.rJD; computeJD(p); clearYMD_HMS_TZ(p); p->rJD += tx.rJD; rc = 0; break; } z += n; while( isspace(*(u8*)z) ) z++; n = strlen(z); if( n>10 || n<3 ) break; if( z[n-1]=='s' ){ z[n-1] = 0; n--; } computeJD(p); rc = 0; if( n==3 && strcmp(z,"day")==0 ){ p->rJD += r; }else if( n==4 && strcmp(z,"hour")==0 ){ p->rJD += r/24.0; }else if( n==6 && strcmp(z,"minute")==0 ){ p->rJD += r/(24.0*60.0); }else if( n==6 && strcmp(z,"second")==0 ){ p->rJD += r/(24.0*60.0*60.0); }else if( n==5 && strcmp(z,"month")==0 ){ int x, y; computeYMD_HMS(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_HMS(p); p->Y += r; p->validJD = 0; computeJD(p); }else{ rc = 1; } clearYMD_HMS_TZ(p); break; } default: { break; } } return rc;}/*** Process time function arguments. argv[0] is a date-time stamp.** argv[1] and following are modifiers. Parse them all and write** the resulting time into the DateTime structure p. Return 0** on success and 1 if there are any errors.*/static int isDate(int argc, sqlite3_value **argv, DateTime *p){ int i; const unsigned char *z; if( argc==0 ) return 1; if( (z = sqlite3_value_text(argv[0]))==0 || parseDateOrTime((char*)z, p) ){ return 1; } for(i=1; i<argc; i++){ if( (z = sqlite3_value_text(argv[i]))==0 || parseModifier((char*)z, p) ){ return 1; } } return 0;}/*** The following routines implement the various date and time functions** of SQLite.*//*** julianday( TIMESTRING, MOD, MOD, ...)**** Return the julian day number of the date specified in the arguments*/static void juliandayFunc( sqlite3_context *context, int argc, sqlite3_value **argv){ DateTime x; if( isDate(argc, argv, &x)==0 ){ computeJD(&x); sqlite3_result_double(context, x.rJD); }}/*** datetime( TIMESTRING, MOD, MOD, ...)**** Return YYYY-MM-DD HH:MM:SS*/static void datetimeFunc( sqlite3_context *context, int argc, sqlite3_value **argv){ DateTime x; if( isDate(argc, argv, &x)==0 ){ char zBuf[100]; computeYMD_HMS(&x); sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d %02d:%02d:%02d", x.Y, x.M, x.D, x.h, x.m, (int)(x.s)); sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); }}/*** time( TIMESTRING, MOD, MOD, ...)**** Return HH:MM:SS*/static void timeFunc( sqlite3_context *context, int argc, sqlite3_value **argv){ DateTime x; if( isDate(argc, argv, &x)==0 ){ char zBuf[100]; computeHMS(&x); sqlite3_snprintf(sizeof(zBuf), zBuf, "%02d:%02d:%02d", x.h, x.m, (int)x.s); sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); }}/*** date( TIMESTRING, MOD, MOD, ...)**** Return YYYY-MM-DD*/static void dateFunc( sqlite3_context *context, int argc, sqlite3_value **argv){ DateTime x; if( isDate(argc, argv, &x)==0 ){ char zBuf[100]; computeYMD(&x); sqlite3_snprintf(sizeof(zBuf), zBuf, "%04d-%02d-%02d", x.Y, x.M, x.D); sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT); }}/*** strftime( FORMAT, TIMESTRING, MOD, MOD, ...)**** Return a string described by FORMAT. Conversions as follows:**** %d day of month** %f ** fractional seconds SS.SSS** %H hour 00-24** %j day of year 000-366** %J ** Julian day number** %m month 01-12** %M minute 00-59** %s seconds since 1970-01-01** %S seconds 00-59** %w day of week 0-6 sunday==0** %W week of year 00-53** %Y year 0000-9999** %% %*/static void strftimeFunc( sqlite3_context *context, int argc, sqlite3_value **argv){ DateTime x; u64 n; int i, j; char *z; const char *zFmt = (const char*)sqlite3_value_text(argv[0]); char zBuf[100]; if( zFmt==0 || isDate(argc-1, argv+1, &x) ) return; for(i=0, n=1; zFmt[i]; i++, n++){ if( zFmt[i]=='%' ){ switch( zFmt[i+1] ){ case 'd': case 'H': case 'm': case 'M': case 'S': case 'W': n++; /* fall thru */ case 'w': case '%': break; case 'f': n += 8; break; case 'j': n += 3; break; case 'Y': n += 8; break; case 's': case 'J': n += 50; break; default: return; /* ERROR. return a NULL */ } i++; } } if( n<sizeof(zBuf) ){ z = zBuf; }else if( n>SQLITE_MAX_LENGTH ){ sqlite3_result_error_toobig(context); return; }else{ z = sqliteMalloc( n ); if( z==0 ) return; } computeJD(&x); computeYMD_HMS(&x); for(i=j=0; zFmt[i]; i++){ if( zFmt[i]!='%' ){ z[j++] = zFmt[i]; }else{ i++; switch( zFmt[i] ){ case 'd': sqlite3_snprintf(3, &z[j],"%02d",x.D); j+=2; break; case 'f': { double s = x.s; if( s>59.999 ) s = 59.999; sqlite3_snprintf(7, &z[j],"%06.3f", s); j += strlen(&z[j]); break; } case 'H': sqlite3_snprintf(3, &z[j],"%02d",x.h); j+=2; break; case 'W': /* Fall thru */ case 'j': { int nDay; /* Number of days since 1st day of year */ DateTime y = x; y.validJD = 0; y.M = 1; y.D = 1; computeJD(&y); nDay = x.rJD - y.rJD + 0.5; if( zFmt[i]=='W' ){ int wd; /* 0=Monday, 1=Tuesday, ... 6=Sunday */ wd = ((int)(x.rJD+0.5)) % 7; sqlite3_snprintf(3, &z[j],"%02d",(nDay+7-wd)/7); j += 2; }else{ sqlite3_snprintf(4, &z[j],"%03d",nDay+1); j += 3; } break; } case 'J': { sqlite3_snprintf(20, &z[j],"%.16g",x.rJD); j+=strlen(&z[j]); break; } case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break; case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break; case 's': { sqlite3_snprintf(30,&z[j],"%d", (int)((x.rJD-2440587.5)*86400.0 + 0.5)); j += strlen(&z[j]); break; } case 'S': sqlite3_snprintf(3,&z[j],"%02d",(int)x.s); j+=2; break; case 'w': z[j++] = (((int)(x.rJD+1.5)) % 7) + '0'; break; case 'Y': sqlite3_snprintf(5,&z[j],"%04d",x.Y); j+=strlen(&z[j]);break; case '%': z[j++] = '%'; break; } } } z[j] = 0; sqlite3_result_text(context, z, -1, SQLITE_TRANSIENT); if( z!=zBuf ){ sqliteFree(z); }}/*** current_time()**** This function returns the same value as time('now').*/static void ctimeFunc( sqlite3_context *context, int argc, sqlite3_value **argv){ sqlite3_value *pVal = sqlite3ValueNew(); if( pVal ){ sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC); timeFunc(context, 1, &pVal); sqlite3ValueFree(pVal); }}/*** current_date()**** This function returns the same value as date('now').*/static void cdateFunc( sqlite3_context *context, int argc, sqlite3_value **argv){ sqlite3_value *pVal = sqlite3ValueNew(); if( pVal ){ sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC); dateFunc(context, 1, &pVal); sqlite3ValueFree(pVal); }}/*** current_timestamp()**** This function returns the same value as datetime('now').*/static void ctimestampFunc( sqlite3_context *context, int argc, sqlite3_value **argv){ sqlite3_value *pVal = sqlite3ValueNew(); if( pVal ){ sqlite3ValueSetStr(pVal, -1, "now", SQLITE_UTF8, SQLITE_STATIC); datetimeFunc(context, 1, &pVal); sqlite3ValueFree(pVal); }}#endif /* !defined(SQLITE_OMIT_DATETIME_FUNCS) */#ifdef SQLITE_OMIT_DATETIME_FUNCS/*** If the library is compiled to omit the full-scale date and time** handling (to get a smaller binary), the following minimal version** of the functions current_time(), current_date() and current_timestamp()** are included instead. This is to support column declarations that** include "DEFAULT CURRENT_TIME" etc.**** This function uses the C-library functions time(), gmtime()** and strftime(). The format string to pass to strftime() is supplied** as the user-data for the function.*/static void currentTimeFunc( sqlite3_context *context, int argc, sqlite3_value **argv){ time_t t; char *zFormat = (char *)sqlite3_user_data(context); char zBuf[20]; time(&t);#ifdef SQLITE_TEST { extern int sqlite3_current_time; /* See os_XXX.c */ if( sqlite3_current_time ){ t = sqlite3_current_time; } }#endif#ifdef HAVE_GMTIME_R { struct tm sNow; gmtime_r(&t, &sNow); strftime(zBuf, 20, zFormat, &sNow); }#else { struct tm *pTm; sqlite3OsEnterMutex(); pTm = gmtime(&t); strftime(zBuf, 20, zFormat, pTm); sqlite3OsLeaveMutex(); }#endif sqlite3_result_text(context, zBuf, -1, SQLITE_TRANSIENT);}#endif/*** This function registered all of the above C functions as SQL** functions. This should be the only routine in this file with** external linkage.*/void sqlite3RegisterDateTimeFunctions(sqlite3 *db){#ifndef SQLITE_OMIT_DATETIME_FUNCS static const struct { char *zName; int nArg; void (*xFunc)(sqlite3_context*,int,sqlite3_value**); } aFuncs[] = { { "julianday", -1, juliandayFunc }, { "date", -1, dateFunc }, { "time", -1, timeFunc }, { "datetime", -1, datetimeFunc }, { "strftime", -1, strftimeFunc }, { "current_time", 0, ctimeFunc }, { "current_timestamp", 0, ctimestampFunc }, { "current_date", 0, cdateFunc }, }; int i; for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg, SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0); }#else static const struct { char *zName; char *zFormat; } aFuncs[] = { { "current_time", "%H:%M:%S" }, { "current_date", "%Y-%m-%d" }, { "current_timestamp", "%Y-%m-%d %H:%M:%S" } }; int i; for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){ sqlite3CreateFunc(db, aFuncs[i].zName, 0, SQLITE_UTF8, aFuncs[i].zFormat, currentTimeFunc, 0, 0); }#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -