i3 - improved tiling WM


Support multiple times with different timezones.

Patch status: rejected

Patch by Emil Mikulic

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

b/i3status.c

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

b/i3status.conf

75
@@ -19,7 +19,7 @@ order += "wireless wlan0"
76
 order += "ethernet eth0"
77
 order += "battery 0"
78
 order += "load"
79
-order += "time"
80
+order += "time local"
81
 
82
 wireless wlan0 {
83
         format_up = "W: (%quality at %essid) %ip"
84
@@ -44,8 +44,8 @@ run_watch VPN {
85
         pidfile = "/var/run/vpnc/pid"
86
 }
87
 
88
-time {
89
-        format = "%Y-%m-%d %H:%M:%S"
90
+time local {
91
+        format = "%Y-%m-%d %H:%M:%S %Z"
92
 }
93
 
94
 load {

b/include/i3status.h

99
@@ -140,8 +140,8 @@ char *auto_detect_format();
100
 void print_ipv6_info(yajl_gen json_gen, char *buffer, const char *format_up, const char *format_down);
101
 void print_disk_info(yajl_gen json_gen, char *buffer, const char *path, const char *format);
102
 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);
103
-void print_time(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm);
104
-void print_ddate(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm);
105
+void print_time(yajl_gen json_gen, char *buffer, const char *format, const char *timezone, time_t t);
106
+void print_ddate(yajl_gen json_gen, char *buffer, const char *format, time_t t);
107
 const char *get_ip_addr();
108
 void print_wireless_info(yajl_gen json_gen, char *buffer, const char *interface, const char *format_up, const char *format_down);
109
 void print_run_watch(yajl_gen json_gen, char *buffer, const char *title, const char *pidfile, const char *format);

b/man/i3status.man

114
@@ -56,7 +56,7 @@ order += "ethernet eth0"
115
 order += "battery 0"
116
 order += "cpu_temperature 0"
117
 order += "load"
118
-order += "time"
119
+order += "time local"
120
 
121
 wireless wlan0 {
122
         format_up = "W: (%quality at %essid, %bitrate) %ip"
123
@@ -83,8 +83,8 @@ run_watch VPN {
124
         pidfile = "/var/run/vpnc/pid"
125
 }
126
 
127
-time {
128
-	format = "%Y-%m-%d %H:%M:%S"
129
+time local {
130
+       format = "%Y-%m-%d %H:%M:%S %Z"
131
 }
132
 
133
 load {
134
@@ -258,11 +258,14 @@ Gets the system load (number of processes waiting for CPU time in the last
135
 
136
 === Time
137
 
138
-Formats the current system time. See +strftime(3)+ for the format.
139
+Outputs the current time in the given timezone, or the local timezone
140
+by default. See +strftime(3)+ for details on the format string.
141
 
142
-*Example order*: +time+
143
+*Example order*: +time local+
144
 
145
-*Example format*: +%Y-%m-%d %H:%M:%S+
146
+*Example format*: +%Y-%m-%d %H:%M:%S %Z+
147
+
148
+*Example timezone*: +America/Los_Angeles+
149
 
150
 === DDate
151
 

b/src/print_ddate.c

156
@@ -204,11 +204,13 @@ struct disc_time *get_ddate(struct tm *current_tm) {
157
         return &dt;
158
 }
159
 
160
-void print_ddate(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm) {
161
+void print_ddate(yajl_gen json_gen, char *buffer, const char *format, time_t t) {
162
         char *outwalk = buffer;
163
         static char *form = NULL;
164
+        struct tm current_tm;
165
         struct disc_time *dt;
166
-        if ((dt = get_ddate(current_tm)) == NULL)
167
+        localtime_r(&t, &current_tm);
168
+        if ((dt = get_ddate(&current_tm)) == NULL)
169
                 return;
170
         if (form == NULL)
171
                 if ((form = malloc(strlen(format) + 1)) == NULL)

b/src/print_time.c

176
@@ -7,12 +7,27 @@
177
 
178
 #include "i3status.h"
179
 
180
-void print_time(yajl_gen json_gen, char *buffer, const char *format, struct tm *current_tm) {
181
+void print_time(yajl_gen json_gen, char *buffer, const char *format, const char *timezone, time_t t) {
182
         char *outwalk = buffer;
183
-        if (current_tm == NULL)
184
-                return;
185
-        /* Get date & time */
186
-        outwalk += strftime(outwalk, 4095, format, current_tm);
187
+        struct tm tm;
188
+        if (timezone[0] == '\0') {
189
+                /* No timezone specified, let libc figure out local time. */
190
+                tzset();
191
+                localtime_r(&t, &tm);
192
+        } else {
193
+                /* Set TZ, calculate tm, restore TZ. */
194
+                char *old_tz = getenv("TZ");
195
+                setenv("TZ", timezone, 1);
196
+                tzset();
197
+                localtime_r(&t, &tm);
198
+                if (old_tz == NULL) {
199
+                        unsetenv("TZ");
200
+                } else {
201
+                        setenv("TZ", old_tz, 1);
202
+                }
203
+        }
204
+        /* Format output. */
205
+        outwalk += strftime(outwalk, 4095, format, &tm);
206
         *outwalk = '\0';
207
         OUTPUT_FULL_TEXT(buffer);
208
 }