style(unitproc):timeUntilNextDay: lowercase returnStates; version
[BK-2020-03.git] / unitproc / bktemp-timeDuration
... / ...
CommitLineData
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(){
9 # Desc: Output approximate time duration string before given time (default:current date)
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 [arg1] ([arg2])
13 # Version: 1.0.0
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 # Example: 'timeDuration 111111 3' yields 'P1DT6H51M'
18 # Depends: date 8 (gnucoreutils), yell,
19 local returnState ARG1 ARG2 arg1Valid arg2Valid remainder precision witherPrecision
20 local fullYears fullMonths fullDays fullHours fullMinutes fullSeconds
21 local displayYears displayMonths displayDays displayHours displayMinutes displaySeconds
22 local hasYears hasMonths hasDays hasHours hasMinutes hasSeconds
23
24 ARG1="$1";
25 ARG2="$2";
26 precision=2; # set default precision
27 returnState="true"; # set default return state
28
29 # Check that between one and two arguments is supplied
30 if ! { [[ $# -ge 1 ]] && [[ $# -le 2 ]]; }; then
31 yell "ERROR:Invalid number of arguments:$# . Exiting.";
32 returnState="ERROR_INPUT"; fi
33
34 # Check that arg1 provided
35 if [[ $# -ge 1 ]]; then
36 # Check that arg1 is a positive integer
37 if [[ "$ARG1" =~ ^[[:digit:]]+$ ]]; then
38 arg1Valid="true";
39 else
40 yell "ERROR:ARG1 not a digit.";
41 returnState="ERROR_INPUT";
42 arg1Valid="false";
43 fi
44 else
45 yell "ERROR:No argument provided. Exiting.";
46 exit 1;
47 fi
48
49 # Consider whether arg2 was provided
50 if [[ $# -eq 2 ]]; then
51 # Check that the second arg is a positive integer
52 if [[ "$ARG2" =~ ^[[:digit:]]+$ ]] && [[ "$ARG2" -gt 0 ]]; then
53 arg2Valid="true";
54 precision="$ARG2";
55 else
56 yell "ERROR:ARG2 not a positive integer. (is $ARG2 ). Leaving early.";
57 returnState="ERROR_INPUT";
58 arg2Valid="false";
59 fi;
60 else
61 arg2Valid="false";
62 fi;
63
64 remainder="$ARG1" ; # seconds
65 ## Calculate full years Y, update remainder
66 fullYears=$(( remainder / (365*24*60*60) ));
67 remainder=$(( remainder - (fullYears*365*24*60*60) ));
68 ## Calculate full months M, update remainder
69 fullMonths=$(( remainder / (30*24*60*60) ));
70 remainder=$(( remainder - (fullMonths*30*24*60*60) ));
71 ## Calculate full days D, update remainder
72 fullDays=$(( remainder / (24*60*60) ));
73 remainder=$(( remainder - (fullDays*24*60*60) ));
74 ## Calculate full hours H, update remainder
75 fullHours=$(( remainder / (60*60) ));
76 remainder=$(( remainder - (fullHours*60*60) ));
77 ## Calculate full minutes M, update remainder
78 fullMinutes=$(( remainder / (60) ));
79 remainder=$(( remainder - (fullMinutes*60) ));
80 ## Calculate full seconds S, update remainder
81 fullSeconds=$(( remainder / (1) ));
82 remainder=$(( remainder - (remainder*1) ));
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
89 if [[ $fullSeconds -gt 0 ]]; then hasSeconds="true"; else hasSeconds="false"; fi
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
164
165
166 ## Determine whether or not the "T" separator is needed to separate date and time elements
167 if ( $displayHours || $displayMinutes || $displaySeconds); then
168 displayDateTime="true"; else displayDateTime="false"; fi
169
170 ## Construct duration output string
171 OUTPUT="P"
172 if $displayYears; then
173 OUTPUT=$OUTPUT$fullYears"Y"; fi
174 if $displayMonths; then
175 OUTPUT=$OUTPUT$fullMonths"M"; fi
176 if $displayDays; then
177 OUTPUT=$OUTPUT$fullDays"D"; fi
178 if $displayDateTime; then
179 OUTPUT=$OUTPUT"T"; fi
180 if $displayHours; then
181 OUTPUT=$OUTPUT$fullHours"H"; fi
182 if $displayMinutes; then
183 OUTPUT=$OUTPUT$fullMinutes"M"; fi
184 if $displaySeconds; then
185 OUTPUT=$OUTPUT$fullSeconds"S"; fi
186
187 ## Output duration string to stdout
188 if [[ "$returnState" = "true" ]]; then echo "$OUTPUT"; fi
189
190 #===Determine function return code===
191 if [ "$returnState" = "true" ]; then
192 return 0;
193 else
194 echo "$returnState" 1>&2;
195 return 1;
196 fi
197
198} # Get duration (ex: PT10M4S )
199
200#==BEGIN sample code==
201echo "Precision 6 duration:$(timeDuration "$(date +%s)" 6)"
202echo "Precision 5 duration:$(timeDuration "$(date +%s)" 5)"
203echo "Precision 4 duration:$(timeDuration "$(date +%s)" 4)"
204echo "Precision 3 duration:$(timeDuration "$(date +%s)" 3)"
205echo "Precision 2 duration:$(timeDuration "$(date +%s)" 2)"
206echo "Precision 1 duration:$(timeDuration "$(date +%s)" 1)"
207echo "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)"
208timeDuration "$@"
209#==END sample code==
210
211# Author: Steven Baltakatei Sandoval
212# License: GPLv3+