fix(user/bkdatev):Make compatible with Bash 3.2.57
[BK-2020-03.git] / user / bkdatev
... / ...
CommitLineData
1#!/usr/bin/env bash
2# Desc: Baltakatei's verbose date command
3# Usage: bkdatev [args]
4# Example: bkdatev --date="2001-09-11T09:02:59-04"
5# Version: 0.3.1
6# Ref/Attrib: [1] "ISO 8601". Wikipedia. https://en.wikipedia.org/wiki/ISO_8601
7# [2] "Changing the Locale in Wine" https://stackoverflow.com/a/16428951
8# [3] "Shanghai vs Beijing" https://bugs.launchpad.net/ubuntu/+source/libgweather/+bug/228554
9# Notes: * Check `ls -R /usr/share/zoneinfo` for time zone names.
10# * Check `cat /usr/share/i18n/SUPPORTED` for supported locales.
11# * For list of valid locales, see: https://manpages.ubuntu.com/manpages/bionic/man3/DateTime::Locale::Catalog.3pm.html
12# * Locations chosen for population, personal signifiance, and spatial coverage.
13# * For International Atomic Time (TAI), use offsets from UTC provided in `/usr/share/zoneinfo/leap-seconds.list`.
14
15yell() { echo "$0: $*" >&2; }
16die() { yell "$*"; exit 111; }
17must() { "$@" || die "cannot $*"; }
18insertStr() {
19 # Desc: Inserts a string into another string at a specified position.
20 # Input: arg1: str str_rec String to receive insertion
21 # arg2: int pos Insertion position (0 = append to front)
22 # arg3: str str_ins String to be inserted
23 # Output: stdout: Combined string
24 # Version: 0.0.2
25 # Depends: BK-2020-03: yell(), die(), must()
26 # Ref/Attrib: * BK-2020-03: https://gitlab.com/baltakatei/baltakatei-exdev/
27 # * Cooper, Mendel. “Advanced Bash-Scripting Guide: Manipulating Strings”. tldp.org https://tldp.org/LDP/abs/html/string-manipulation.html
28
29 local str_rec pos str_ins re len_str_rec;
30 local pfx_pos_start pfx_len pfx;
31 local sfx_pos_start sfx_len sfx;
32
33 # Check args
34 if [[ $# -ne 3 ]]; then
35 yell "ERROR:Invalid argument count:$#";
36 return 1; fi;
37 re='^[0-9]+$';
38 if [[ ! "$2" =~ $re ]]; then
39 yell "ERROR:Not an int:$2";
40 return 1; fi;
41 str_rec="$1";
42 pos="$2";
43 str_ins="$3";
44
45 # Calculate string stats
46 len_str_rec="${#str_rec}";
47
48 # Form prefix
49 pfx_pos_start="0";
50 pfx_len="$pos";
51 pfx="${str_rec:$pfx_pos_start:$pfx_len}";
52
53 # Form suffix
54 sfx_pos_start="$(( pos ))";
55 sfx_len="$(( len_str_rec - pos ))";
56 sfx="${str_rec:$sfx_pos_start:$sfx_len}";
57
58 # Print output to stdout
59 printf "%s%s%s\n" "$pfx" "$str_ins" "$sfx";
60}; # Insert string provided at indicated position via stdout
61line_sep() {
62 # Input: var: n_ln
63 local skip_every=4;
64 ((n_ln++));
65 if ! ((n_ln % "$skip_every")); then
66 printf "\n";
67 fi;
68 return 0;
69}; # periodically print separating blank line
70get_tz_offset() {
71 # Desc: Get from 'date' the timezone UTC offset in a way
72 # compatible with both GNU Coreutils and BSD versions.
73 # Input: env var: TZ (time zone for date; e.g. 'America/Denver')
74 # Depends: date (GNU Coreutils 8.32 or BSD), rev
75 local ntz ntz ntz_out;
76 local last2;
77
78 # Get numeric time zone string in way compatible with GNU Coreutils and BSD
79 ntz="$(date "+%z")"; # e.g. "+0530"
80
81 # Check if last two characters are trailing zeros that can be removed.
82 last2="${ntz:3:2}"; # assumes $ntz is 5 characters (i.e. "±HHMM")
83 #last2="$(rev <<< $ntz)" && last2="${last2:0:2}" && last2="$(rev <<< "$last2")";
84 if [[ "$last2" == "00" ]]; then
85 ## ntz_out is truncated by 2 characters
86 len_ntz="${#ntz}";
87 len_ntz_out="$(( len_ntz - 2 ))";
88 ntz_out=""${ntz:0:$len_ntz_out};
89 else
90 ## ntz_out is ntz with semicolon inserted after HH
91 ntz_out="$(insertStr "$ntz" 3 ":" )";
92 fi;
93
94 # Output via stdout
95 printf "%s" "$ntz_out";
96}; # Format numeric time zone (for BSD date compatibility)
97print_dateline() {
98 # Input: var: $id
99 # var: $fs_1
100 # var: $fs_2
101 # var: $fs_3
102 # args: $@
103 # env var: TZ (time zone for date; e.g. 'America/Denver')
104 # Output: stdout
105 # Depends: printf, date
106 # get_tz_offset()
107 # Ref/Attrib: * Truncate string in printf https://stackoverflow.com/a/46812677
108 local s_1 s_2 s_2_tz s_3 s_4;
109
110 s_1="$id";
111 s_2="$(date "$@" "$fs_1")"; # ISO-8601 without numeric timezone
112 s_3="$(date "$@" "$fs_2")"; # Alternate ISO-8601 expressions
113 s_4="$(date "$@" "$fs_3")"; # locale-specific date strings
114
115 # Append numeric timezone to $s_2 with appropriate format
116 # (e.g. '-07' for 'Arizona', '+05:45' for 'Asia/Kathmandu')
117 s_2_tz="$(get_tz_offset)";
118 s_2="$( printf "%s%s" "$s_2" "$s_2_tz" )";
119
120 printf "%-10.10s %-25.25s (%-20.20s) (%s)" "$s_1" "$s_2" "$s_3" "$s_4";
121 printf "\n";
122
123 unset fs_1 fs_2 fs_3 fs_4;
124 }; # print line of dates
125main() {
126 n_ln=0; # for line_sep()
127 unset LC_TIME; # Fall back to time zone-specific locale settings.
128
129 # format strings
130 fs_iso8601="+%Y-%m-%dT%H:%M:%S"; # typical ISO-8601 without timezone
131 fs_iso8601_etc="+%G-W%V-%u, %Y-%j"; # alternate ISO-8601 dates
132 fs_locale="+%Z; %A; %c"; # locale-specific date strings
133
134 # vars for print_dateline()
135 fs_1="$fs_iso8601";
136 fs_2="$fs_iso8601_etc";
137 fs_3="$fs_locale";
138
139 # UTC (pop. (2021): 7,837,000,000)
140 (
141 export TZ=UTC;
142 id="UTC";
143 fs_3="+%s seconds since 1970-01-01T00:00+00";
144 print_dateline "$@";
145 ); line_sep;
146
147 # Hawaii
148 (
149 export TZ=US/Hawaii;
150 export LANG="haw-US.UTF8";
151 id="HAWAII";
152 print_dateline "$@";
153 ); line_sep;
154
155 # Los Angeles, USA
156 (
157 export TZ=America/Los_Angeles;
158 export LANG="en_US.UTF-8";
159 id="LOS ANGELES";
160 print_dateline "$@";
161 ); line_sep;
162
163 # Denver, USA (pop. (2021): 711,463)
164 (
165 export TZ=America/Denver;
166 export LANG="en_US.UTF-8";
167 id="DENVER";
168 print_dateline "$@";
169 ); line_sep;
170
171 # Chicago, USA (pop. (2021): 711,463)
172 (
173 export TZ=America/Chicago;
174 export LANG="en_US.UTF-8";
175 id="CHICAGO";
176 print_dateline "$@";
177 ); line_sep;
178
179 # Mexico City, Mexico (pop. (2018): 21,804,515)
180 (
181 export TZ=America/Mexico_City;
182 export LANG="es_MX.UTF8";
183 id="MEXICO CITY";
184 print_dateline "$@";
185 ); line_sep;
186
187 # Panama City, Panama
188 (
189 export TZ=America/Panama;
190 export LANG="es_PA.UTF8";
191 id="PANAMA CITY";
192 print_dateline "$@";
193 ); line_sep;
194
195 # New York, USA (pop. (2018): 20,140,470)
196 (
197 export TZ=America/New_York;
198 export LANG="en_US.UTF-8";
199 id="NEW YORK";
200 print_dateline "$@";
201 ); line_sep;
202
203 # São Paulo, Brazil
204 (
205 export TZ=America/Sao_Paulo;
206 export LANG="pt_BR.UTF8";
207 id="SAO PAULO";
208 print_dateline "$@";
209 ); line_sep;
210
211 # Buenos Aires
212 (
213 export TZ=America/Argentina/Buenos_Aires;
214 export LANG="es_AR.UTF8";
215 id="BUENOS AIRES";
216 print_dateline "$@";
217 ); line_sep;
218
219 # London, England
220 (
221 export TZ=Europe/London;
222 export LANG="en_GB.UTF-8";
223 id="LONDON";
224 print_dateline "$@";
225 ); line_sep;
226
227 # Kinshasa, Africa
228 (
229 export TZ=Africa/Kinshasa;
230 export LANG="ln_CD.UTF8";
231 id="KINSHASA";
232 print_dateline "$@";
233 ); line_sep;
234
235 # Lagos, Africa
236 (
237 export TZ=Africa/Lagos;
238 export LANG="en_NG.UTF8";
239 id="LAGOS";
240 print_dateline "$@";
241 ); line_sep;
242
243 # Paris, France
244 (
245 export TZ=Europe/Paris;
246 export LANG="fr_FR.UTF8";
247 id="PARIS";
248 print_dateline "$@";
249 ); line_sep;
250
251 # Stockholm, Sweden
252 (
253 export TZ=Europe/Stockholm;
254 export LANG="sv_SE.UTF8";
255 id="STOCKHOLM";
256 print_dateline "$@";
257 ); line_sep;
258
259 # Cairo, Egypt
260 (
261 export TZ=Africa/Cairo;
262 export LANG="ar_EG.UTF8";
263 id="CAIRO";
264 print_dateline "$@";
265 ); line_sep;
266
267 # Athens (pop. (2020): 3,526,887)
268 (
269 export TZ=Europe/Athens;
270 export LANG="el_GR.UTF8";
271 id="ATHENS";
272 print_dateline "$@";
273 ); line_sep;
274
275 # Istanbul (pop. (2020): 13,719,061)
276 (
277 export TZ=Asia/Istanbul;
278 export LANG="tr_TR.UTF8";
279 id="ISTANBUL";
280 print_dateline "$@";
281 ); line_sep;
282
283 # Tehran, Iran
284 (
285 export TZ=Asia/Tehran;
286 export LANG="fa_IR.UTF8";
287 id="TEHRAN";
288 print_dateline "$@";
289 ); line_sep;
290
291 # Moscow, Russia
292 (
293 export TZ=Europe/Moscow;
294 export LANG="ru_RU.UTF-8";
295 id="MOSCOW";
296 print_dateline "$@";
297 ); line_sep;
298
299 # Kyiv, Ukraine (pop. (2021): 2,962,180)
300 (
301 export TZ=Europe/Kyiv;
302 export LANG="uk_UA.UTF-8";
303 id="KYIV";
304 print_dateline "$@";
305 ); line_sep;
306
307 # Delhi, India (pop. (2018): 29,000,000)
308 (
309 export TZ=Asia/Kolkata;
310 export LANG="hi_IN.UTF-8";
311 id="DELHI";
312 print_dateline "$@";
313 ); line_sep;
314
315 # Jakarta, Indonesia (pop. (2018): 33,430,285)
316 (
317 export TZ=Asia/Jakarta;
318 export LANG="id_ID.UTF8";
319 id="JAKARTA";
320 print_dateline "$@";
321 ); line_sep;
322
323 # Singapore, Singapore (pop (2018): 5,792,000)
324 (
325 export TZ=Asia/Singapore;
326 export LANG="en_SG.UTF-8";
327 id="SINGAPORE";
328 print_dateline "$@";
329 ); line_sep;
330
331 # Beijing, China (pop. (2018): 19,618,000)
332 (
333 export TZ=Asia/Shanghai; # [3]
334 export LANG="zh_CN.UTF-8";
335 id="BEIJING";
336 print_dateline "$@";
337 ); line_sep;
338
339 # Taipei, Taiwan (pop (2019): 7,034,084)
340 (
341 export TZ=Asia/Taipei; # [3]
342 export LANG="zh_TW.UTF-8";
343 id="TAIPEI";
344 print_dateline "$@";
345 ); line_sep;
346
347 # Tokyo, Japan (pop. (2018): 37,274,000)
348 (
349 export TZ=Asia/Tokyo;
350 export LANG="ja_JP.UTF8";
351 id="TOKYO";
352 print_dateline "$@";
353 ); line_sep;
354
355 # Seoul, South Korea (pop. (2018): 25,514,000)
356 (
357 export TZ=Asia/Seoul;
358 export LANG="ko_KR.UTF8";
359 id="SEOUL";
360 print_dateline "$@";
361 ); line_sep;
362
363 # Pyongyang, North Korea
364 (
365 export TZ=Asia/Pyongyang;
366 export LANG="ko_KP.UTF8";
367 id="PYONGYANG";
368 print_dateline "$@";
369 ); line_sep;
370
371 # Sydney, Australia
372 (
373 export TZ=Australia/Sydney;
374 export LANG="en_AU.UTF8";
375 id="SYDNEY";
376 print_dateline "$@";
377 ); line_sep;
378
379 # Guam
380 (
381 export TZ=Pacific/Guam;
382 export LANG="en_GU.UTF8";
383 id="GUAM";
384 print_dateline "$@";
385 ); line_sep;
386
387 # Auckland, New Zealand
388 (
389 export TZ=Pacific/Auckland;
390 export LANG="en_NZ.UTF8";
391 id="AUCKLAND";
392 print_dateline "$@";
393 ); line_sep;
394
395 return 0;
396}; # main program
397
398main "$@";
399
400# Author: Steven Baltakatei Sandoval
401# License: GPLv3+