Fossil SCM

Improved rounding behavior for timestamp identifiers on object where the timestamp has less then millisecond precision.

drh 2025-03-18 11:04 trunk
Commit 633ea7343f68c90745f7a6f2a44da3253bc4b1f83c4b985b2ca7d22aaf4f35ba
+2 -2
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -127,16 +127,16 @@
127127
DIFF_HTML|DIFF_WEBPAGE|DIFF_BROWSER|DIFF_JSON|DIFF_TCL))==0 ){
128128
fossil_print("Fossil-Diff-From: %s\n",
129129
zFrom[0]=='(' ? zFrom : mprintf("%S %s",
130130
rid_to_uuid(symbolic_name_to_rid(zFrom, "ci")),
131131
db_text("","SELECT datetime(%f)||' UTC'",
132
- symbolic_name_to_mtime(zFrom, 0))));
132
+ symbolic_name_to_mtime(zFrom, 0, 0))));
133133
fossil_print("Fossil-Diff-To: %s\n",
134134
zTo[0]=='(' ? zTo : mprintf("%S %s",
135135
rid_to_uuid(symbolic_name_to_rid(zTo, "ci")),
136136
db_text("","SELECT datetime(%f)||' UTC'",
137
- symbolic_name_to_mtime(zTo, 0))));
137
+ symbolic_name_to_mtime(zTo, 0, 1))));
138138
fossil_print("%.66c\n", '-');
139139
}
140140
}
141141
142142
/*
143143
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -127,16 +127,16 @@
127 DIFF_HTML|DIFF_WEBPAGE|DIFF_BROWSER|DIFF_JSON|DIFF_TCL))==0 ){
128 fossil_print("Fossil-Diff-From: %s\n",
129 zFrom[0]=='(' ? zFrom : mprintf("%S %s",
130 rid_to_uuid(symbolic_name_to_rid(zFrom, "ci")),
131 db_text("","SELECT datetime(%f)||' UTC'",
132 symbolic_name_to_mtime(zFrom, 0))));
133 fossil_print("Fossil-Diff-To: %s\n",
134 zTo[0]=='(' ? zTo : mprintf("%S %s",
135 rid_to_uuid(symbolic_name_to_rid(zTo, "ci")),
136 db_text("","SELECT datetime(%f)||' UTC'",
137 symbolic_name_to_mtime(zTo, 0))));
138 fossil_print("%.66c\n", '-');
139 }
140 }
141
142 /*
143
--- src/diffcmd.c
+++ src/diffcmd.c
@@ -127,16 +127,16 @@
127 DIFF_HTML|DIFF_WEBPAGE|DIFF_BROWSER|DIFF_JSON|DIFF_TCL))==0 ){
128 fossil_print("Fossil-Diff-From: %s\n",
129 zFrom[0]=='(' ? zFrom : mprintf("%S %s",
130 rid_to_uuid(symbolic_name_to_rid(zFrom, "ci")),
131 db_text("","SELECT datetime(%f)||' UTC'",
132 symbolic_name_to_mtime(zFrom, 0, 0))));
133 fossil_print("Fossil-Diff-To: %s\n",
134 zTo[0]=='(' ? zTo : mprintf("%S %s",
135 rid_to_uuid(symbolic_name_to_rid(zTo, "ci")),
136 db_text("","SELECT datetime(%f)||' UTC'",
137 symbolic_name_to_mtime(zTo, 0, 1))));
138 fossil_print("%.66c\n", '-');
139 }
140 }
141
142 /*
143
+2 -2
--- src/finfo.c
+++ src/finfo.c
@@ -498,16 +498,16 @@
498498
" AND event.objid=mlink.mid\n",
499499
TAG_BRANCH
500500
);
501501
if( (zA = P("a"))!=0 ){
502502
blob_append_sql(&sql, " AND event.mtime>=%.16g\n",
503
- symbolic_name_to_mtime(zA,0));
503
+ symbolic_name_to_mtime(zA,0,0));
504504
url_add_parameter(&url, "a", zA);
505505
}
506506
if( (zB = P("b"))!=0 ){
507507
blob_append_sql(&sql, " AND event.mtime<=%.16g\n",
508
- symbolic_name_to_mtime(zB,0));
508
+ symbolic_name_to_mtime(zB,0,1));
509509
url_add_parameter(&url, "b", zB);
510510
}
511511
if( ridFrom ){
512512
blob_append_sql(&sql,
513513
" AND mlink.mid IN (SELECT rid FROM ancestor)\n"
514514
--- src/finfo.c
+++ src/finfo.c
@@ -498,16 +498,16 @@
498 " AND event.objid=mlink.mid\n",
499 TAG_BRANCH
500 );
501 if( (zA = P("a"))!=0 ){
502 blob_append_sql(&sql, " AND event.mtime>=%.16g\n",
503 symbolic_name_to_mtime(zA,0));
504 url_add_parameter(&url, "a", zA);
505 }
506 if( (zB = P("b"))!=0 ){
507 blob_append_sql(&sql, " AND event.mtime<=%.16g\n",
508 symbolic_name_to_mtime(zB,0));
509 url_add_parameter(&url, "b", zB);
510 }
511 if( ridFrom ){
512 blob_append_sql(&sql,
513 " AND mlink.mid IN (SELECT rid FROM ancestor)\n"
514
--- src/finfo.c
+++ src/finfo.c
@@ -498,16 +498,16 @@
498 " AND event.objid=mlink.mid\n",
499 TAG_BRANCH
500 );
501 if( (zA = P("a"))!=0 ){
502 blob_append_sql(&sql, " AND event.mtime>=%.16g\n",
503 symbolic_name_to_mtime(zA,0,0));
504 url_add_parameter(&url, "a", zA);
505 }
506 if( (zB = P("b"))!=0 ){
507 blob_append_sql(&sql, " AND event.mtime<=%.16g\n",
508 symbolic_name_to_mtime(zB,0,1));
509 url_add_parameter(&url, "b", zB);
510 }
511 if( ridFrom ){
512 blob_append_sql(&sql,
513 " AND mlink.mid IN (SELECT rid FROM ancestor)\n"
514
+32 -20
--- src/name.c
+++ src/name.c
@@ -59,34 +59,41 @@
5959
** the punctuation. Example: "20190327084549" instead of
6060
** "2019-03-27 08:45:49". If the string is of the appropriate form,
6161
** then return an alternative string (in static space) that is the same
6262
** string with punctuation inserted.
6363
**
64
-** Assume the maximum allowed value for unspecified digits. In other
65
-** words: 202503171234 -> 2025-03-17 12:34:59
66
-** ^^--- Added seconds.
67
-** and: 20250317 -> 2025-03-17 23:59:59
68
-** ^^^^^^^^--- Added time.
64
+** If the bRoundUp parameter is true, then round the resulting date-time
65
+** up to the largest date/time that is consistent with the input value.
66
+** This is because the result will be used for an mtime<=julianday($DATE)
67
+** comparison. In other words:
68
+**
69
+** 20250317123421 -> 2025-03-17 12:34:21.999
70
+** ^^^^--- Added
71
+**
72
+** 202503171234 -> 2025-03-17 12:34:59.999
73
+** ^^^^^^^--- Added
74
+** 20250317 -> 2025-03-17 23:59:59.999
75
+** ^^^^^^^^^^^^--- Added
6976
**
7077
** If the bVerifyNotAHash flag is true, then a check is made to see if
7178
** the input string is a hash prefix and NULL is returned if it is. If the
7279
** bVerifyNotAHash flag is false, then the result is determined by syntax
7380
** of the input string only, without reference to the artifact table.
7481
*/
75
-char *fossil_expand_datetime(const char *zIn, int bVerifyNotAHash){
82
+char *fossil_expand_datetime(const char *zIn,int bVerifyNotAHash,int bRoundUp){
7683
static char zEDate[24];
7784
static const char aPunct[] = { 0, 0, '-', '-', ' ', ':', ':' };
7885
int n = (int)strlen(zIn);
7986
int i, j;
8087
int addZulu = 0;
8188
8289
/* These forms are allowed:
8390
**
84
- ** 123456789 1234 123456789 123456789
85
- ** (1) YYYYMMDD => YYYY-MM-DD 23:59:59
86
- ** (2) YYYYMMDDHHMM => YYYY-MM-DD HH:MM:59
87
- ** (3) YYYYMMDDHHMMSS => YYYY-MM-DD HH:MM:SS
91
+ ** 123456789 1234 123456789 123456789 1234
92
+ ** (1) YYYYMMDD => YYYY-MM-DD 23:59:59.999
93
+ ** (2) YYYYMMDDHHMM => YYYY-MM-DD HH:MM:59.999
94
+ ** (3) YYYYMMDDHHMMSS => YYYY-MM-DD HH:MM:SS.999
8895
**
8996
** An optional "Z" zulu timezone designator is allowed at the end.
9097
*/
9198
if( n>0 && (zIn[n-1]=='Z' || zIn[n-1]=='z') ){
9299
n--;
@@ -105,16 +112,21 @@
105112
if( i>=4 && (i%2)==0 ){
106113
zEDate[j++] = aPunct[i/2];
107114
}
108115
zEDate[j++] = zIn[i];
109116
}
110
- if( j==10 ){
111
- memcpy(&zEDate[10], " 23:59:59", 9);
112
- j += 9;
113
- }else if( j==16 ){
114
- memcpy(&zEDate[16], ":59",3);
115
- j += 3;
117
+ if( bRoundUp ){
118
+ if( j==10 ){
119
+ memcpy(&zEDate[10], " 23:59:59.999", 13);
120
+ j += 13;
121
+ }else if( j==16 ){
122
+ memcpy(&zEDate[16], ":59.999",7);
123
+ j += 7;
124
+ }else if( j==19 ){
125
+ memcpy(&zEDate[19], ".999", 4);
126
+ j += 4;
127
+ }
116128
}
117129
if( addZulu ){
118130
zEDate[j++] = 'Z';
119131
}
120132
zEDate[j] = 0;
@@ -488,11 +500,11 @@
488500
if( rid ) return rid;
489501
}
490502
491503
/* Date and times */
492504
if( memcmp(zTag, "date:", 5)==0 ){
493
- zDate = fossil_expand_datetime(&zTag[5],0);
505
+ zDate = fossil_expand_datetime(&zTag[5],0,1);
494506
if( zDate==0 ) zDate = &zTag[5];
495507
rid = db_int(0,
496508
"SELECT objid FROM event"
497509
" WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
498510
" ORDER BY mtime DESC LIMIT 1",
@@ -554,21 +566,21 @@
554566
555567
/* symbolic-name ":" date-time */
556568
nTag = strlen(zTag);
557569
for(i=0; i<nTag-8 && zTag[i]!=':'; i++){}
558570
if( zTag[i]==':'
559
- && (fossil_isdate(&zTag[i+1]) || fossil_expand_datetime(&zTag[i+1],0)!=0)
571
+ && (fossil_isdate(&zTag[i+1]) || fossil_expand_datetime(&zTag[i+1],0,0)!=0)
560572
){
561573
char *zDate = mprintf("%s", &zTag[i+1]);
562574
char *zTagBase = mprintf("%.*s", i, zTag);
563575
char *zXDate;
564576
int nDate = strlen(zDate);
565577
if( sqlite3_strnicmp(&zDate[nDate-3],"utc",3)==0 ){
566578
zDate[nDate-3] = 'z';
567579
zDate[nDate-2] = 0;
568580
}
569
- zXDate = fossil_expand_datetime(zDate,0);
581
+ zXDate = fossil_expand_datetime(zDate,0,1);
570582
if( zXDate==0 ) zXDate = zDate;
571583
rid = db_int(0,
572584
"SELECT event.objid, max(event.mtime)"
573585
" FROM tag, tagxref, event"
574586
" WHERE tag.tagname='sym-%q' "
@@ -640,11 +652,11 @@
640652
if( startOfBranch ) rid = start_of_branch(rid,1);
641653
return rid;
642654
}
643655
644656
/* Pure numeric date/time */
645
- zDate = fossil_expand_datetime(zTag, 0);
657
+ zDate = fossil_expand_datetime(zTag, 0,1);
646658
if( zDate ){
647659
rid = db_int(0,
648660
"SELECT objid FROM event"
649661
" WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
650662
" ORDER BY mtime DESC LIMIT 1",
651663
--- src/name.c
+++ src/name.c
@@ -59,34 +59,41 @@
59 ** the punctuation. Example: "20190327084549" instead of
60 ** "2019-03-27 08:45:49". If the string is of the appropriate form,
61 ** then return an alternative string (in static space) that is the same
62 ** string with punctuation inserted.
63 **
64 ** Assume the maximum allowed value for unspecified digits. In other
65 ** words: 202503171234 -> 2025-03-17 12:34:59
66 ** ^^--- Added seconds.
67 ** and: 20250317 -> 2025-03-17 23:59:59
68 ** ^^^^^^^^--- Added time.
 
 
 
 
 
 
 
69 **
70 ** If the bVerifyNotAHash flag is true, then a check is made to see if
71 ** the input string is a hash prefix and NULL is returned if it is. If the
72 ** bVerifyNotAHash flag is false, then the result is determined by syntax
73 ** of the input string only, without reference to the artifact table.
74 */
75 char *fossil_expand_datetime(const char *zIn, int bVerifyNotAHash){
76 static char zEDate[24];
77 static const char aPunct[] = { 0, 0, '-', '-', ' ', ':', ':' };
78 int n = (int)strlen(zIn);
79 int i, j;
80 int addZulu = 0;
81
82 /* These forms are allowed:
83 **
84 ** 123456789 1234 123456789 123456789
85 ** (1) YYYYMMDD => YYYY-MM-DD 23:59:59
86 ** (2) YYYYMMDDHHMM => YYYY-MM-DD HH:MM:59
87 ** (3) YYYYMMDDHHMMSS => YYYY-MM-DD HH:MM:SS
88 **
89 ** An optional "Z" zulu timezone designator is allowed at the end.
90 */
91 if( n>0 && (zIn[n-1]=='Z' || zIn[n-1]=='z') ){
92 n--;
@@ -105,16 +112,21 @@
105 if( i>=4 && (i%2)==0 ){
106 zEDate[j++] = aPunct[i/2];
107 }
108 zEDate[j++] = zIn[i];
109 }
110 if( j==10 ){
111 memcpy(&zEDate[10], " 23:59:59", 9);
112 j += 9;
113 }else if( j==16 ){
114 memcpy(&zEDate[16], ":59",3);
115 j += 3;
 
 
 
 
 
116 }
117 if( addZulu ){
118 zEDate[j++] = 'Z';
119 }
120 zEDate[j] = 0;
@@ -488,11 +500,11 @@
488 if( rid ) return rid;
489 }
490
491 /* Date and times */
492 if( memcmp(zTag, "date:", 5)==0 ){
493 zDate = fossil_expand_datetime(&zTag[5],0);
494 if( zDate==0 ) zDate = &zTag[5];
495 rid = db_int(0,
496 "SELECT objid FROM event"
497 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
498 " ORDER BY mtime DESC LIMIT 1",
@@ -554,21 +566,21 @@
554
555 /* symbolic-name ":" date-time */
556 nTag = strlen(zTag);
557 for(i=0; i<nTag-8 && zTag[i]!=':'; i++){}
558 if( zTag[i]==':'
559 && (fossil_isdate(&zTag[i+1]) || fossil_expand_datetime(&zTag[i+1],0)!=0)
560 ){
561 char *zDate = mprintf("%s", &zTag[i+1]);
562 char *zTagBase = mprintf("%.*s", i, zTag);
563 char *zXDate;
564 int nDate = strlen(zDate);
565 if( sqlite3_strnicmp(&zDate[nDate-3],"utc",3)==0 ){
566 zDate[nDate-3] = 'z';
567 zDate[nDate-2] = 0;
568 }
569 zXDate = fossil_expand_datetime(zDate,0);
570 if( zXDate==0 ) zXDate = zDate;
571 rid = db_int(0,
572 "SELECT event.objid, max(event.mtime)"
573 " FROM tag, tagxref, event"
574 " WHERE tag.tagname='sym-%q' "
@@ -640,11 +652,11 @@
640 if( startOfBranch ) rid = start_of_branch(rid,1);
641 return rid;
642 }
643
644 /* Pure numeric date/time */
645 zDate = fossil_expand_datetime(zTag, 0);
646 if( zDate ){
647 rid = db_int(0,
648 "SELECT objid FROM event"
649 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
650 " ORDER BY mtime DESC LIMIT 1",
651
--- src/name.c
+++ src/name.c
@@ -59,34 +59,41 @@
59 ** the punctuation. Example: "20190327084549" instead of
60 ** "2019-03-27 08:45:49". If the string is of the appropriate form,
61 ** then return an alternative string (in static space) that is the same
62 ** string with punctuation inserted.
63 **
64 ** If the bRoundUp parameter is true, then round the resulting date-time
65 ** up to the largest date/time that is consistent with the input value.
66 ** This is because the result will be used for an mtime<=julianday($DATE)
67 ** comparison. In other words:
68 **
69 ** 20250317123421 -> 2025-03-17 12:34:21.999
70 ** ^^^^--- Added
71 **
72 ** 202503171234 -> 2025-03-17 12:34:59.999
73 ** ^^^^^^^--- Added
74 ** 20250317 -> 2025-03-17 23:59:59.999
75 ** ^^^^^^^^^^^^--- Added
76 **
77 ** If the bVerifyNotAHash flag is true, then a check is made to see if
78 ** the input string is a hash prefix and NULL is returned if it is. If the
79 ** bVerifyNotAHash flag is false, then the result is determined by syntax
80 ** of the input string only, without reference to the artifact table.
81 */
82 char *fossil_expand_datetime(const char *zIn,int bVerifyNotAHash,int bRoundUp){
83 static char zEDate[24];
84 static const char aPunct[] = { 0, 0, '-', '-', ' ', ':', ':' };
85 int n = (int)strlen(zIn);
86 int i, j;
87 int addZulu = 0;
88
89 /* These forms are allowed:
90 **
91 ** 123456789 1234 123456789 123456789 1234
92 ** (1) YYYYMMDD => YYYY-MM-DD 23:59:59.999
93 ** (2) YYYYMMDDHHMM => YYYY-MM-DD HH:MM:59.999
94 ** (3) YYYYMMDDHHMMSS => YYYY-MM-DD HH:MM:SS.999
95 **
96 ** An optional "Z" zulu timezone designator is allowed at the end.
97 */
98 if( n>0 && (zIn[n-1]=='Z' || zIn[n-1]=='z') ){
99 n--;
@@ -105,16 +112,21 @@
112 if( i>=4 && (i%2)==0 ){
113 zEDate[j++] = aPunct[i/2];
114 }
115 zEDate[j++] = zIn[i];
116 }
117 if( bRoundUp ){
118 if( j==10 ){
119 memcpy(&zEDate[10], " 23:59:59.999", 13);
120 j += 13;
121 }else if( j==16 ){
122 memcpy(&zEDate[16], ":59.999",7);
123 j += 7;
124 }else if( j==19 ){
125 memcpy(&zEDate[19], ".999", 4);
126 j += 4;
127 }
128 }
129 if( addZulu ){
130 zEDate[j++] = 'Z';
131 }
132 zEDate[j] = 0;
@@ -488,11 +500,11 @@
500 if( rid ) return rid;
501 }
502
503 /* Date and times */
504 if( memcmp(zTag, "date:", 5)==0 ){
505 zDate = fossil_expand_datetime(&zTag[5],0,1);
506 if( zDate==0 ) zDate = &zTag[5];
507 rid = db_int(0,
508 "SELECT objid FROM event"
509 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
510 " ORDER BY mtime DESC LIMIT 1",
@@ -554,21 +566,21 @@
566
567 /* symbolic-name ":" date-time */
568 nTag = strlen(zTag);
569 for(i=0; i<nTag-8 && zTag[i]!=':'; i++){}
570 if( zTag[i]==':'
571 && (fossil_isdate(&zTag[i+1]) || fossil_expand_datetime(&zTag[i+1],0,0)!=0)
572 ){
573 char *zDate = mprintf("%s", &zTag[i+1]);
574 char *zTagBase = mprintf("%.*s", i, zTag);
575 char *zXDate;
576 int nDate = strlen(zDate);
577 if( sqlite3_strnicmp(&zDate[nDate-3],"utc",3)==0 ){
578 zDate[nDate-3] = 'z';
579 zDate[nDate-2] = 0;
580 }
581 zXDate = fossil_expand_datetime(zDate,0,1);
582 if( zXDate==0 ) zXDate = zDate;
583 rid = db_int(0,
584 "SELECT event.objid, max(event.mtime)"
585 " FROM tag, tagxref, event"
586 " WHERE tag.tagname='sym-%q' "
@@ -640,11 +652,11 @@
652 if( startOfBranch ) rid = start_of_branch(rid,1);
653 return rid;
654 }
655
656 /* Pure numeric date/time */
657 zDate = fossil_expand_datetime(zTag, 0,1);
658 if( zDate ){
659 rid = db_int(0,
660 "SELECT objid FROM event"
661 " WHERE mtime<=julianday(%Q,fromLocal()) AND type GLOB '%q'"
662 " ORDER BY mtime DESC LIMIT 1",
663
+24 -9
--- src/timeline.c
+++ src/timeline.c
@@ -1092,24 +1092,39 @@
10921092
}
10931093
10941094
/*
10951095
** Convert a symbolic name used as an argument to the a=, b=, or c=
10961096
** query parameters of timeline into a julianday mtime value.
1097
+**
1098
+** If pzDisplay is not null, then display text for the symbolic name might
1099
+** be written into *pzDisplay. But that is not guaranteed.
1100
+**
1101
+** If bRoundUp is true and the symbolic name is a timestamp with less
1102
+** than millisecond resolution, then the timestamp is rounding up to the
1103
+** largest millisecond consistent with that timestamp. If bRoundUp is
1104
+** false, then the resulting time is obtained by extending the timestamp
1105
+** with zeros (hence rounding down). Use bRoundUp==1 if the result
1106
+** will be used in mtime<=$RESULT and use bRoundUp==0 if the result
1107
+** will be used in mtime>=$RESULT.
10971108
*/
1098
-double symbolic_name_to_mtime(const char *z, const char **pzDisplay){
1109
+double symbolic_name_to_mtime(
1110
+ const char *z, /* Input symbolic name */
1111
+ const char **pzDisplay, /* Perhaps write display text here, if not NULL */
1112
+ int bRoundUp /* Round up if true */
1113
+){
10991114
double mtime;
11001115
int rid;
11011116
const char *zDate;
11021117
if( z==0 ) return -1.0;
11031118
if( fossil_isdate(z) ){
11041119
mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())", z);
11051120
if( mtime>0.0 ) return mtime;
11061121
}
1107
- zDate = fossil_expand_datetime(z, 1);
1122
+ zDate = fossil_expand_datetime(z, 1, bRoundUp);
11081123
if( zDate!=0 ){
11091124
mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())",
1110
- fossil_roundup_date(zDate));
1125
+ bRoundUp ? fossil_roundup_date(zDate) : zDate);
11111126
if( mtime>0.0 ){
11121127
if( pzDisplay ) *pzDisplay = fossil_strdup(zDate);
11131128
return mtime;
11141129
}
11151130
}
@@ -2867,13 +2882,13 @@
28672882
blob_append_sql(&cond,
28682883
" AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
28692884
zSearch, zSearch);
28702885
}
28712886
}
2872
- rBefore = symbolic_name_to_mtime(zBefore, &zBefore);
2873
- rAfter = symbolic_name_to_mtime(zAfter, &zAfter);
2874
- rCirca = symbolic_name_to_mtime(zCirca, &zCirca);
2887
+ rBefore = symbolic_name_to_mtime(zBefore, &zBefore, 1);
2888
+ rAfter = symbolic_name_to_mtime(zAfter, &zAfter, 0);
2889
+ rCirca = symbolic_name_to_mtime(zCirca, &zCirca, 0);
28752890
blob_append_sql(&sql, "%s", blob_sql_text(&cond));
28762891
if( rAfter>0.0 ){
28772892
if( rBefore>0.0 ){
28782893
blob_append_sql(&sql,
28792894
" AND event.mtime>=%.17g AND event.mtime<=%.17g\n"
@@ -3010,11 +3025,11 @@
30103025
zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
30113026
if( (!zDate || !zDate[0]) && ( zAfter || zBefore ) ){
30123027
zDate = mprintf("%s", (zAfter ? zAfter : zBefore));
30133028
}
30143029
if( zDate ){
3015
- rDate = symbolic_name_to_mtime(zDate, 0);
3030
+ rDate = symbolic_name_to_mtime(zDate, 0, 0);
30163031
if( db_int(0,
30173032
"SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob"
30183033
" WHERE blob.rid=event.objid AND mtime<=%.17g%s)",
30193034
rDate-ONE_SECOND, blob_sql_text(&cond))
30203035
){
@@ -3026,11 +3041,11 @@
30263041
zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/");
30273042
if( (!zDate || !zDate[0]) && ( zAfter || zBefore ) ){
30283043
zDate = mprintf("%s", (zBefore ? zBefore : zAfter));
30293044
}
30303045
if( zDate ){
3031
- rDate = symbolic_name_to_mtime(zDate, 0);
3046
+ rDate = symbolic_name_to_mtime(zDate, 0, 0);
30323047
if( db_int(0,
30333048
"SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob"
30343049
" WHERE blob.rid=event.objid AND mtime>=%.17g%s)",
30353050
rDate+ONE_SECOND, blob_sql_text(&cond))
30363051
){
@@ -3069,11 +3084,11 @@
30693084
style_submenu_element("Advanced", "%s",
30703085
url_render(&url, "advm", "1", "udc", "1"));
30713086
}
30723087
if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID;
30733088
if( useDividers && zMark && zMark[0] ){
3074
- double r = symbolic_name_to_mtime(zMark, 0);
3089
+ double r = symbolic_name_to_mtime(zMark, 0, 0);
30753090
if( r>0.0 && !selectedRid ) selectedRid = timeline_add_divider(r);
30763091
}
30773092
blob_zero(&sql);
30783093
if( PB("oldestfirst") ){
30793094
db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby ASC /*scan*/");
30803095
--- src/timeline.c
+++ src/timeline.c
@@ -1092,24 +1092,39 @@
1092 }
1093
1094 /*
1095 ** Convert a symbolic name used as an argument to the a=, b=, or c=
1096 ** query parameters of timeline into a julianday mtime value.
 
 
 
 
 
 
 
 
 
 
 
1097 */
1098 double symbolic_name_to_mtime(const char *z, const char **pzDisplay){
 
 
 
 
1099 double mtime;
1100 int rid;
1101 const char *zDate;
1102 if( z==0 ) return -1.0;
1103 if( fossil_isdate(z) ){
1104 mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())", z);
1105 if( mtime>0.0 ) return mtime;
1106 }
1107 zDate = fossil_expand_datetime(z, 1);
1108 if( zDate!=0 ){
1109 mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())",
1110 fossil_roundup_date(zDate));
1111 if( mtime>0.0 ){
1112 if( pzDisplay ) *pzDisplay = fossil_strdup(zDate);
1113 return mtime;
1114 }
1115 }
@@ -2867,13 +2882,13 @@
2867 blob_append_sql(&cond,
2868 " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
2869 zSearch, zSearch);
2870 }
2871 }
2872 rBefore = symbolic_name_to_mtime(zBefore, &zBefore);
2873 rAfter = symbolic_name_to_mtime(zAfter, &zAfter);
2874 rCirca = symbolic_name_to_mtime(zCirca, &zCirca);
2875 blob_append_sql(&sql, "%s", blob_sql_text(&cond));
2876 if( rAfter>0.0 ){
2877 if( rBefore>0.0 ){
2878 blob_append_sql(&sql,
2879 " AND event.mtime>=%.17g AND event.mtime<=%.17g\n"
@@ -3010,11 +3025,11 @@
3010 zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
3011 if( (!zDate || !zDate[0]) && ( zAfter || zBefore ) ){
3012 zDate = mprintf("%s", (zAfter ? zAfter : zBefore));
3013 }
3014 if( zDate ){
3015 rDate = symbolic_name_to_mtime(zDate, 0);
3016 if( db_int(0,
3017 "SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob"
3018 " WHERE blob.rid=event.objid AND mtime<=%.17g%s)",
3019 rDate-ONE_SECOND, blob_sql_text(&cond))
3020 ){
@@ -3026,11 +3041,11 @@
3026 zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/");
3027 if( (!zDate || !zDate[0]) && ( zAfter || zBefore ) ){
3028 zDate = mprintf("%s", (zBefore ? zBefore : zAfter));
3029 }
3030 if( zDate ){
3031 rDate = symbolic_name_to_mtime(zDate, 0);
3032 if( db_int(0,
3033 "SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob"
3034 " WHERE blob.rid=event.objid AND mtime>=%.17g%s)",
3035 rDate+ONE_SECOND, blob_sql_text(&cond))
3036 ){
@@ -3069,11 +3084,11 @@
3069 style_submenu_element("Advanced", "%s",
3070 url_render(&url, "advm", "1", "udc", "1"));
3071 }
3072 if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID;
3073 if( useDividers && zMark && zMark[0] ){
3074 double r = symbolic_name_to_mtime(zMark, 0);
3075 if( r>0.0 && !selectedRid ) selectedRid = timeline_add_divider(r);
3076 }
3077 blob_zero(&sql);
3078 if( PB("oldestfirst") ){
3079 db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby ASC /*scan*/");
3080
--- src/timeline.c
+++ src/timeline.c
@@ -1092,24 +1092,39 @@
1092 }
1093
1094 /*
1095 ** Convert a symbolic name used as an argument to the a=, b=, or c=
1096 ** query parameters of timeline into a julianday mtime value.
1097 **
1098 ** If pzDisplay is not null, then display text for the symbolic name might
1099 ** be written into *pzDisplay. But that is not guaranteed.
1100 **
1101 ** If bRoundUp is true and the symbolic name is a timestamp with less
1102 ** than millisecond resolution, then the timestamp is rounding up to the
1103 ** largest millisecond consistent with that timestamp. If bRoundUp is
1104 ** false, then the resulting time is obtained by extending the timestamp
1105 ** with zeros (hence rounding down). Use bRoundUp==1 if the result
1106 ** will be used in mtime<=$RESULT and use bRoundUp==0 if the result
1107 ** will be used in mtime>=$RESULT.
1108 */
1109 double symbolic_name_to_mtime(
1110 const char *z, /* Input symbolic name */
1111 const char **pzDisplay, /* Perhaps write display text here, if not NULL */
1112 int bRoundUp /* Round up if true */
1113 ){
1114 double mtime;
1115 int rid;
1116 const char *zDate;
1117 if( z==0 ) return -1.0;
1118 if( fossil_isdate(z) ){
1119 mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())", z);
1120 if( mtime>0.0 ) return mtime;
1121 }
1122 zDate = fossil_expand_datetime(z, 1, bRoundUp);
1123 if( zDate!=0 ){
1124 mtime = db_double(0.0, "SELECT julianday(%Q,fromLocal())",
1125 bRoundUp ? fossil_roundup_date(zDate) : zDate);
1126 if( mtime>0.0 ){
1127 if( pzDisplay ) *pzDisplay = fossil_strdup(zDate);
1128 return mtime;
1129 }
1130 }
@@ -2867,13 +2882,13 @@
2882 blob_append_sql(&cond,
2883 " AND (event.comment LIKE '%%%q%%' OR event.brief LIKE '%%%q%%')",
2884 zSearch, zSearch);
2885 }
2886 }
2887 rBefore = symbolic_name_to_mtime(zBefore, &zBefore, 1);
2888 rAfter = symbolic_name_to_mtime(zAfter, &zAfter, 0);
2889 rCirca = symbolic_name_to_mtime(zCirca, &zCirca, 0);
2890 blob_append_sql(&sql, "%s", blob_sql_text(&cond));
2891 if( rAfter>0.0 ){
2892 if( rBefore>0.0 ){
2893 blob_append_sql(&sql,
2894 " AND event.mtime>=%.17g AND event.mtime<=%.17g\n"
@@ -3010,11 +3025,11 @@
3025 zDate = db_text(0, "SELECT min(timestamp) FROM timeline /*scan*/");
3026 if( (!zDate || !zDate[0]) && ( zAfter || zBefore ) ){
3027 zDate = mprintf("%s", (zAfter ? zAfter : zBefore));
3028 }
3029 if( zDate ){
3030 rDate = symbolic_name_to_mtime(zDate, 0, 0);
3031 if( db_int(0,
3032 "SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob"
3033 " WHERE blob.rid=event.objid AND mtime<=%.17g%s)",
3034 rDate-ONE_SECOND, blob_sql_text(&cond))
3035 ){
@@ -3026,11 +3041,11 @@
3041 zDate = db_text(0, "SELECT max(timestamp) FROM timeline /*scan*/");
3042 if( (!zDate || !zDate[0]) && ( zAfter || zBefore ) ){
3043 zDate = mprintf("%s", (zBefore ? zBefore : zAfter));
3044 }
3045 if( zDate ){
3046 rDate = symbolic_name_to_mtime(zDate, 0, 0);
3047 if( db_int(0,
3048 "SELECT EXISTS (SELECT 1 FROM event CROSS JOIN blob"
3049 " WHERE blob.rid=event.objid AND mtime>=%.17g%s)",
3050 rDate+ONE_SECOND, blob_sql_text(&cond))
3051 ){
@@ -3069,11 +3084,11 @@
3084 style_submenu_element("Advanced", "%s",
3085 url_render(&url, "advm", "1", "udc", "1"));
3086 }
3087 if( PB("showid") ) tmFlags |= TIMELINE_SHOWRID;
3088 if( useDividers && zMark && zMark[0] ){
3089 double r = symbolic_name_to_mtime(zMark, 0, 0);
3090 if( r>0.0 && !selectedRid ) selectedRid = timeline_add_divider(r);
3091 }
3092 blob_zero(&sql);
3093 if( PB("oldestfirst") ){
3094 db_prepare(&q, "SELECT * FROM timeline ORDER BY sortby ASC /*scan*/");
3095

Keyboard Shortcuts

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