feat(unitproc):timeEpochNS:Add date-string parsing feature
[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])
17ccc034 13 # Version: 1.0.3
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'
25f31c30 21 # Depends: date 8 (gnucoreutils), yell,
1a6ae9e0 22 local returnState argSeconds argPrecision remainder precision witherPrecision
25f31c30
SBS
23 local fullYears fullMonths fullDays fullHours fullMinutes fullSeconds
24 local displayYears displayMonths displayDays displayHours displayMinutes displaySeconds
25 local hasYears hasMonths hasDays hasHours hasMinutes hasSeconds
26
1a6ae9e0
SBS
27 argSeconds="$1"; # read arg1 (seconds)
28 argPrecision="$2"; # read arg2 (precision)
7ad273d8 29 precision=2; # set default precision
7ad273d8
SBS
30
31 # Check that between one and two arguments is supplied
32 if ! { [[ $# -ge 1 ]] && [[ $# -le 2 ]]; }; then
33 yell "ERROR:Invalid number of arguments:$# . Exiting.";
1a6ae9e0 34 returnState="error_input"; fi
7ad273d8 35
1a6ae9e0 36 # Check that argSeconds provided
7ad273d8 37 if [[ $# -ge 1 ]]; then
1a6ae9e0
SBS
38 ## Check that argSeconds is a positive integer
39 if [[ "$argSeconds" =~ ^[[:digit:]]+$ ]]; then
25ecb96f 40 :
7ad273d8 41 else
1a6ae9e0
SBS
42 yell "ERROR:argSeconds not a digit.";
43 returnState="error_input";
7ad273d8
SBS
44 fi
45 else
46 yell "ERROR:No argument provided. Exiting.";
47 exit 1;
48 fi
49
1a6ae9e0 50 # Consider whether argPrecision was provided
7ad273d8 51 if [[ $# -eq 2 ]]; then
1a6ae9e0
SBS
52 # Check that argPrecision is a positive integer
53 if [[ "$argPrecision" =~ ^[[:digit:]]+$ ]] && [[ "$argPrecision" -gt 0 ]]; then
54 precision="$argPrecision";
7ad273d8 55 else
1a6ae9e0
SBS
56 yell "ERROR:argPrecision not a positive integer. (is $argPrecision ). Leaving early.";
57 returnState="error_input";
7ad273d8
SBS
58 fi;
59 else
25ecb96f 60 :
7ad273d8
SBS
61 fi;
62
1a6ae9e0 63 remainder="$argSeconds" ; # seconds
7ad273d8
SBS
64 ## Calculate full years Y, update remainder
65 fullYears=$(( remainder / (365*24*60*60) ));
66 remainder=$(( remainder - (fullYears*365*24*60*60) ));
7ad273d8
SBS
67 ## Calculate full months M, update remainder
68 fullMonths=$(( remainder / (30*24*60*60) ));
69 remainder=$(( remainder - (fullMonths*30*24*60*60) ));
7ad273d8
SBS
70 ## Calculate full days D, update remainder
71 fullDays=$(( remainder / (24*60*60) ));
72 remainder=$(( remainder - (fullDays*24*60*60) ));
7ad273d8
SBS
73 ## Calculate full hours H, update remainder
74 fullHours=$(( remainder / (60*60) ));
75 remainder=$(( remainder - (fullHours*60*60) ));
7ad273d8
SBS
76 ## Calculate full minutes M, update remainder
77 fullMinutes=$(( remainder / (60) ));
78 remainder=$(( remainder - (fullMinutes*60) ));
7ad273d8
SBS
79 ## Calculate full seconds S, update remainder
80 fullSeconds=$(( remainder / (1) ));
81 remainder=$(( remainder - (remainder*1) ));
7ad273d8
SBS
82 ## Check which fields filled
83 if [[ $fullYears -gt 0 ]]; then hasYears="true"; else hasYears="false"; fi
84 if [[ $fullMonths -gt 0 ]]; then hasMonths="true"; else hasMonths="false"; fi
85 if [[ $fullDays -gt 0 ]]; then hasDays="true"; else hasDays="false"; fi
86 if [[ $fullHours -gt 0 ]]; then hasHours="true"; else hasHours="false"; fi
87 if [[ $fullMinutes -gt 0 ]]; then hasMinutes="true"; else hasMinutes="false"; fi
88 if [[ $fullSeconds -gt 0 ]]; then hasSeconds="true"; else hasSeconds="false"; fi
89
90 ## Determine which fields to display (see ISO-8601:2004 §4.4.3.2)
91 witherPrecision="false"
92
93 ### Years
94 if $hasYears && [[ $precision -gt 0 ]]; then
95 displayYears="true";
96 witherPrecision="true";
97 else
98 displayYears="false";
99 fi;
100 if $witherPrecision; then ((precision--)); fi;
101
102 ### Months
103 if $hasMonths && [[ $precision -gt 0 ]]; then
104 displayMonths="true";
105 witherPrecision="true";
106 else
107 displayMonths="false";
108 fi;
109 if $witherPrecision && [[ $precision -gt 0 ]]; then
110 displayMonths="true";
111 fi;
112 if $witherPrecision; then ((precision--)); fi;
113
114 ### Days
115 if $hasDays && [[ $precision -gt 0 ]]; then
116 displayDays="true";
117 witherPrecision="true";
118 else
119 displayDays="false";
120 fi;
121 if $witherPrecision && [[ $precision -gt 0 ]]; then
122 displayDays="true";
123 fi;
124 if $witherPrecision; then ((precision--)); fi;
125
126 ### Hours
127 if $hasHours && [[ $precision -gt 0 ]]; then
128 displayHours="true";
129 witherPrecision="true";
130 else
131 displayHours="false";
132 fi;
133 if $witherPrecision && [[ $precision -gt 0 ]]; then
134 displayHours="true";
135 fi;
136 if $witherPrecision; then ((precision--)); fi;
137
138 ### Minutes
139 if $hasMinutes && [[ $precision -gt 0 ]]; then
140 displayMinutes="true";
141 witherPrecision="true";
142 else
143 displayMinutes="false";
144 fi;
145 if $witherPrecision && [[ $precision -gt 0 ]]; then
146 displayMinutes="true";
147 fi;
148 if $witherPrecision; then ((precision--)); fi;
149
150 ### Seconds
151
152 if $hasSeconds && [[ $precision -gt 0 ]]; then
153 displaySeconds="true";
154 witherPrecision="true";
155 else
156 displaySeconds="false";
157 fi;
158 if $witherPrecision && [[ $precision -gt 0 ]]; then
159 displaySeconds="true";
160 fi;
161 if $witherPrecision; then ((precision--)); fi;
162
7ad273d8 163 ## Determine whether or not the "T" separator is needed to separate date and time elements
7ad273d8
SBS
164 if ( $displayHours || $displayMinutes || $displaySeconds); then
165 displayDateTime="true"; else displayDateTime="false"; fi
166
167 ## Construct duration output string
168 OUTPUT="P"
169 if $displayYears; then
170 OUTPUT=$OUTPUT$fullYears"Y"; fi
171 if $displayMonths; then
172 OUTPUT=$OUTPUT$fullMonths"M"; fi
173 if $displayDays; then
174 OUTPUT=$OUTPUT$fullDays"D"; fi
175 if $displayDateTime; then
176 OUTPUT=$OUTPUT"T"; fi
177 if $displayHours; then
178 OUTPUT=$OUTPUT$fullHours"H"; fi
179 if $displayMinutes; then
180 OUTPUT=$OUTPUT$fullMinutes"M"; fi
181 if $displaySeconds; then
182 OUTPUT=$OUTPUT$fullSeconds"S"; fi
183
184 ## Output duration string to stdout
1a6ae9e0 185 echo "$OUTPUT" && returnState="true";
7ad273d8
SBS
186
187 #===Determine function return code===
188 if [ "$returnState" = "true" ]; then
189 return 0;
1a6ae9e0
SBS
190 elif [ "$returnState" = "error_input" ]; then
191 yell "ERROR:input";
7ad273d8 192 return 1;
1a6ae9e0
SBS
193 else
194 yell "ERROR:Unknown";
195 return 2;
7ad273d8
SBS
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+