style(unitproc):timeDuration:Changed variable names
[BK-2020-03.git] / unitproc / bktemp-timeDuration
1 #!/bin/bash
2
3 # Desc: Template to indicate time duration in ISO-8601 format
4
5 yell() { echo "$0: $*" >&2; } # Yell, Die, Try Three-Fingered Claw technique; # Ref/Attrib: https://stackoverflow.com/a/25515370
6 die() { yell "$*"; exit 111; }
7 try() { "$@" || die "cannot $*"; }
8 timeDuration(){
9 # Desc: Given seconds, output ISO-8601 duration string
10 # Ref/Attrib: ISO-8601:2004(E), §4.4.4.2 Representations of time intervals by duration and context information
11 # Note: "1 month" ("P1M") is assumed to be "30 days" (see ISO-8601:2004(E), §2.2.1.2)
12 # Usage: timeDuration [1:seconds] ([2:precision])
13 # Version: 1.0.2
14 # Input: arg1: seconds as base 10 integer >= 0 (ex: 3601)
15 # arg2: precision level (optional; default=2)
16 # Output: stdout: ISO-8601 duration string (ex: "P1H1S", "P2Y10M15DT10H30M20S")
17 # exit code 0: success
18 # exit code 1: error_input
19 # Example: 'timeDuration 111111 3' yields 'P1DT6H51M'
20 # Depends: date 8 (gnucoreutils), yell,
21 local returnState argSeconds argPrecision remainder precision witherPrecision
22 local fullYears fullMonths fullDays fullHours fullMinutes fullSeconds
23 local displayYears displayMonths displayDays displayHours displayMinutes displaySeconds
24 local hasYears hasMonths hasDays hasHours hasMinutes hasSeconds
25
26 argSeconds="$1"; # read arg1 (seconds)
27 argPrecision="$2"; # read arg2 (precision)
28 precision=2; # set default precision
29
30 # Check that between one and two arguments is supplied
31 if ! { [[ $# -ge 1 ]] && [[ $# -le 2 ]]; }; then
32 yell "ERROR:Invalid number of arguments:$# . Exiting.";
33 returnState="error_input"; fi
34
35 # Check that argSeconds provided
36 if [[ $# -ge 1 ]]; then
37 ## Check that argSeconds is a positive integer
38 if [[ "$argSeconds" =~ ^[[:digit:]]+$ ]]; then
39 :
40 else
41 yell "ERROR:argSeconds not a digit.";
42 returnState="error_input";
43 fi
44 else
45 yell "ERROR:No argument provided. Exiting.";
46 exit 1;
47 fi
48
49 # Consider whether argPrecision was provided
50 if [[ $# -eq 2 ]]; then
51 # Check that argPrecision is a positive integer
52 if [[ "$argPrecision" =~ ^[[:digit:]]+$ ]] && [[ "$argPrecision" -gt 0 ]]; then
53 precision="$argPrecision";
54 else
55 yell "ERROR:argPrecision not a positive integer. (is $argPrecision ). Leaving early.";
56 returnState="error_input";
57 fi;
58 else
59 :
60 fi;
61
62 remainder="$argSeconds" ; # seconds
63 ## Calculate full years Y, update remainder
64 fullYears=$(( remainder / (365*24*60*60) ));
65 remainder=$(( remainder - (fullYears*365*24*60*60) ));
66 ## Calculate full months M, update remainder
67 fullMonths=$(( remainder / (30*24*60*60) ));
68 remainder=$(( remainder - (fullMonths*30*24*60*60) ));
69 ## Calculate full days D, update remainder
70 fullDays=$(( remainder / (24*60*60) ));
71 remainder=$(( remainder - (fullDays*24*60*60) ));
72 ## Calculate full hours H, update remainder
73 fullHours=$(( remainder / (60*60) ));
74 remainder=$(( remainder - (fullHours*60*60) ));
75 ## Calculate full minutes M, update remainder
76 fullMinutes=$(( remainder / (60) ));
77 remainder=$(( remainder - (fullMinutes*60) ));
78 ## Calculate full seconds S, update remainder
79 fullSeconds=$(( remainder / (1) ));
80 remainder=$(( remainder - (remainder*1) ));
81 ## Check which fields filled
82 if [[ $fullYears -gt 0 ]]; then hasYears="true"; else hasYears="false"; fi
83 if [[ $fullMonths -gt 0 ]]; then hasMonths="true"; else hasMonths="false"; fi
84 if [[ $fullDays -gt 0 ]]; then hasDays="true"; else hasDays="false"; fi
85 if [[ $fullHours -gt 0 ]]; then hasHours="true"; else hasHours="false"; fi
86 if [[ $fullMinutes -gt 0 ]]; then hasMinutes="true"; else hasMinutes="false"; fi
87 if [[ $fullSeconds -gt 0 ]]; then hasSeconds="true"; else hasSeconds="false"; fi
88
89 ## Determine which fields to display (see ISO-8601:2004 §4.4.3.2)
90 witherPrecision="false"
91
92 ### Years
93 if $hasYears && [[ $precision -gt 0 ]]; then
94 displayYears="true";
95 witherPrecision="true";
96 else
97 displayYears="false";
98 fi;
99 if $witherPrecision; then ((precision--)); fi;
100
101 ### Months
102 if $hasMonths && [[ $precision -gt 0 ]]; then
103 displayMonths="true";
104 witherPrecision="true";
105 else
106 displayMonths="false";
107 fi;
108 if $witherPrecision && [[ $precision -gt 0 ]]; then
109 displayMonths="true";
110 fi;
111 if $witherPrecision; then ((precision--)); fi;
112
113 ### Days
114 if $hasDays && [[ $precision -gt 0 ]]; then
115 displayDays="true";
116 witherPrecision="true";
117 else
118 displayDays="false";
119 fi;
120 if $witherPrecision && [[ $precision -gt 0 ]]; then
121 displayDays="true";
122 fi;
123 if $witherPrecision; then ((precision--)); fi;
124
125 ### Hours
126 if $hasHours && [[ $precision -gt 0 ]]; then
127 displayHours="true";
128 witherPrecision="true";
129 else
130 displayHours="false";
131 fi;
132 if $witherPrecision && [[ $precision -gt 0 ]]; then
133 displayHours="true";
134 fi;
135 if $witherPrecision; then ((precision--)); fi;
136
137 ### Minutes
138 if $hasMinutes && [[ $precision -gt 0 ]]; then
139 displayMinutes="true";
140 witherPrecision="true";
141 else
142 displayMinutes="false";
143 fi;
144 if $witherPrecision && [[ $precision -gt 0 ]]; then
145 displayMinutes="true";
146 fi;
147 if $witherPrecision; then ((precision--)); fi;
148
149 ### Seconds
150
151 if $hasSeconds && [[ $precision -gt 0 ]]; then
152 displaySeconds="true";
153 witherPrecision="true";
154 else
155 displaySeconds="false";
156 fi;
157 if $witherPrecision && [[ $precision -gt 0 ]]; then
158 displaySeconds="true";
159 fi;
160 if $witherPrecision; then ((precision--)); fi;
161
162 ## Determine whether or not the "T" separator is needed to separate date and time elements
163 if ( $displayHours || $displayMinutes || $displaySeconds); then
164 displayDateTime="true"; else displayDateTime="false"; fi
165
166 ## Construct duration output string
167 OUTPUT="P"
168 if $displayYears; then
169 OUTPUT=$OUTPUT$fullYears"Y"; fi
170 if $displayMonths; then
171 OUTPUT=$OUTPUT$fullMonths"M"; fi
172 if $displayDays; then
173 OUTPUT=$OUTPUT$fullDays"D"; fi
174 if $displayDateTime; then
175 OUTPUT=$OUTPUT"T"; fi
176 if $displayHours; then
177 OUTPUT=$OUTPUT$fullHours"H"; fi
178 if $displayMinutes; then
179 OUTPUT=$OUTPUT$fullMinutes"M"; fi
180 if $displaySeconds; then
181 OUTPUT=$OUTPUT$fullSeconds"S"; fi
182
183 ## Output duration string to stdout
184 echo "$OUTPUT" && returnState="true";
185
186 #===Determine function return code===
187 if [ "$returnState" = "true" ]; then
188 return 0;
189 elif [ "$returnState" = "error_input" ]; then
190 yell "ERROR:input";
191 return 1;
192 else
193 yell "ERROR:Unknown";
194 return 2;
195 fi
196
197 } # Get duration (ex: PT10M4S )
198
199 #==BEGIN sample code==
200 echo "Precision 6 duration:$(timeDuration "$(date +%s)" 6)"
201 echo "Precision 5 duration:$(timeDuration "$(date +%s)" 5)"
202 echo "Precision 4 duration:$(timeDuration "$(date +%s)" 4)"
203 echo "Precision 3 duration:$(timeDuration "$(date +%s)" 3)"
204 echo "Precision 2 duration:$(timeDuration "$(date +%s)" 2)"
205 echo "Precision 1 duration:$(timeDuration "$(date +%s)" 1)"
206 echo "Precision 6 duration:$(timeDuration $((60+60*60+60*60*24+60*60*24*30+60*60*24*365 - (60+60*60+60*60*24+60*60*24*30) )) 6)"
207 timeDuration "$@"
208 #==END sample code==
209
210 # Author: Steven Baltakatei Sandoval
211 # License: GPLv3+