i3 - improved tiling WM


Add tztime module to support multiple different timezones.

Patch status: rejected

Patch by Emil Mikulic

To apply this patch, use:
curl http://cr.i3wm.org/patch/41/raw.patch | git am

b/i3status.c

18
@@ -239,7 +239,13 @@ int main(int argc, char *argv[]) {
19
         };
20
 
21
         cfg_opt_t time_opts[] = {
22
-                CFG_STR("format", "%d.%m.%Y %H:%M:%S", CFGF_NONE),
23
+                CFG_STR("format", "%Y-%m-%d %H:%M:%S", CFGF_NONE),
24
+                CFG_END()
25
+        };
26
+
27
+        cfg_opt_t tztime_opts[] = {
28
+                CFG_STR("format", "%Y-%m-%d %H:%M:%S %Z", CFGF_NONE),
29
+                CFG_STR("timezone", "", CFGF_NONE),
30
                 CFG_END()
31
         };
32
 
33
@@ -292,6 +298,7 @@ int main(int argc, char *argv[]) {
34
                 CFG_SEC("volume", volume_opts, CFGF_TITLE | CFGF_MULTI),
35
                 CFG_SEC("ipv6", ipv6_opts, CFGF_NONE),
36
                 CFG_SEC("time", time_opts, CFGF_NONE),
37
+                CFG_SEC("tztime", tztime_opts, CFGF_TITLE | CFGF_MULTI),
38
                 CFG_SEC("ddate", ddate_opts, CFGF_NONE),
39
                 CFG_SEC("load", load_opts, CFGF_NONE),
40
                 CFG_SEC("cpu_usage", usage_opts, CFGF_NONE),
41
@@ -403,16 +410,9 @@ int main(int argc, char *argv[]) {
42
          * (!), not individual plugins, seem very unlikely. */
43
         char buffer[4096];
44
 
45
-        struct tm tm;
46
         while (1) {
47
                 struct timeval tv;
48
                 gettimeofday(&tv, NULL);
49
-                time_t current_time = tv.tv_sec;
50
-                struct tm *current_tm = NULL;
51
-                if (current_time != (time_t) -1) {
52
-                        localtime_r(&current_time, &tm);
53
-                        current_tm = &tm;
54
-                }
55
                 if (output_format == O_I3BAR)
56
                         yajl_gen_array_open(json_gen);
57
                 for (j = 0; j < cfg_size(cfg, "order"); j++) {
58
@@ -465,13 +465,19 @@ int main(int argc, char *argv[]) {
59
 
60
                         CASE_SEC("time") {
61
                                 SEC_OPEN_MAP("time");
62
-                                print_time(json_gen, buffer, cfg_getstr(sec, "format"), current_tm);
63
+                                print_time(json_gen, buffer, cfg_getstr(sec, "format"), NULL, tv.tv_sec);
64
+                                SEC_CLOSE_MAP;
65
+                        }
66
+
67
+                        CASE_SEC_TITLE("tztime") {
68
+                                SEC_OPEN_MAP("tztime");
69
+                                print_time(json_gen, buffer, cfg_getstr(sec, "format"), cfg_getstr(sec, "timezone"), tv.tv_sec);
70
                                 SEC_CLOSE_MAP;
71
                         }
72
 
73
                         CASE_SEC("ddate") {
74
                                 SEC_OPEN_MAP("ddate");
75
-                                print_ddate(json_gen, buffer, cfg_getstr(sec, "format"), current_tm);
76
+                                print_ddate(json_gen, buffer, cfg_getstr(sec, "format"), tv.tv_sec);
77
                                 SEC_CLOSE_MAP;
78
                         }
79
 

b/i3status.conf

84
@@ -19,7 +19,8 @@ order += "wireless wlan0"
85
 order += "ethernet eth0"
86
 order += "battery 0"
87
 order += "load"
88
-order += "time"
89
+order += "tztime local"
90
+order += "tztime pacific"
91
 
92
 wireless wlan0 {
93
         format_up = "W: (%quality at %essid) %ip"
94
@@ -44,10 +45,15 @@ run_watch VPN {
95
         pidfile = "/var/run/vpnc/pid"
96
 }
97
 
98
-time {
99
+tztime local {
100
         format = "%Y-%m-%d %H:%M:%S"
101
 }
102
 
103
+tztime pacific {
104
+        format = "%Y-%m-%d %H:%M:%S %Z"
105
+        timezone = "US/Pacific"
106
+}
107
+
108
 load {
109
         format = "%1min"
110
 }

b/include/i3status.h

115
@@ -137,11 +137,14 @@ char *endcolor() __attribute__ ((pure));
116
 /* src/auto_detect_format.c */
117
 char *auto_detect_format();
118
 
119
+/* src/print_time.c */
120
+void set_timezone(const char *timezone);
121
+
122
 void print_ipv6_info(yajl_gen json_gen, char *buffer, const char *format_up, const char *format_down);
123
 void print_disk_info(yajl_gen json_gen, char *buffer, const char *path, const char *format);
124
 void print_battery_info(yajl_gen json_gen, char *buffer, int number, const char *path, const char *format, int low_threshold, char *threshold_type, bool last_full_capacity);
125
-void print_time(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm);
126
-void print_ddate(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm);
127
+void print_time(yajl_gen json_gen, char *buffer, const char *format, const char *timezone, time_t t);
128
+void print_ddate(yajl_gen json_gen, char *buffer, const char *format, time_t t);
129
 const char *get_ip_addr();
130
 void print_wireless_info(yajl_gen json_gen, char *buffer, const char *interface, const char *format_up, const char *format_down);
131
 void print_run_watch(yajl_gen json_gen, char *buffer, const char *title, const char *pidfile, const char *format);

b/man/i3status.man

136
@@ -56,7 +56,8 @@ order += "ethernet eth0"
137
 order += "battery 0"
138
 order += "cpu_temperature 0"
139
 order += "load"
140
-order += "time"
141
+order += "tztime local"
142
+order += "tztime pacific"
143
 
144
 wireless wlan0 {
145
         format_up = "W: (%quality at %essid, %bitrate) %ip"
146
@@ -83,8 +84,13 @@ run_watch VPN {
147
         pidfile = "/var/run/vpnc/pid"
148
 }
149
 
150
-time {
151
-	format = "%Y-%m-%d %H:%M:%S"
152
+tztime local {
153
+        format = "%Y-%m-%d %H:%M:%S"
154
+}
155
+
156
+tztime pacific {
157
+        format = "%Y-%m-%d %H:%M:%S %Z"
158
+        timezone = "US/Pacific"
159
 }
160
 
161
 load {
162
@@ -258,12 +264,28 @@ Gets the system load (number of processes waiting for CPU time in the last
163
 
164
 === Time
165
 
166
-Formats the current system time. See +strftime(3)+ for the format.
167
+Outputs the current time in the local timezone.
168
+To use a different timezone, you can set the TZ environment variable,
169
+or use the +tztime+ module.
170
+See +strftime(3)+ for details on the format string.
171
 
172
 *Example order*: +time+
173
 
174
 *Example format*: +%Y-%m-%d %H:%M:%S+
175
 
176
+=== TzTime
177
+
178
+Outputs the current time in the given timezone.
179
+If no timezone is given, local time will be used.
180
+See +strftime(3)+ for details on the format string.
181
+The system's timezone database is usually installed in +/usr/share/zoneinfo+.
182
+
183
+*Example order*: +tztime pacific+
184
+
185
+*Example format*: +%Y-%m-%d %H:%M:%S %Z+
186
+
187
+*Example timezone*: +US/Pacific+
188
+
189
 === DDate
190
 
191
 Outputs the current discordian date in user-specified format. See +ddate(1)+ for

b/src/print_ddate.c

196
@@ -204,11 +204,14 @@ struct disc_time *get_ddate(struct tm *current_tm) {
197
         return &dt;
198
 }
199
 
200
-void print_ddate(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm) {
201
+void print_ddate(yajl_gen json_gen, char *buffer, const char *format, time_t t) {
202
         char *outwalk = buffer;
203
         static char *form = NULL;
204
+        struct tm current_tm;
205
         struct disc_time *dt;
206
-        if ((dt = get_ddate(current_tm)) == NULL)
207
+        set_timezone(NULL);  /* Use local time. */
208
+        localtime_r(&t, &current_tm);
209
+        if ((dt = get_ddate(&current_tm)) == NULL)
210
                 return;
211
         if (form == NULL)
212
                 if ((form = malloc(strlen(format) + 1)) == NULL)

b/src/print_time.c

217
@@ -7,12 +7,39 @@
218
 
219
 #include "i3status.h"
220
 
221
-void print_time(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm) {
222
+static int local_timezone_init = 0;
223
+static const char *local_timezone = NULL;
224
+static const char *current_timezone = NULL;
225
+
226
+void set_timezone(const char *timezone) {
227
+        if (!local_timezone_init) {
228
+                /* First call, initialize. */
229
+                local_timezone = getenv("TZ");
230
+                local_timezone_init = 1;
231
+        }
232
+        if (timezone == NULL || timezone[0] == '\0') {
233
+                /* User wants localtime. */
234
+                timezone = local_timezone;
235
+        }
236
+        if (timezone != current_timezone) {
237
+                if (timezone) {
238
+                  setenv("TZ", timezone, 1);
239
+                } else {
240
+                  unsetenv("TZ");
241
+                }
242
+                tzset();
243
+                current_timezone = timezone;
244
+        }
245
+}
246
+
247
+void print_time(yajl_gen json_gen, char *buffer, const char *format, const char *timezone, time_t t) {
248
         char *outwalk = buffer;
249
-        if (current_tm == NULL)
250
-                return;
251
-        /* Get date & time */
252
-        outwalk += strftime(outwalk, 4095, format, current_tm);
253
+        struct tm tm;
254
+
255
+        /* Convert time and format output. */
256
+        set_timezone(timezone);
257
+        localtime_r(&t, &tm);
258
+        outwalk += strftime(outwalk, 4095, format, &tm);
259
         *outwalk = '\0';
260
         OUTPUT_FULL_TEXT(buffer);
261
 }