]> git.ipfire.org Git - thirdparty/sarg.git/commitdiff
Add clever date ranges specification to command line option -d
authorFrédéric Marchal <fmarchal@users.sourceforge.net>
Mon, 3 May 2010 20:09:11 +0000 (20:09 +0000)
committerFrédéric Marchal <fmarchal@users.sourceforge.net>
Mon, 3 May 2010 20:09:11 +0000 (20:09 +0000)
sarg.1
util.c

diff --git a/sarg.1 b/sarg.1
index f61ab2523f26997d38db1fb00c06552389e8dbd1..16aeb3d3ef3458551b370d4dbd197e8a37007015 100644 (file)
--- a/sarg.1
+++ b/sarg.1
@@ -2,7 +2,7 @@
 .\" First parameter, NAME, should be all caps
 .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
 .\" other parameters are allowed: see man(7), man(1)
-.TH SARG 1 "September 25, 2004"
+.TH SARG 1 "May 3, 2010"
 .\" Please adjust this date whenever revising the manpage.
 .\"
 .\" Some roff macros, for reference:
@@ -61,11 +61,16 @@ as the exclude files to select records that are not counted.
 .TP
 .B \-d date
 Uses
-.IR "date"
-as the timelimit during logfile processing. Format for
-.IR "date"
+.I date
+as the time limit during log file processing. Format for
+.I date
 is
 .B dd/mm/yyyy-dd/mm/yyyy
+or a single date
+.BR "dd/mm/yyyy" ". Date ranges can also be specified as " "day-\fIn\fP" ", " "week-\fIn\fP" ", or " "month-\fIn\fP"
+where
+.I n
+is the number of days, weeks or months to jump backward. Note that there is no spaces around the hyphen.
 .TP
 .B \-e email
 Sends report to
diff --git a/util.c b/util.c
index 4d4ea584d7d36b1422561942807275d081098037..b3e02971933a600ec3e24364f7c4b03cc556a9b6 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1177,24 +1177,126 @@ void date_from(char *date, int *dfrom, int *duntil)
    int d1;
    int m1;
    int y1;
-   int next=-1;
 
