Module Name: src
Committed By: christos
Date: Mon Dec 7 20:55:49 UTC 2015
Modified Files:
src/lib/libutil: parsedate.3 parsedate.y
Log Message:
- Add support for "midnight" "noon", dawn etc.
- Add validation to date/time strings by checking that mktime did not change
the fields of struct tm from the ones requested
- Allow the format "year monthname day".
>From kre
To generate a diff of this commit:
cvs rdiff -u -r1.17 -r1.18 src/lib/libutil/parsedate.3
cvs rdiff -u -r1.22 -r1.23 src/lib/libutil/parsedate.y
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/lib/libutil/parsedate.3
diff -u src/lib/libutil/parsedate.3:1.17 src/lib/libutil/parsedate.3:1.18
--- src/lib/libutil/parsedate.3:1.17 Thu Nov 26 04:48:21 2015
+++ src/lib/libutil/parsedate.3 Mon Dec 7 15:55:49 2015
@@ -1,4 +1,4 @@
-.\" $NetBSD: parsedate.3,v 1.17 2015/11/26 09:48:21 wiz Exp $
+.\" $NetBSD: parsedate.3,v 1.18 2015/12/07 20:55:49 christos Exp $
.\"
.\" Copyright (c) 2006 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -27,7 +27,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd November 25, 2015
+.Dd December 7, 2015
.Dt PARSEDATE 3
.Os
.Sh NAME
@@ -106,7 +106,14 @@ The following words are recognized in En
.Dv AM ,
.Dv PM ,
.Dv a.m. ,
-.Dv p.m.
+.Dv p.m. ,
+.Dv midnight ,
+.Dv mn ,
+.Dv noon ,
+.Dv dawn ,
+.Dv sunup ,
+.Dv sunset ,
+.Dv sundown .
.Pp
The months:
.Dv january ,
@@ -229,7 +236,7 @@ An ISO-8601 date.
The year in an ISO-8601 date is always taken literally,
so this is the year 69, not 2069.
.It 10/1/2000
-October 10, 2000; the common US format.
+October 1, 2000; the common, but bizarre, US format.
.It 20 Jun 1994
.It 23jun2001
.It 1-sep-06
@@ -253,6 +260,7 @@ As well as times:
.It 12:11:01.000012
.It 12:21-0500
.El
+Fractions of seconds (after a decimal point) are parsed, but ignored.
.Pp
Relative items are also supported:
.Bl -tag -compact -width "this thursday"
Index: src/lib/libutil/parsedate.y
diff -u src/lib/libutil/parsedate.y:1.22 src/lib/libutil/parsedate.y:1.23
--- src/lib/libutil/parsedate.y:1.22 Sun Dec 6 09:43:59 2015
+++ src/lib/libutil/parsedate.y Mon Dec 7 15:55:49 2015
@@ -14,7 +14,7 @@
#include <sys/cdefs.h>
#ifdef __RCSID
-__RCSID("$NetBSD: parsedate.y,v 1.22 2015/12/06 14:43:59 christos Exp $");
+__RCSID("$NetBSD: parsedate.y,v 1.23 2015/12/07 20:55:49 christos Exp $");
#endif
#include <stdio.h>
@@ -99,10 +99,10 @@ struct dateinfo {
}
%token tAGO tDAY tDAYZONE tID tMERIDIAN tMINUTE_UNIT tMONTH tMONTH_UNIT
-%token tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST AT_SIGN
+%token tSEC_UNIT tSNUMBER tUNUMBER tZONE tDST AT_SIGN tTIME
%type <Number> tDAY tDAYZONE tMINUTE_UNIT tMONTH tMONTH_UNIT
-%type <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE
+%type <Number> tSEC_UNIT tSNUMBER tUNUMBER tZONE tTIME
%type <Meridian> tMERIDIAN o_merid
%parse-param { struct dateinfo *param }
@@ -215,6 +215,15 @@ time : tUNUMBER tMERIDIAN {
param->yyMeridian = MER24;
/* XXX: Do nothing with millis */
}
+ | tTIME {
+ param->yyHour = $1;
+ param->yyMinutes = 0;
+ param->yySeconds = 0;
+ param->yyMeridian = MER24;
+ /* Tues midnight --> Weds 00:00, midnight Tues -> Tues 00:00 */
+ if ($1 == 0 && param->yyHaveDay)
+ param->yyDayNumber++;
+ }
;
time_numericzone : tUNUMBER ':' tUNUMBER tSNUMBER {
@@ -306,8 +315,13 @@ date : tUNUMBER '/' tUNUMBER {
}
| tUNUMBER tMONTH tUNUMBER {
param->yyMonth = $2;
- param->yyDay = $1;
- param->yyYear = $3;
+ if ($1 < 35) {
+ param->yyDay = $1;
+ param->yyYear = $3;
+ } else {
+ param->yyDay = $3;
+ param->yyYear = $1;
+ }
}
;
@@ -589,6 +603,17 @@ static const TABLE MilitaryTable[] = {
{ NULL, 0, 0 }
};
+static const TABLE TimeNames[] = {
+ { "midnight", tTIME, 0 },
+ { "mn", tTIME, 0 },
+ { "noon", tTIME, 12 },
+ { "dawn", tTIME, 6 },
+ { "sunup", tTIME, 6 },
+ { "sunset", tTIME, 18 },
+ { "sundown", tTIME, 18 },
+ { NULL, 0, 0 }
+};
+
@@ -635,6 +660,7 @@ Convert(
)
{
struct tm tm = {.tm_sec = 0};
+ struct tm otm;
time_t result;
tm.tm_sec = Seconds;
@@ -673,6 +699,15 @@ Convert(
fprintf(stderr, " %s", ctime(&result));
#endif
+#define TM_NE(fld) (otm.tm_ ## fld != tm.tm_ ## fld)
+ if (TM_NE(year) || TM_NE(mon) || TM_NE(mday) ||
+ TM_NE(hour) || TM_NE(min) || TM_NE(sec)) {
+ /* mktime() "corrected" our tm, so it must have been invalid */
+ result = -1;
+ errno = EAGAIN;
+ }
+#undef TM_NE
+
return result;
}
@@ -800,6 +835,12 @@ LookupWord(YYSTYPE *yylval, char *buff)
if (strcmp(buff, "dst") == 0)
return tDST;
+ for (tp = TimeNames; tp->name; tp++)
+ if (strcmp(buff, tp->name) == 0) {
+ yylval->Number = tp->value;
+ return tp->type;
+ }
+
for (tp = UnitsTable; tp->name; tp++)
if (strcmp(buff, tp->name) == 0) {
yylval->Number = tp->value;