From: Frédéric Marchal Date: Mon, 3 May 2010 20:09:11 +0000 (+0000) Subject: Add clever date ranges specification to command line option -d X-Git-Tag: v2.3-pre2~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=19c5ad736a8e238c257689234435d0416966d25d;p=thirdparty%2Fsarg.git Add clever date ranges specification to command line option -d --- diff --git a/sarg.1 b/sarg.1 index f61ab25..16aeb3d 100644 --- 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 4d4ea58..b3e0297 100644 --- 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_montm_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;