Fossil SCM

Accept pure numeric ISO8601 date/time strings (without punctuation) if there are not conflicts with other identifiers.

drh 2019-03-27 13:16 trunk
Commit 437f39b87c3340cb50b91cacfc6186fe037694013a85ad40c516a7f307490e22
2 files changed +83 -1 +7
+83 -1
--- src/name.c
+++ src/name.c
@@ -38,10 +38,77 @@
3838
if( z[7]!='-') return 0;
3939
if( !fossil_isdigit(z[8]) ) return 0;
4040
if( !fossil_isdigit(z[9]) ) return 0;
4141
return 1;
4242
}
43
+
44
+/*
45
+** Check to see if the string might be a compact date/time that omits
46
+** the punctuation. Example: "20190327084549" instead of
47
+** "2019-03-27 08:45:49". If the string is of the appropriate form,
48
+** then return an alternative string (in static space) that is the same
49
+** string with punctuation inserted.
50
+**
51
+** If the bVerifyNotAHash flag is true, then a check is made to see if
52
+** the string is a hash prefix and NULL is returned if it is. If the
53
+** bVerifyNotAHash flag is false, then the result is determined by syntax
54
+** of the input string only, without reference to the artifact table.
55
+*/
56
+char *fossil_expand_datetime(const char *zIn, int bVerifyNotAHash){
57
+ static char zEDate[20];
58
+ static const char aPunct[] = { 0, 0, '-', '-', ' ', ':', ':' };
59
+ int n = (int)strlen(zIn);
60
+ int i, j;
61
+
62
+ /* Only three forms allowed:
63
+ ** (1) YYYYMMDD
64
+ ** (2) YYYYMMDDHHMM
65
+ ** (3) YYYYMMDDHHMMSS
66
+ */
67
+ if( n!=8 && n!=12 && n!=14 ) return 0;
68
+
69
+ /* Every character must be a digit */
70
+ for(i=0; fossil_isdigit(zIn[i]); i++){}
71
+ if( i!=n ) return 0;
72
+
73
+ /* Expand the date */
74
+ for(i=j=0; zIn[i]; i++){
75
+ if( i>=4 && (i%2)==0 ){
76
+ zEDate[j++] = aPunct[i/2];
77
+ }
78
+ zEDate[j++] = zIn[i];
79
+ }
80
+ zEDate[j] = 0;
81
+
82
+ /* Check for reasonable date values.
83
+ ** Offset references:
84
+ ** YYYY-MM-DD HH:MM:SS
85
+ ** 0123456789 12345678
86
+ */
87
+
88
+ i = atoi(zEDate);
89
+ if( i<1970 || i>2100 ) return 0;
90
+ i = atoi(zEDate+5);
91
+ if( i<1 || i>12 ) return 0;
92
+ i = atoi(zEDate+8);
93
+ if( i<1 || i>31 ) return 0;
94
+ if( n>8 ){
95
+ i = atoi(zEDate+11);
96
+ if( i>24 ) return 0;
97
+ i = atoi(zEDate+14);
98
+ if( i>60 ) return 0;
99
+ if( n==14 && atoi(zEDate+17)>60 ) return 0;
100
+ }
101
+
102
+ /* The string is not also a hash prefix */
103
+ if( bVerifyNotAHash ){
104
+ if( db_exists("SELECT 1 FROM blob WHERE uuid GLOB '%q*'",zIn) ) return 0;
105
+ }
106
+
107
+ /* It looks like this may be a date. Return it with punctuation added. */
108
+ return zEDate;
109
+}
43110
44111
/*
45112
** Return the RID that is the "root" of the branch that contains
46113
** check-in "rid" if inBranch==0 or the first check-in in the branch
47114
** if inBranch==1.
@@ -114,10 +181,11 @@
114181
int nTag;
115182
int i;
116183
int startOfBranch = 0;
117184
const char *zXTag; /* zTag with optional [...] removed */
118185
int nXTag; /* Size of zXTag */
186
+ const char *zDate; /* Expanded date-time string */
119187
120188
if( zType==0 || zType[0]==0 ){
121189
zType = "*";
122190
}else if( zType[0]=='b' ){
123191
zType = "ci";
@@ -150,15 +218,17 @@
150218
if( rid ) return rid;
151219
}
152220
153221
/* Date and times */
154222
if( memcmp(zTag, "date:", 5)==0 ){
223
+ zDate = fossil_expand_datetime(&zTag[5],0);
224
+ if( zDate==0 ) zDate = &zTag[5];
155225
rid = db_int(0,
156226
"SELECT objid FROM event"
157227
" WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
158228
" ORDER BY mtime DESC LIMIT 1",
159
- &zTag[5], zType);
229
+ zDate, zType);
160230
return rid;
161231
}
162232
if( fossil_isdate(zTag) ){
163233
rid = db_int(0,
164234
"SELECT objid FROM event"
@@ -283,10 +353,22 @@
283353
);
284354
if( rid>0 ){
285355
if( startOfBranch ) rid = start_of_branch(rid,1);
286356
return rid;
287357
}
358
+
359
+ /* Pure numeric date/time */
360
+ zDate = fossil_expand_datetime(zTag, 0);
361
+ if( zDate ){
362
+ rid = db_int(0,
363
+ "SELECT objid FROM event"
364
+ " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
365
+ " ORDER BY mtime DESC LIMIT 1",
366
+ zDate, zType);
367
+ if( rid) return rid;
368
+ }
369
+
288370
289371
/* Undocumented: numeric tags get translated directly into the RID */
290372
if( memcmp(zTag, "rid:", 4)==0 ){
291373
zTag += 4;
292374
for(i=0; fossil_isdigit(zTag[i]); i++){}
293375
--- src/name.c
+++ src/name.c
@@ -38,10 +38,77 @@
38 if( z[7]!='-') return 0;
39 if( !fossil_isdigit(z[8]) ) return 0;
40 if( !fossil_isdigit(z[9]) ) return 0;
41 return 1;
42 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
44 /*
45 ** Return the RID that is the "root" of the branch that contains
46 ** check-in "rid" if inBranch==0 or the first check-in in the branch
47 ** if inBranch==1.
@@ -114,10 +181,11 @@
114 int nTag;
115 int i;
116 int startOfBranch = 0;
117 const char *zXTag; /* zTag with optional [...] removed */
118 int nXTag; /* Size of zXTag */
 
119
120 if( zType==0 || zType[0]==0 ){
121 zType = "*";
122 }else if( zType[0]=='b' ){
123 zType = "ci";
@@ -150,15 +218,17 @@
150 if( rid ) return rid;
151 }
152
153 /* Date and times */
154 if( memcmp(zTag, "date:", 5)==0 ){
 
 
155 rid = db_int(0,
156 "SELECT objid FROM event"
157 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
158 " ORDER BY mtime DESC LIMIT 1",
159 &zTag[5], zType);
160 return rid;
161 }
162 if( fossil_isdate(zTag) ){
163 rid = db_int(0,
164 "SELECT objid FROM event"
@@ -283,10 +353,22 @@
283 );
284 if( rid>0 ){
285 if( startOfBranch ) rid = start_of_branch(rid,1);
286 return rid;
287 }
 
 
 
 
 
 
 
 
 
 
 
 
288
289 /* Undocumented: numeric tags get translated directly into the RID */
290 if( memcmp(zTag, "rid:", 4)==0 ){
291 zTag += 4;
292 for(i=0; fossil_isdigit(zTag[i]); i++){}
293
--- src/name.c
+++ src/name.c
@@ -38,10 +38,77 @@
38 if( z[7]!='-') return 0;
39 if( !fossil_isdigit(z[8]) ) return 0;
40 if( !fossil_isdigit(z[9]) ) return 0;
41 return 1;
42 }
43
44 /*
45 ** Check to see if the string might be a compact date/time that omits
46 ** the punctuation. Example: "20190327084549" instead of
47 ** "2019-03-27 08:45:49". If the string is of the appropriate form,
48 ** then return an alternative string (in static space) that is the same
49 ** string with punctuation inserted.
50 **
51 ** If the bVerifyNotAHash flag is true, then a check is made to see if
52 ** the string is a hash prefix and NULL is returned if it is. If the
53 ** bVerifyNotAHash flag is false, then the result is determined by syntax
54 ** of the input string only, without reference to the artifact table.
55 */
56 char *fossil_expand_datetime(const char *zIn, int bVerifyNotAHash){
57 static char zEDate[20];
58 static const char aPunct[] = { 0, 0, '-', '-', ' ', ':', ':' };
59 int n = (int)strlen(zIn);
60 int i, j;
61
62 /* Only three forms allowed:
63 ** (1) YYYYMMDD
64 ** (2) YYYYMMDDHHMM
65 ** (3) YYYYMMDDHHMMSS
66 */
67 if( n!=8 && n!=12 && n!=14 ) return 0;
68
69 /* Every character must be a digit */
70 for(i=0; fossil_isdigit(zIn[i]); i++){}
71 if( i!=n ) return 0;
72
73 /* Expand the date */
74 for(i=j=0; zIn[i]; i++){
75 if( i>=4 && (i%2)==0 ){
76 zEDate[j++] = aPunct[i/2];
77 }
78 zEDate[j++] = zIn[i];
79 }
80 zEDate[j] = 0;
81
82 /* Check for reasonable date values.
83 ** Offset references:
84 ** YYYY-MM-DD HH:MM:SS
85 ** 0123456789 12345678
86 */
87
88 i = atoi(zEDate);
89 if( i<1970 || i>2100 ) return 0;
90 i = atoi(zEDate+5);
91 if( i<1 || i>12 ) return 0;
92 i = atoi(zEDate+8);
93 if( i<1 || i>31 ) return 0;
94 if( n>8 ){
95 i = atoi(zEDate+11);
96 if( i>24 ) return 0;
97 i = atoi(zEDate+14);
98 if( i>60 ) return 0;
99 if( n==14 && atoi(zEDate+17)>60 ) return 0;
100 }
101
102 /* The string is not also a hash prefix */
103 if( bVerifyNotAHash ){
104 if( db_exists("SELECT 1 FROM blob WHERE uuid GLOB '%q*'",zIn) ) return 0;
105 }
106
107 /* It looks like this may be a date. Return it with punctuation added. */
108 return zEDate;
109 }
110
111 /*
112 ** Return the RID that is the "root" of the branch that contains
113 ** check-in "rid" if inBranch==0 or the first check-in in the branch
114 ** if inBranch==1.
@@ -114,10 +181,11 @@
181 int nTag;
182 int i;
183 int startOfBranch = 0;
184 const char *zXTag; /* zTag with optional [...] removed */
185 int nXTag; /* Size of zXTag */
186 const char *zDate; /* Expanded date-time string */
187
188 if( zType==0 || zType[0]==0 ){
189 zType = "*";
190 }else if( zType[0]=='b' ){
191 zType = "ci";
@@ -150,15 +218,17 @@
218 if( rid ) return rid;
219 }
220
221 /* Date and times */
222 if( memcmp(zTag, "date:", 5)==0 ){
223 zDate = fossil_expand_datetime(&zTag[5],0);
224 if( zDate==0 ) zDate = &zTag[5];
225 rid = db_int(0,
226 "SELECT objid FROM event"
227 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
228 " ORDER BY mtime DESC LIMIT 1",
229 zDate, zType);
230 return rid;
231 }
232 if( fossil_isdate(zTag) ){
233 rid = db_int(0,
234 "SELECT objid FROM event"
@@ -283,10 +353,22 @@
353 );
354 if( rid>0 ){
355 if( startOfBranch ) rid = start_of_branch(rid,1);
356 return rid;
357 }
358
359 /* Pure numeric date/time */
360 zDate = fossil_expand_datetime(zTag, 0);
361 if( zDate ){
362 rid = db_int(0,
363 "SELECT objid FROM event"
364 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
365 " ORDER BY mtime DESC LIMIT 1",
366 zDate, zType);
367 if( rid) return rid;
368 }
369
370
371 /* Undocumented: numeric tags get translated directly into the RID */
372 if( memcmp(zTag, "rid:", 4)==0 ){
373 zTag += 4;
374 for(i=0; fossil_isdigit(zTag[i]); i++){}
375
--- src/timeline.c
+++ src/timeline.c
@@ -1027,14 +1027,21 @@
10271027
** query parameters of timeline into a julianday mtime value.
10281028
*/
10291029
double symbolic_name_to_mtime(const char *z){
10301030
double mtime;
10311031
int rid;
1032
+ const char *zDate;
10321033
if( z==0 ) return -1.0;
10331034
if( fossil_isdate(z) ){
10341035
mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())", z);
10351036
if( mtime>0.0 ) return mtime;
1037
+ }
1038
+ zDate = fossil_expand_datetime(z, 1);
1039
+ if( zDate!=0
1040
+ && (mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())", zDate))>0.0
1041
+ ){
1042
+ return mtime;
10361043
}
10371044
rid = symbolic_name_to_rid(z, "*");
10381045
if( rid ){
10391046
mtime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
10401047
}else{
10411048
--- src/timeline.c
+++ src/timeline.c
@@ -1027,14 +1027,21 @@
1027 ** query parameters of timeline into a julianday mtime value.
1028 */
1029 double symbolic_name_to_mtime(const char *z){
1030 double mtime;
1031 int rid;
 
1032 if( z==0 ) return -1.0;
1033 if( fossil_isdate(z) ){
1034 mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())", z);
1035 if( mtime>0.0 ) return mtime;
 
 
 
 
 
 
1036 }
1037 rid = symbolic_name_to_rid(z, "*");
1038 if( rid ){
1039 mtime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
1040 }else{
1041
--- src/timeline.c
+++ src/timeline.c
@@ -1027,14 +1027,21 @@
1027 ** query parameters of timeline into a julianday mtime value.
1028 */
1029 double symbolic_name_to_mtime(const char *z){
1030 double mtime;
1031 int rid;
1032 const char *zDate;
1033 if( z==0 ) return -1.0;
1034 if( fossil_isdate(z) ){
1035 mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())", z);
1036 if( mtime>0.0 ) return mtime;
1037 }
1038 zDate = fossil_expand_datetime(z, 1);
1039 if( zDate!=0
1040 && (mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())", zDate))>0.0
1041 ){
1042 return mtime;
1043 }
1044 rid = symbolic_name_to_rid(z, "*");
1045 if( rid ){
1046 mtime = db_double(0.0, "SELECT mtime FROM event WHERE objid=%d", rid);
1047 }else{
1048

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button