fix(user/bkdatev):Unset LC_TIME so date can use locale-specific %c
[BK-2020-03.git] / user / bk_this-date-in-recent-years.sh
1 #!/usr/bin/env bash
2 # Desc: Prints days
3 # Depends: date (GNU Coreutils 8.32)
4 # Version: 0.0.1
5 # Ref/Attrib: [1] Template:This date in recent years https://en.wikipedia.org/wiki/Template:This_date_in_recent_years
6 # [2] Removing leading zeros before passing a shell variable to another command https://stackoverflow.com/a/11130324
7
8 declare -g yearRange; # range of years to consider
9
10 yell() { echo "$0: $*" >&2; } #o Yell, Die, Try Three-Fingered Claw technique
11 die() { yell "$*"; exit 111; } #o Ref/Attrib: https://stackoverflow.com/a/25515370
12 try() { "$@" || die "cannot $*"; } #o
13 vbm() {
14 # Description: Prints verbose message ("vbm") to stderr if opVerbose is set to "true".
15 # Usage: vbm "DEBUG :verbose message here"
16 # Version 0.2.0
17 # Input: arg1: string
18 # vars: opVerbose
19 # Output: stderr
20 # Depends: bash 5.1.16, GNU-coreutils 8.30 (echo, date)
21
22 if [ "$opVerbose" = "true" ]; then
23 functionTime="$(date --iso-8601=ns)"; # Save current time in nano seconds.
24 echo "[$functionTime]:$0:""$*" 1>&2; # Display argument text.
25 fi
26
27 # End function
28 return 0; # Function finished.
29 } # Displays message if opVerbose true
30 showUsage() {
31 # Desc: Display script usage information
32 # Usage: showUsage
33 # Version 0.0.2
34 # Input: none
35 # Output: stdout
36 # Depends: GNU-coreutils 8.30 (cat)
37 cat <<'EOF'
38 USAGE:
39 bk_this-date-in-recent-years.sh [ options ] [str day of month]
40
41 OPTIONS:
42 -h, --help
43 Display help information.
44 --version
45 Display script version.
46 -v, --verbose
47 Display debugging info.
48 -r, --iso-range
49 Specify year range (iso-8601 period), e.g.
50 "2010/2020". By default, most recent 10
51 years are considered.
52 --
53 Indicate end of options.
54
55 EXAMPLE:
56 bk_this_date-in-recent-years.sh "05-11"
57 bk_this_date-in-recent-years.sh -r "1990/2020" "05-11"
58 bk_this_date-in-recent-years.sh -r "1990/2020" -- "05-11"
59 EOF
60 } # Display information on how to use this script.
61 processArgs() {
62 # Desc: Processes arguments provided to script.
63 # Usage: processArgs "$@"
64 # Version: 1.0.0
65 # Input: "$@" (list of arguments provided to the function)
66 # yearRange Iso date range to consider (e.g. "1999/2020").
67 # Output: Sets following variables used by other functions:
68 # opVerbose Indicates verbose mode enable status. (ex: "true", "false")
69 # opIsoRange Indicates that an iso-8601 date range is specified. (ex: "true", "false")
70 # yearRange Iso date range to consider (e.g. "1999/2020").
71 # arrayPosArgs Array of remaining positional argments
72 # Depends:
73 # yell() Displays messages to stderr.
74 # vbm() Displays messsages to stderr if opVerbose set to "true".
75 # showUsage() Displays usage information about parent script.
76 # showVersion() Displays version about parent script.
77 # arrayPosArgs Global array for storing non-option positional arguments (i.e. arguments following the `--` option).
78 # External dependencies: bash (5.1.16), echo
79 # Ref./Attrib.:
80 # [1]: Marco Aurelio (2014-05-08). "echo that outputs to stderr". https://stackoverflow.com/a/23550347
81 # [2]: "Handling positional parameters" (2018-05-12). https://wiki.bash-hackers.org/scripting/posparams
82
83 # Initialize function
84 vbm "DEBUG:processArgs function called."
85
86 # Perform work
87 while [ ! $# -eq 0 ]; do # While number of arguments ($#) is not (!) equal to (-eq) zero (0).
88 #yell "DEBUG:Starting processArgs while loop." # Debug stderr message. See [1].
89 #yell "DEBUG:Provided arguments are:""$*" # Debug stderr message. See [1].
90 case "$1" in
91 -h | --help) showUsage; exit 1;; # Display usage.
92 --version) showVersion; exit 1;; # Show version
93 -v | --verbose) opVerbose="true"; vbm "DEBUG:Verbose mode enabled.";; # Enable verbose mode. See [1].
94 -r | --iso-range)
95 opIsoRange="true"; vbm "DEBUG:Accepting iso-8601 year range."; # Accept iso-8601 year range.
96 shift;
97 yearRange="$1";;
98 --) # End of all options. See [2].
99 shift;
100 for arg in "$@"; do
101 vbm "DEBUG:adding to arrayPosArgs:$arg";
102 arrayPosArgs+=("$arg");
103 done;
104 break;;
105 -*) showUsage; yell "ERROR: Unrecognized option."; exit 1;; # Display usage
106 *) for arg in "$@"; do
107 vbm "DEBUG:adding to arrayPosArgs:$arg";
108 arrayPosArgs+=("$arg");
109 done;
110 break;;
111 esac
112 shift
113 done
114
115 # End function
116 vbm "DEBUG:processArgs function ended."
117 return 0; # Function finished.
118 } # Evaluate script options from positional arguments (ex: $1, $2, $3, etc.).
119 validatePosArgs() {
120 # Input: arrayPosArgs array with positional arguments
121 # opVerbose bool indicates to vbm() to display verbose text
122 # opIsoRange bool indicates to use a user-provided year range
123 # yearRange str iso-8601 year range provided by -r, --iso-range option
124
125 # Validate year $range
126 re='^[0-9]+/[0-9]+$'; # Simply check (int)/(int). Don't address Gregorian Calendar here.
127 if [[ $opIsoRange == "true" && ! "$yearRange" =~ $re ]] ; then
128 showUsage;
129 yell "ERROR:Not a valid date range (e.g. 2010/2022):$yearRange";
130 return 1;
131 fi;
132 return 0;
133 }; # Validate arguments
134 main() {
135 # Input: arrayPosArgs array with positional arguments
136 # opVerbose bool indicates to vbm() to display verbose text
137 # opIsoRange bool indicates to use a user-provided year range
138 # yearRange str iso-8601 year range provided by -r, --iso-range option
139 # Output: stdout: dates with days of the week (newline delimited)
140 # Depends: date (GNU Coreutils 8.32)
141 # Depends: processArgs(), yell(), vbm(), showUsage(), showVersion(), validatePosArgs()
142 local dom yc ymin ymax;
143
144 # Check input
145 processArgs "$@";
146 if ! validatePosArgs; then
147 die "FATAL:Invalid positional arguments:$(declare -p arrayPosArgs)";
148 fi;
149
150 # Define year range
151 if [[ ! $opIsoRange == "true" ]]; then
152 ## Default: Most recent 10 years
153 yc="10"; # count of years to consider
154 ymax="$(date +%Y)"; # highest year to consider
155 ymin="$((ymax - yc))"; # earliest year to consider
156 else
157 ## Provided via -r,--iso-range option
158 ymin="$(echo "$yearRange" | cut -d'/' -f1)";
159 ymin="$((10#$ymin))"; # strip leading zeroes. See [2]
160 ymax="$(echo "$yearRange" | cut -d'/' -f2)"; # See [2]
161 ymax="$((10#$ymax))"; # strip leading zeroes. See [2]
162 yc="$((ymax - ymin + 1))";
163 fi;
164 # yell "DEBUG:ymin:$ymin";
165 # yell "DEBUG:ymax:$ymax";
166 # yell "DEBUG:yc :$yc";
167
168 # Check year range
169 if ! [[ $(( ymax - ymin )) -ge 0 ]]; then die "FATAL:Invalid year range:$yearRange"; fi;
170
171 # Print Output
172 ## Get day of month (first positional argument)
173 dom="${arrayPosArgs[0]}";
174 for (( year = ymin; year <= ymax; year++ )); do
175 dstr="$year-$dom";
176 date +%Y-%m-%d\ %A --date="$dstr";
177 # printf "DEBUG:dom :%s\n" "$dom";
178 # printf "DEBUG:ymax:%s\n" "$ymax";
179 # printf "DEBUG:ymin:%s\n" "$ymin";
180 # printf "DEBUG:year:%s\n" "$year";
181 # printf "DEBUG:dstr:%s\n" "$dstr";
182 done;
183 }; # main program
184
185 main "$@";
186
187
188
189 # Author: Steven Baltakatei Sandoval
190 # License: GPLv3+
191
192 # Ref/Attrib (depends)
193
194 # date (GNU coreutils) 8.32
195 # Copyright (C) 2020 Free Software Foundation, Inc.
196 # License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
197 # This is free software: you are free to change and redistribute it.
198 # There is NO WARRANTY, to the extent permitted by law.
199
200 # Written by David MacKenzie.