new GPRINT option :strftime to print time associated with a VDEF value
authoroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Sun, 21 May 2006 21:15:39 +0000 (21:15 +0000)
committeroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Sun, 21 May 2006 21:15:39 +0000 (21:15 +0000)
git-svn-id: svn://svn.oetiker.ch/rrdtool/branches/1.2/program@831 a5681a0c-68f1-0310-ab6d-d61299d08faa

doc/rrdgraph_graph.pod
src/rrd_graph.c
src/rrd_graph.h
src/rrd_graph_helper.c

index 7e3aaf2..4543d74 100644 (file)
@@ -50,7 +50,7 @@ Similarly, no report is generated if you don't use print options.
 =over 4
 
 
-=item B<PRINT:>I<vname>B<:>I<format>
+=item B<PRINT:>I<vname>B<:>I<format>[B<:strftime>]
 
 Depending on the context, either the value component or the time
 component of a B<VDEF> is printed using I<format>. It is an error
@@ -64,29 +64,29 @@ For printing values:
 
 =over 4
 
-=item *
+=item B<%%>
 
-B<%%> just prints a literal '%' character
+just prints a literal '%' character
 
-=item *
+=item B<%#.#le>
 
-B<%#.#le> prints numbers like 1.2346e+04. The optional integers # denote field
+prints numbers like 1.2346e+04. The optional integers # denote field
 width and decimal precision.
 
-=item *
+=item B<%#.#lf>
 
-B<%#.#lf> prints numbers like 12345.6789, with optional field width
+prints numbers like 12345.6789, with optional field width
 and precision.
 
-=item *
+=item B<%s>
 
-B<%s> place this after B<%le>, B<%lf> or B<%lg>. This will be replaced by the
+place this after B<%le>, B<%lf> or B<%lg>. This will be replaced by the
 appropriate SI magnitude unit and the value will be scaled
 accordingly (123456 -> 123.456 k).
 
-=item *
+=item B<%S>
 
-B<%S> is similar to B<%s>. It does, however, use a previously defined
+is similar to B<%s>. It does, however, use a previously defined
 magnitude unit. If there is no such unit yet, it tries to define
 one (just like B<%s>) unless the value is zero, in which case the magnitude
 unit stays undefined. Thus, formatter strings using B<%S> and no B<%s>
@@ -94,51 +94,111 @@ will all use the same magnitude unit except for zero values.
 
 =back
 
-For printing times:
+If you PRINT a VDEF value, you can also print the time associated with it by appending the string
+B<:strftime> to the format. Note that rrdtool uses the strftime function of your OSs clibrary. This means that
+the conversion specifier may vary. Check the manual page if you are uncertain. The following is a list of
+conversion specifiers usually supported across the board. 
 
 =over 4
 
-=item *
+=item B<%a>
 
-B<%%> just prints a literal '%' character
+The abbreviated weekday name according to the current locale.
 
-=item *
+=item B<%A>
 
-B<%a, %A> print the abbreviated or full name of the day of the week.
+The full weekday name according to the current locale.
 
-=item *
+=item B<%b>
 
-B<%b, %B> print the abbreviated or full name of the month.
+The abbreviated month name according to the current locale.
 
-=item *
+=item B<%B>
 
-B<%d, %m, %y, %H, %M, %S> print day, month, year, hour, minute, and
-second in two-digit format.
+The full month name according to the current locale.
 
-=item *
+=item B<%c>
 
-B<%Y> prints the year in 4-digit format.
+The preferred date and time representation for the current locale.
 
-=item *
+=item B<%d>
 
-B<%I, %p> print the hour (01..12), 'am' or 'pm'.
+The day of the month as a decimal number (range 01 to 31).
 
-=item *
+=item B<%H>
 
-B<%j, %w> print day of the week (0..6), day of the year (1..366)
+The hour as a decimal number using a 24-hour clock (range 00 to 23).
 
-=item *
+=item B<%I>
 
-B<%c, %x, %X> print date+time, date only, time only.
+The hour as a decimal number using a 12-hour clock (range 01 to 12).
 
-=item *
+=item B<%j>
 
-B<%U, %W> number of the week of the current year, with either the
-first Sunday (%U) or the first Monday (%W) determining the first week.
+The day of the year as a decimal number (range 001 to 366).
 
-=item *
+=item B<%m>
 
