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/bc2eb6cacfe4
branches:  trunk
changeset: 815174:bc2eb6cacfe4
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 350b636065e7 -r bc2eb6cacfe4 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