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