-B<%Z> prints the time zone.
+The month as a decimal number (range 01 to 12).
+
+=item B<%M>
+
+The minute as a decimal number (range 00 to 59).
+
+=item B<%p>
+
+Either `AM' or `PM' according to the given time value, or the corresponding
+strings for the current locale.  Noon is treated as `pm' and midnight as
+`am'.  Note that in many locales and `pm' notation is unsupported and in
+such cases %p will return an empty string.
+
+=item B<%S>
+
+The second as a decimal number (range 00 to 61).
+
+=item B<%U>
+
+The  week  number  of  the current year as a decimal number, range 00 to 53, starting with the
+first Sunday as the first day of week 01. See also %V and %W.
+
+=item B<%V>
+
+The ISO 8601:1988 week number of the current year as a decimal number, range 01 to  53,  where
+week  1 is the first week that has at least 4 days in the current year, and with Monday as the
+first day of the week. See also %U and %W.
+
+=item B<%w>
+
+The day of the week as a decimal, range 0 to 6, Sunday being 0.  See also %u.
+
+=item B<%W>
+
+The week number of the current year as a decimal number, range 00 to  53,  starting  with  the
+first Monday as the first day of week 01.
+
+=item B<%x>
+
+The preferred date representation for the current locale without the time.
+
+=item B<%X>
+
+The preferred time representation for the current locale without the date.
+
+=item B<%y>
+
+The year as a decimal number without a century (range 00 to 99).
+
+=item B<%Y>
+
+The year as a decimal number including the century.
+
+=item B<%Z>
+
+The time zone or name or abbreviation.
+
+=item B<%%>
+
+A literal `%' character.
 
 =back
 
index 938132a..e8a07b6 100644 (file)
@@ -1227,7 +1227,7 @@ print_calc(image_desc_t *im, char ***prdata)
 {
     long i,ii,validsteps;
     double printval;
-    time_t printtime;
+    struct tm tmvdef;
     int graphelement = 0;
     long vidx;
     int max_ii;        
@@ -1235,6 +1235,9 @@ print_calc(image_desc_t *im, char ***prdata)
     char *si_symb = "";
     char *percent_s;
     int prlines = 1;
+    /* wow initializing tmvdef is quite a task :-) */
+    time_t now = time(NULL);
+    localtime_r(&now,&tmvdef);
     if (im->imginfo) prlines++;
     for(i=0;i<im->gdes_c;i++){
        switch(im->gdes[i].gf){
@@ -1252,7 +1255,7 @@ print_calc(image_desc_t *im, char ***prdata)
            vidx = im->gdes[i].vidx;
            if (im->gdes[vidx].gf==GF_VDEF) { /* simply use vals */
                printval = im->gdes[vidx].vf.val;
-               printtime = im->gdes[vidx].vf.when;
+               localtime_r(&im->gdes[vidx].vf.when,&tmvdef);
            } else { /* need to calculate max,min,avg etcetera */
                max_ii =((im->gdes[vidx].end 
                        - im->gdes[vidx].start)
@@ -1298,21 +1301,6 @@ print_calc(image_desc_t *im, char ***prdata)
                }
            } /* prepare printval */
 
-           if (!strcmp(im->gdes[i].format,"%c")) { /* VDEF time print */
-               char ctime_buf[128]; /* PS: for ctime_r, must be >= 26 chars */
-               int iii=0;
-               ctime_r(&printtime,ctime_buf); 
-               while(isprint(ctime_buf[iii])){iii++;}
-               ctime_buf[iii]='\0';
-               if (im->gdes[i].gf == GF_PRINT){
-                   (*prdata)[prlines-2] = malloc((FMT_LEG_LEN+2)*sizeof(char));
-                   sprintf((*prdata)[prlines-2],"%s (%lu)",ctime_buf,printtime);
-                   (*prdata)[prlines-1] = NULL;
-               } else {
-                   sprintf(im->gdes[i].legend,"%s (%lu)",ctime_buf,printtime);
-                   graphelement = 1;
-               }
-           } else {
            if ((percent_s = strstr(im->gdes[i].format,"%S")) != NULL) {
                /* Magfact is set to -1 upon entry to print_calc.  If it
                 * is still less than 0, then we need to run auto_scale.
@@ -1331,33 +1319,41 @@ print_calc(image_desc_t *im, char ***prdata)
                auto_scale(im,&printval,&si_symb,&magfact);
            }
 
-           if (im->gdes[i].gf == GF_PRINT){
+            if (im->gdes[i].gf == GF_PRINT){
                (*prdata)[prlines-2] = malloc((FMT_LEG_LEN+2)*sizeof(char));
                (*prdata)[prlines-1] = NULL;
-               if (bad_format(im->gdes[i].format)) {
-                       rrd_set_error("bad format for PRINT in '%s'", im->gdes[i].format);
+                if (im->gdes[i].strftm){
+                       strftime((*prdata)[prlines-2],FMT_LEG_LEN,im->gdes[i].format,&tmvdef);
+                } else {
+                 if (bad_format(im->gdes[i].format)) {
+                       rrd_set_error("bad format for PRINT in '%s'", im->gdes[i].format);
                        return -1;
-               }
+                 }
+
 #ifdef HAVE_SNPRINTF
-               snprintf((*prdata)[prlines-2],FMT_LEG_LEN,im->gdes[i].format,printval,si_symb);
+                 snprintf((*prdata)[prlines-2],FMT_LEG_LEN,im->gdes[i].format,printval,si_symb);
 #else
-               sprintf((*prdata)[prlines-2],im->gdes[i].format,printval,si_symb);
+                 sprintf((*prdata)[prlines-2],im->gdes[i].format,printval,si_symb);
 #endif
-           } else {
+               }
+             } else {
                /* GF_GPRINT */
 
-               if (bad_format(im->gdes[i].format)) {
+                if (im->gdes[i].strftm){
+                       strftime(im->gdes[i].legend,FMT_LEG_LEN,im->gdes[i].format,&tmvdef);
+                } else {
+                 if (bad_format(im->gdes[i].format)) {
                        rrd_set_error("bad format for GPRINT in '%s'", im->gdes[i].format);
                        return -1;
-               }
+                 }
 #ifdef HAVE_SNPRINTF
-               snprintf(im->gdes[i].legend,FMT_LEG_LEN-2,im->gdes[i].format,printval,si_symb);
+                 snprintf(im->gdes[i].legend,FMT_LEG_LEN-2,im->gdes[i].format,printval,si_symb);
 #else
-               sprintf(im->gdes[i].legend,im->gdes[i].format,printval,si_symb);
+                 sprintf(im->gdes[i].legend,im->gdes[i].format,printval,si_symb);
 #endif
-               graphelement = 1;
-           }
-           }
+                }
+               graphelement = 1;               
+           }       
            break;
        case GF_LINE:
        case GF_AREA:
@@ -2943,6 +2939,7 @@ gdes_alloc(image_desc_t *im){
     im->gdes[im->gdes_c-1].col = 0x0;
     im->gdes[im->gdes_c-1].legend[0]='\0';
     im->gdes[im->gdes_c-1].format[0]='\0';
+    im->gdes[im->gdes_c-1].strftm=0;   
     im->gdes[im->gdes_c-1].rrd[0]='\0';
     im->gdes[im->gdes_c-1].ds=-1;    
     im->gdes[im->gdes_c-1].cf_reduce=CF_AVERAGE;    
index e143b7b..ef6a696 100644 (file)
@@ -118,6 +118,7 @@ typedef  struct graph_desc_t {
     gfx_color_t    col;        /* graph color */
     char  format[FMT_LEG_LEN+5]; /* format for PRINT AND GPRINT */
     char  legend[FMT_LEG_LEN+5]; /* legend*/
+    int            strftm;     /* should the VDEF legend be formated with strftime */
     double         leg_x,leg_y;  /* location of legend */   
     double         yrule;      /* value for y rule line and for VDEF */
     time_t         xrule;      /* time for x rule line and for VDEF */
index 3af2b1e..d6411a0 100644 (file)
@@ -256,7 +256,7 @@ int
 rrd_parse_print(const char *const line, unsigned int *const eaten, graph_desc_t *const gdp, image_desc_t *const im) {
     /* vname:CF:format in case of DEF-based vname
     ** vname:CF:format in case of CDEF-based vname
-    ** vname:format in case of VDEF-based vname
+    ** vname:format[:strftime] in case of VDEF-based vname
     */
     if ((gdp->vidx=rrd_parse_find_vname(line,eaten,gdp,im))<0) return 1;
  
@@ -279,6 +279,11 @@ rrd_parse_print(const char *const line, unsigned int *const eaten, graph_desc_t
        get the format at this juncture */
     strcpy(gdp->format,gdp->legend);
     gdp->legend[0]='\0';       
+    /* this is a very crud test, parsing :style flags should be in a function */
+    if (im->gdes[gdp->vidx].gf == GF_VDEF && strcmp(line+(*eaten),":strftime")==0){
+       gdp->strftm = 1;
+        (*eaten)+=strlen(":strftime");
+    }
     return 0;
 }