Index: src/rrd_graph.c
===================================================================
--- src/rrd_graph.c	(revision 2018)
+++ src/rrd_graph.c	(working copy)
@@ -26,6 +26,8 @@
 #endif
 
 #include <time.h>
+#define LOCALTIME_R(a,b,c) (c ? gmtime_r(a,b) : localtime_r(a,b))
+#define MKTIME(a,b) (b ? timegm(a) : mktime(a))
 
 #include <locale.h>
 
@@ -1381,12 +1383,13 @@
 time_t find_first_time(
     time_t start,       /* what is the initial time */
     enum tmt_en baseint,    /* what is the basic interval */
-    long basestep       /* how many if these do we jump a time */
+    long basestep,      /* how many of these do we jump a time */
+    int utc
     )
 {
     struct tm tm;
 
-    localtime_r(&start, &tm);
+    LOCALTIME_R(&start, &tm, utc);
 
     switch (baseint) {
     case TMT_SECOND:
@@ -1441,20 +1444,21 @@
     tm.tm_year + 1900) %basestep;
 
     }
-    return mktime(&tm);
+    return MKTIME(&tm, utc);
 }
 
 /* identify the point where the next gridline, label ... gets placed */
 time_t find_next_time(
     time_t current,     /* what is the initial time */
     enum tmt_en baseint,    /* what is the basic interval */
-    long basestep       /* how many if these do we jump a time */
+    long basestep,      /* how many of these do we jump a time */
+    int utc
     )
 {
     struct tm tm;
     time_t    madetime;
 
-    localtime_r(&current, &tm);
+    LOCALTIME_R(&current, &tm, utc);
 
     do {
         switch (baseint) {
@@ -1485,7 +1489,7 @@
         case TMT_YEAR:
             tm.       tm_year += basestep;
         }
-        madetime = mktime(&tm);
+        madetime = MKTIME(&tm, utc);
     } while (madetime == -1);   /* this is necessary to skip impssible times
                                    like the daylight saving time skips */
     return madetime;
@@ -1512,7 +1516,7 @@
     /* wow initializing tmvdef is quite a task :-) */
     time_t    now = time(NULL);
 
-    localtime_r(&now, &tmvdef);
+    LOCALTIME_R(&now, &tmvdef, im->extra_flags & FORCE_UTC_TIME);
     for (i = 0; i < im->gdes_c; i++) {
         vidx = im->gdes[i].vidx;
         switch (im->gdes[i].gf) {
@@ -1524,7 +1528,7 @@
              */
             if (im->gdes[vidx].gf == GF_VDEF) { /* simply use vals */
                 printval = im->gdes[vidx].vf.val;
-                localtime_r(&im->gdes[vidx].vf.when, &tmvdef);
+                LOCALTIME_R(&im->gdes[vidx].vf.when, &tmvdef, im->extra_flags & FORCE_UTC_TIME);
             } else {    /* need to calculate max,min,avg etcetera */
                 max_ii = ((im->gdes[vidx].end - im->gdes[vidx].start)
                           / im->gdes[vidx].step * im->gdes[vidx].ds_cnt);
@@ -2476,16 +2480,18 @@
                                   gridtm,
                                   im->
                                   xlab_user.
-                                  gridst),
+                                  gridst,
+                                  im->extra_flags & FORCE_UTC_TIME),
              timajor =
              find_first_time(im->start,
                              im->xlab_user.
                              mgridtm,
                              im->xlab_user.
-                             mgridst);
+                             mgridst,
+                             im->extra_flags & FORCE_UTC_TIME);
              ti < im->end;
              ti =
-             find_next_time(ti, im->xlab_user.gridtm, im->xlab_user.gridst)
+             find_next_time(ti, im->xlab_user.gridtm, im->xlab_user.gridst, im->extra_flags & FORCE_UTC_TIME)
             ) {
             /* are we inside the graph ? */
             if (ti < im->start || ti > im->end)
@@ -2494,7 +2500,8 @@
                 timajor = find_next_time(timajor,
                                          im->
                                          xlab_user.
-                                         mgridtm, im->xlab_user.mgridst);
+                                         mgridtm, im->xlab_user.mgridst,
+                                         im->extra_flags & FORCE_UTC_TIME);
             }
             if (ti == timajor)
                 continue;   /* skip as falls on major grid line */
@@ -2518,9 +2525,10 @@
                               mgridtm,
                               im->
                               xlab_user.
-                              mgridst);
+                              mgridst,
+                              im->extra_flags & FORCE_UTC_TIME);
          ti < im->end;
-         ti = find_next_time(ti, im->xlab_user.mgridtm, im->xlab_user.mgridst)
+         ti = find_next_time(ti, im->xlab_user.mgridtm, im->xlab_user.mgridst, im->extra_flags & FORCE_UTC_TIME)
         ) {
         /* are we inside the graph ? */
         if (ti < im->start || ti > im->end)
@@ -2544,18 +2552,19 @@
                          im->xlab_user.
                          labtm,
                          im->xlab_user.
-                         labst);
+                         labst,
+                         im->extra_flags & FORCE_UTC_TIME);
          ti <=
          im->end -
          im->xlab_user.precis / 2;
-         ti = find_next_time(ti, im->xlab_user.labtm, im->xlab_user.labst)
+         ti = find_next_time(ti, im->xlab_user.labtm, im->xlab_user.labst, im->extra_flags & FORCE_UTC_TIME)
         ) {
         tilab = ti + im->xlab_user.precis / 2;  /* correct time for the label */
         /* are we inside the graph ? */
         if (tilab < im->start || tilab > im->end)
             continue;
 #if HAVE_STRFTIME
-        localtime_r(&tilab, &tm);
+        LOCALTIME_R(&tilab, &tm, im->extra_flags & FORCE_UTC_TIME);
         strftime(graph_label, 99, im->xlab_user.stst, &tm);
 #else
 # error "your libc has no strftime I guess we'll abort the exercise here."
@@ -4202,6 +4211,7 @@
         { "border",             required_argument, 0, 1007},
         { "grid-dash",          required_argument, 0, 1008},
         { "dynamic-labels",     no_argument,       0, 1009},
+        { "utc",                no_argument,       0, 1010},
         {  0, 0, 0, 0}
 };
 /* *INDENT-ON* */
@@ -4272,6 +4282,9 @@
         case 1001:
             im->extra_flags |= NO_RRDTOOL_TAG;
             break;
+        case 1010:
+            im->extra_flags |= FORCE_UTC_TIME;
+            break;
         case LONGOPT_UNITS_SI:
             if (im->extra_flags & FORCE_UNITS) {
                 rrd_set_error("--units can only be used once!");
Index: src/rrd_graph.h
===================================================================
--- src/rrd_graph.h	(revision 2018)
+++ src/rrd_graph.h	(working copy)
@@ -39,6 +39,7 @@
 
 #define FULL_SIZE_MODE     0x200    /* -width and -height indicate the total size of the image */
 #define NO_RRDTOOL_TAG 0x400  /* disable the rrdtool tag */
+#define FORCE_UTC_TIME  0x800   /* Work in UTC timezone instead of localtimg */
 
 enum tmt_en { TMT_SECOND = 0, TMT_MINUTE, TMT_HOUR, TMT_DAY,
     TMT_WEEK, TMT_MONTH, TMT_YEAR
@@ -334,11 +335,13 @@
 time_t    find_first_time(
     time_t,
     enum tmt_en,
-    long);
+    long,
+    int);
 time_t    find_next_time(
     time_t,
     enum tmt_en,
-    long);
+    long,
+    int);
 int       print_calc(
     image_desc_t *);
 int       leg_place(

