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/27/raw.patch | git am

b/i3status.c

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

b/i3status.conf

82
@@ -20,6 +20,7 @@ order += "ethernet eth0"
83
 order += "battery 0"
84
 order += "load"
85
 order += "time"
86
+order += "tztime pacific"
87
 
88
 wireless wlan0 {
89
         format_up = "W: (%quality at %essid) %ip"
90
@@ -48,6 +49,11 @@ time {
91
         format = "%Y-%m-%d %H:%M:%S"
92
 }
93
 
94
+tztime pacific {
95
+        format = "%Y-%m-%d %H:%M:%S %Z"
96
+        timezone = "US/Pacific"
97
+}
98
+
99
 load {
100
         format = "%1min"
101
 }

b/include/i3status.h

106
@@ -140,8 +140,8 @@ char *auto_detect_format();
107
 void print_ipv6_info(yajl_gen json_gen, char *buffer, const char *format_up, const char *format_down);
108
 void print_disk_info(yajl_gen json_gen, char *buffer, const char *path, const char *format);
109
 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);
110
-void print_time(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm);
111
-void print_ddate(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm);
112
+void print_time(yajl_gen json_gen, char *buffer, const char *format, const char *timezone, time_t t);
113
+void print_ddate(yajl_gen json_gen, char *buffer, const char *format, time_t t);
114
 const char *get_ip_addr();
115
 void print_wireless_info(yajl_gen json_gen, char *buffer, const char *interface, const char *format_up, const char *format_down);
116
 void print_run_watch(yajl_gen json_gen, char *buffer, const char *title, const char *pidfile, const char *format);

b/man/i3status.man

121
@@ -57,6 +57,7 @@ order += "battery 0"
122
 order += "cpu_temperature 0"
123
 order += "load"
124
 order += "time"
125
+order += "tztime pacific"
126
 
127
 wireless wlan0 {
128
         format_up = "W: (%quality at %essid, %bitrate) %ip"
129
@@ -87,6 +88,11 @@ time {
130
 	format = "%Y-%m-%d %H:%M:%S"
131
 }
132
 
133
+tztime pacific {
134
+        format = "%Y-%m-%d %H:%M:%S %Z"
135
+        timezone = "US/Pacific"
136
+}
137
+
138
 load {
139
 	format = "%5min"
140
 }
141
@@ -258,12 +264,26 @@ Gets the system load (number of processes waiting for CPU time in the last
142
 
143
 === Time
144
 
145
-Formats the current system time. See +strftime(3)+ for the format.
146
+Outputs the current time in the local timezone.
147
+To use a different timezone, you can set the TZ environment variable,
148
+or use the +tztime+ module.
149
+See +strftime(3)+ for details on the format string.
150
 
151
 *Example order*: +time+
152
 
153
 *Example format*: +%Y-%m-%d %H:%M:%S+
154
 
155
+=== TzTime
156
+
157
+Outputs the current time in the given timezone.
158
+See +strftime(3)+ for details on the format string.
159
+
160
+*Example order*: +tztime pacific+
161
+
162
+*Example format*: +%Y-%m-%d %H:%M:%S %Z+
163
+
164
+*Example timezone*: +US/Pacific+
165
+
166
 === DDate
167
 
168
 Outputs the current discordian date in user-specified format. See +ddate(1)+ for

b/src/print_ddate.c

173
@@ -204,11 +204,13 @@ struct disc_time *get_ddate(struct tm *current_tm) {
174
         return &dt;
175
 }
176
 
177
-void print_ddate(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm) {
178
+void print_ddate(yajl_gen json_gen, char *buffer, const char *format, time_t t) {
179
         char *outwalk = buffer;
180
         static char *form = NULL;
181
+        struct tm current_tm;
182
         struct disc_time *dt;
183
-        if ((dt = get_ddate(current_tm)) == NULL)
184
+        localtime_r(&t, &current_tm);
185
+        if ((dt = get_ddate(&current_tm)) == NULL)
186
                 return;
187
         if (form == NULL)
188
                 if ((form = malloc(strlen(format) + 1)) == NULL)

b/src/print_time.c

193
@@ -7,12 +7,36 @@
194
 
195
 #include "i3status.h"
196
 
197
-void print_time(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm) {
198
+static const char *local_timezone = NULL;
199
+static const char *current_timezone = NULL;
200
+
201
+void print_time(yajl_gen json_gen, char *buffer, const char *format, const char *timezone, time_t t) {
202
         char *outwalk = buffer;
203
-        if (current_tm == NULL)
204
-                return;
205
-        /* Get date & time */
206
-        outwalk += strftime(outwalk, 4095, format, current_tm);
207
+        struct tm tm;
208
+
209
+        if (local_timezone == NULL) {
210
+                /* First call, initialize. */
211
+                local_timezone = getenv("TZ");
212
+                if (local_timezone == NULL) {
213
+                        /* Not set in environment, use empty string and tzset()
214
+                         * will use /etc/localtime.
215
+                         */
216
+                        local_timezone = "";
217
+                }
218
+        }
219
+        if (timezone == NULL) {
220
+                /* User wants localtime. */
221
+                timezone = local_timezone;
222
+        }
223
+        if (timezone != current_timezone) {
224
+                /* Need to tzset() before formatting. */
225
+                setenv("TZ", timezone, 1);
226
+                tzset();
227
+                current_timezone = timezone;
228
+        }
229
+        /* Convert time and format output. */
230
+        localtime_r(&t, &tm);
231
+        outwalk += strftime(outwalk, 4095, format, &tm);
232
         *outwalk = '\0';
233
         OUTPUT_FULL_TEXT(buffer);
234
 }