-   if (sscanf(date,"%d/%d/%d%n",&d0,&m0,&y0,&next)!=3 || y0<100 || m0<1 || m0>12 || d0<1 || d0>31 || next<0) {
-      debuga(_("The date passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
-      exit(EXIT_FAILURE);
-   }
-   if (date[next]=='-') {
-      if (sscanf(date+next+1,"%d/%d/%d",&d1,&m1,&y1)!=3 || y1<100 || m1<1 || m1>12 || d1<1 || d1>31) {
+   if (isdigit(date[0])) {
+      int next=-1;
+
+      if (sscanf(date,"%d/%d/%d%n",&d0,&m0,&y0,&next)!=3 || y0<100 || m0<1 || m0>12 || d0<1 || d0>31 || next<0) {
+         debuga(_("The date passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
+         exit(EXIT_FAILURE);
+      }
+      if (date[next]=='-') {
+         if (sscanf(date+next+1,"%d/%d/%d",&d1,&m1,&y1)!=3 || y1<100 || m1<1 || m1>12 || d1<1 || d1>31) {
+            debuga(_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
+            exit(EXIT_FAILURE);
+         }
+      } else if (date[next]!='\0') {
          debuga(_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
          exit(EXIT_FAILURE);
+      } else {
+         d1=d0;
+         m1=m0;
+         y1=y0;
       }
-   } else if (date[next]!='\0') {
-      debuga(_("The date range passed as argument is not formated as dd/mm/yyyy or dd/mm/yyyy-dd/mm/yyyy\n"));
-      exit(EXIT_FAILURE);
    } else {
-      d1=d0;
-      m1=m0;
-      y1=y0;
+      int i;
+      time_t Today,t1;
+      struct tm *Date0,Date1;
+
+      if (time(&Today)==(time_t)-1) {
+         debuga(_("Failed to get the current time\n"));
+         exit(EXIT_FAILURE);
+      }
+      if (sscanf(date,"day-%d",&i)==1) {
+         if (i<0) {
+            debuga(_("Invalid number of days in -d parameter\n"));
+            exit(EXIT_FAILURE);
+         }
+         Today-=i*24*60*60;
+         Date0=localtime(&Today);
+         if (Date0==NULL) {
+            debuga(_("Cannot convert local time: %s\n"),strerror(errno));
+            exit(EXIT_FAILURE);
+         }
+         y0=y1=Date0->tm_year+1900;
+         m0=m1=Date0->tm_mon+1;
+         d0=d1=Date0->tm_mday;
+      } else if (sscanf(date,"week-%d",&i)==1) {
+         /*
+         There is no portable way to find the first day of the week even though the
+         information is available in the locale. nl_langinfo has the unofficial
+         parameters _NL_TIME_FIRST_WEEKDAY and _NL_TIME_WEEK_1STDAY but they are
+         undocumented as is their return value and it is discouraged to use them.
+         Beside, nl_langinfo isn't available on windows and the first day of the
+         week isn't available at all on that system.
+         */
+         const int FirstWeekDay=1;
+         time_t WeekBegin;
+
+         if (i<0) {
+            debuga(_("Invalid number of weeks in -d parameter\n"));
+            exit(EXIT_FAILURE);
+         }
+         Date0=localtime(&Today);
+         if (Date0==NULL) {
+            debuga(_("Cannot convert local time: %s\n"),strerror(errno));
+            exit(EXIT_FAILURE);
+         }
+         WeekBegin=Today-((Date0->tm_wday-FirstWeekDay+7)%7)*24*60*60;
+         WeekBegin-=i*7*24*60*60;
+         Date0=localtime(&WeekBegin);
+         if (Date0==NULL) {
+            debuga(_("Cannot convert local time: %s\n"),strerror(errno));
+            exit(EXIT_FAILURE);
+         }
+         y0=Date0->tm_year+1900;
+         m0=Date0->tm_mon+1;
+         d0=Date0->tm_mday;
+         WeekBegin+=6*24*60*60;
+         Date0=localtime(&WeekBegin);
+         if (Date0==NULL) {
+            debuga(_("Cannot convert local time: %s\n"),strerror(errno));
+            exit(EXIT_FAILURE);
+         }
+         y1=Date0->tm_year+1900;
+         m1=Date0->tm_mon+1;
+         d1=Date0->tm_mday;
+      } else if (sscanf(date,"month-%d",&i)==1) {
+         if (i<0) {
+            debuga(_("Invalid number of months in -d parameter\n"));
+            exit(EXIT_FAILURE);
+         }
+         Date0=localtime(&Today);
+         if (Date0==NULL) {
+            debuga(_("Cannot convert local time: %s\n"),strerror(errno));
+            exit(EXIT_FAILURE);
+         }
+         if (Date0->tm_mon<i%12) {
+            y0=Date0->tm_year+1900-i/12-1;
+            m0=(Date0->tm_mon+12-i%12)%12+1;
+            d0=1;
+         } else {
+            y0=Date0->tm_year+1900-i/12;
+            m0=Date0->tm_mon-i%12+1;
+            d0=1;
+         }
+         memcpy(&Date1,Date0,sizeof(struct tm));
+         Date1.tm_isdst=-1;
+         Date1.tm_mday=1;
+         if (m0<12) {
+            Date1.tm_mon=m0;
+            Date1.tm_year=y0-1900;
+         } else {
+            Date1.tm_mon=0;
+            Date1.tm_year=y0-1900+1;
+         }
+         t1=mktime(&Date1);
+         t1-=24*60*60;
+         Date0=localtime(&t1);
+         y1=Date0->tm_year+1900;
+         m1=Date0->tm_mon+1;
+         d1=Date0->tm_mday;
+      }
    }
 
    *dfrom=y0*10000+m0*100+d0;