Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib/libutil Make relative date changes ("+ 2 months") etc, w...
details: https://anonhg.NetBSD.org/src/rev/9f771f058013
branches: trunk
changeset: 345032:9f771f058013
user: kre <kre%NetBSD.org@localhost>
date: Tue May 03 18:14:54 2016 +0000
description:
Make relative date changes ("+ 2 months") etc, work a little more sanely.
OK christos@
diffstat:
lib/libutil/parsedate.y | 84 ++++++++++++++++++++++++++++++++++++------------
1 files changed, 62 insertions(+), 22 deletions(-)
diffs (183 lines):
diff -r 2a2697e88f10 -r 9f771f058013 lib/libutil/parsedate.y
--- a/lib/libutil/parsedate.y Tue May 03 18:10:38 2016 +0000
+++ b/lib/libutil/parsedate.y Tue May 03 18:14:54 2016 +0000
@@ -14,7 +14,7 @@
#include <sys/cdefs.h>
#ifdef __RCSID
-__RCSID("$NetBSD: parsedate.y,v 1.27 2015/12/31 10:52:06 dholland Exp $");
+__RCSID("$NetBSD: parsedate.y,v 1.28 2016/05/03 18:14:54 kre Exp $");
#endif
#include <stdio.h>
@@ -42,6 +42,8 @@
#define HOUR(x) ((time_t)((x) * 60))
#define SECSPERDAY (24L * 60L * 60L)
+#define MAXREL 16 /* hours mins secs days weeks months years - maybe twice each ...*/
+
#define USE_LOCAL_TIME 99999 /* special case for Convert() and yyTimezone */
/*
@@ -88,8 +90,10 @@
time_t yySeconds; /* Second of minute [0-60] */
time_t yyYear; /* Year, see also yyHaveFullYear */
MERIDIAN yyMeridian; /* Interpret yyHour as AM/PM/24 hour clock */
- time_t yyRelMonth;
- time_t yyRelSeconds;
+ struct {
+ time_t yyRelVal;
+ int yyRelMonth;
+ } yyRel[MAXREL];
};
%}
@@ -309,21 +313,21 @@
rel:
relunit
| relunit tAGO {
- param->yyRelSeconds = -param->yyRelSeconds;
- param->yyRelMonth = -param->yyRelMonth;
+ param->yyRel[param->yyHaveRel].yyRelVal =
+ -param->yyRel[param->yyHaveRel].yyRelVal;
}
;
relunit:
- tUNUMBER tMINUTE_UNIT { param->yyRelSeconds += $1 * $2 * 60L; }
- | tSNUMBER tMINUTE_UNIT { param->yyRelSeconds += $1 * $2 * 60L; }
- | tMINUTE_UNIT { param->yyRelSeconds += $1 * 60L; }
- | tSNUMBER tSEC_UNIT { param->yyRelSeconds += $1; }
- | tUNUMBER tSEC_UNIT { param->yyRelSeconds += $1; }
- | tSEC_UNIT { param->yyRelSeconds++; }
- | tSNUMBER tMONTH_UNIT { param->yyRelMonth += $1 * $2; }
- | tUNUMBER tMONTH_UNIT { param->yyRelMonth += $1 * $2; }
- | tMONTH_UNIT { param->yyRelMonth += $1; }
+ tUNUMBER tMINUTE_UNIT { RelVal(param, $1 * $2 * 60L, 0); }
+ | tSNUMBER tMINUTE_UNIT { RelVal(param, $1 * $2 * 60L, 0); }
+ | tMINUTE_UNIT { RelVal(param, $1 * 60L, 0); }
+ | tSNUMBER tSEC_UNIT { RelVal(param, $1, 0); }
+ | tUNUMBER tSEC_UNIT { RelVal(param, $1, 0); }
+ | tSEC_UNIT { RelVal(param, 1L, 0); }
+ | tSNUMBER tMONTH_UNIT { RelVal(param, $1 * $2, 1); }
+ | tUNUMBER tMONTH_UNIT { RelVal(param, $1 * $2, 1); }
+ | tMONTH_UNIT { RelVal(param, $1, 1); }
;
number:
@@ -362,6 +366,17 @@
%%
+static short DaysInMonth[12] = {
+ 31, 28, 31, 30, 31, 30,
+ 31, 31, 30, 31, 30, 31
+};
+
+/*
+ * works with tm.tm_year (ie: rel to 1900)
+ */
+#define isleap(yr) (((yr) & 3) == 0 && (((yr) % 100) != 0 || \
+ ((1900+(yr)) % 400) == 0))
+
/* Month and day table. */
static const TABLE MonthDayTable[] = {
{ "january", tMONTH, 1 },
@@ -571,6 +586,7 @@
{ "midnight", tTIME, 0 },
{ "mn", tTIME, 0 },
{ "noon", tTIME, 12 },
+ { "midday", tTIME, 12 },
{ "dawn", tTIME, 6 },
{ "sunup", tTIME, 6 },
{ "sunset", tTIME, 18 },
@@ -580,7 +596,6 @@
-
/* ARGSUSED */
static int
yyerror(struct dateinfo *param, const char **inp, const char *s __unused)
@@ -588,6 +603,20 @@
return 0;
}
+/*
+ * Save a relative value, if it fits
+ */
+static void
+RelVal(struct dateinfo *param, time_t v, int type)
+{
+ int i;
+
+ if ((i = param->yyHaveRel) >= MAXREL)
+ return;
+ param->yyRel[i].yyRelMonth = type;
+ param->yyRel[i].yyRelVal = v;
+}
+
/* Adjust year from a value that might be abbreviated, to a full value.
* e.g. convert 70 to 1970.
@@ -729,6 +758,7 @@
struct tm tm;
time_t Month;
time_t Then;
+ int Day;
if (RelMonth == 0)
return 0;
@@ -748,6 +778,9 @@
Month = 12 * (tm.tm_year + 1900) + tm.tm_mon + RelMonth;
tm.tm_year = (Month / 12) - 1900;
tm.tm_mon = Month % 12;
+ if (tm.tm_mday > (Day = DaysInMonth[tm.tm_mon] +
+ ((tm.tm_mon==1) ? isleap(tm.tm_year) : 0)))
+ tm.tm_mday = Day;
errno = 0;
Then = mktime(&tm);
if (Then == -1 && errno != 0)
@@ -939,6 +972,7 @@
time_t tod, rm;
struct dateinfo param;
int saved_errno;
+ int i;
saved_errno = errno;
errno = 0;
@@ -972,8 +1006,6 @@
param.yyMinutes = 0;
param.yySeconds = 0;
param.yyMeridian = MER24;
- param.yyRelSeconds = 0;
- param.yyRelMonth = 0;
param.yyHaveDate = 0;
param.yyHaveFullYear = 0;
param.yyHaveDay = 0;
@@ -1005,12 +1037,20 @@
Start -= ((tm->tm_hour * 60L + tm->tm_min) * 60L) + tm->tm_sec;
}
- Start += param.yyRelSeconds;
- errno = 0;
- rm = RelativeMonth(Start, param.yyRelMonth, param.yyTimezone);
- if (rm == -1 && errno != 0)
+ if (param.yyHaveRel > MAXREL) {
+ errno = EINVAL;
return -1;
- Start += rm;
+ }
+ for (i = 0; i < param.yyHaveRel; i++) {
+ if (param.yyRel[i].yyRelMonth) {
+ errno = 0;
+ rm = RelativeMonth(Start, param.yyRel[i].yyRelVal, param.yyTimezone);
+ if (rm == -1 && errno != 0)
+ return -1;
+ Start += rm;
+ } else
+ Start += param.yyRel[i].yyRelVal;
+ }
if (param.yyHaveDay && !param.yyHaveDate) {
errno = 0;
Home |
Main Index |
Thread Index |
Old Index