From fc69a0209c68de5366db5b292dab941f4b97e524 Mon Sep 17 00:00:00 2001 From: Steven Baltakatei Sandoval Date: Sun, 25 Sep 2022 11:22:44 +0000 Subject: [PATCH] feat(user/bk_this-date): Add script to print dow for given dom - Note: script name: bk_this-date-in-recent-years.sh - Note: The script prints out an iso-8601 date string followed by the day of the week for the most recent 10 years or a specified date range. Useful for determining likely years a month-day combination occured when the day of the week is known. --- user/bk_this-date-in-recent-years.sh | 200 +++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 user/bk_this-date-in-recent-years.sh diff --git a/user/bk_this-date-in-recent-years.sh b/user/bk_this-date-in-recent-years.sh new file mode 100644 index 0000000..f072ca6 --- /dev/null +++ b/user/bk_this-date-in-recent-years.sh @@ -0,0 +1,200 @@ +#!/usr/bin/env bash +# Desc: Prints days +# Depends: date (GNU Coreutils 8.32) +# Version: 0.0.1 +# Ref/Attrib: [1] Template:This date in recent years https://en.wikipedia.org/wiki/Template:This_date_in_recent_years +# [2] Removing leading zeros before passing a shell variable to another command https://stackoverflow.com/a/11130324 + +declare -g yearRange; # range of years to consider + +yell() { echo "$0: $*" >&2; } #o Yell, Die, Try Three-Fingered Claw technique +die() { yell "$*"; exit 111; } #o Ref/Attrib: https://stackoverflow.com/a/25515370 +try() { "$@" || die "cannot $*"; } #o +vbm() { + # Description: Prints verbose message ("vbm") to stderr if opVerbose is set to "true". + # Usage: vbm "DEBUG :verbose message here" + # Version 0.2.0 + # Input: arg1: string + # vars: opVerbose + # Output: stderr + # Depends: bash 5.1.16, GNU-coreutils 8.30 (echo, date) + + if [ "$opVerbose" = "true" ]; then + functionTime="$(date --iso-8601=ns)"; # Save current time in nano seconds. + echo "[$functionTime]:$0:""$*" 1>&2; # Display argument text. + fi + + # End function + return 0; # Function finished. +} # Displays message if opVerbose true +showUsage() { + # Desc: Display script usage information + # Usage: showUsage + # Version 0.0.2 + # Input: none + # Output: stdout + # Depends: GNU-coreutils 8.30 (cat) + cat <<'EOF' + USAGE: + bk_this-date-in-recent-years.sh [ options ] [str day of month] + + OPTIONS: + -h, --help + Display help information. + --version + Display script version. + -v, --verbose + Display debugging info. + -r, --iso-range + Specify year range (iso-8601 period), e.g. + "2010/2020". By default, most recent 10 + years are considered. + -- + Indicate end of options. + + EXAMPLE: + bk_this_date-in-recent-years.sh "05-11" + bk_this_date-in-recent-years.sh -r "1990/2020" "05-11" + bk_this_date-in-recent-years.sh -r "1990/2020" -- "05-11" +EOF +} # Display information on how to use this script. +processArgs() { + # Desc: Processes arguments provided to script. + # Usage: processArgs "$@" + # Version: 1.0.0 + # Input: "$@" (list of arguments provided to the function) + # yearRange Iso date range to consider (e.g. "1999/2020"). + # Output: Sets following variables used by other functions: + # opVerbose Indicates verbose mode enable status. (ex: "true", "false") + # opIsoRange Indicates that an iso-8601 date range is specified. (ex: "true", "false") + # yearRange Iso date range to consider (e.g. "1999/2020"). + # arrayPosArgs Array of remaining positional argments + # Depends: + # yell() Displays messages to stderr. + # vbm() Displays messsages to stderr if opVerbose set to "true". + # showUsage() Displays usage information about parent script. + # showVersion() Displays version about parent script. + # arrayPosArgs Global array for storing non-option positional arguments (i.e. arguments following the `--` option). + # External dependencies: bash (5.1.16), echo + # Ref./Attrib.: + # [1]: Marco Aurelio (2014-05-08). "echo that outputs to stderr". https://stackoverflow.com/a/23550347 + # [2]: "Handling positional parameters" (2018-05-12). https://wiki.bash-hackers.org/scripting/posparams + + # Initialize function + vbm "DEBUG:processArgs function called." + + # Perform work + while [ ! $# -eq 0 ]; do # While number of arguments ($#) is not (!) equal to (-eq) zero (0). + #yell "DEBUG:Starting processArgs while loop." # Debug stderr message. See [1]. + #yell "DEBUG:Provided arguments are:""$*" # Debug stderr message. See [1]. + case "$1" in + -h | --help) showUsage; exit 1;; # Display usage. + --version) showVersion; exit 1;; # Show version + -v | --verbose) opVerbose="true"; vbm "DEBUG:Verbose mode enabled.";; # Enable verbose mode. See [1]. + -r | --iso-range) + opIsoRange="true"; vbm "DEBUG:Accepting iso-8601 year range."; # Accept iso-8601 year range. + shift; + yearRange="$1";; + --) # End of all options. See [2]. + shift; + for arg in "$@"; do + vbm "DEBUG:adding to arrayPosArgs:$arg"; + arrayPosArgs+=("$arg"); + done; + break;; + -*) showUsage; yell "ERROR: Unrecognized option."; exit 1;; # Display usage + *) for arg in "$@"; do + vbm "DEBUG:adding to arrayPosArgs:$arg"; + arrayPosArgs+=("$arg"); + done; + break;; + esac + shift + done + + # End function + vbm "DEBUG:processArgs function ended." + return 0; # Function finished. +} # Evaluate script options from positional arguments (ex: $1, $2, $3, etc.). +validatePosArgs() { + # Input: arrayPosArgs array with positional arguments + # opVerbose bool indicates to vbm() to display verbose text + # opIsoRange bool indicates to use a user-provided year range + # yearRange str iso-8601 year range provided by -r, --iso-range option + + # Validate year $range + re='^[0-9]+/[0-9]+$'; # Simply check (int)/(int). Don't address Gregorian Calendar here. + if [[ $opIsoRange == "true" && ! "$yearRange" =~ $re ]] ; then + showUsage; + yell "ERROR:Not a valid date range (e.g. 2010/2022):$yearRange"; + return 1; + fi; + return 0; +}; # Validate arguments +main() { + # Input: arrayPosArgs array with positional arguments + # opVerbose bool indicates to vbm() to display verbose text + # opIsoRange bool indicates to use a user-provided year range + # yearRange str iso-8601 year range provided by -r, --iso-range option + # Output: stdout: dates with days of the week (newline delimited) + # Depends: date (GNU Coreutils 8.32) + # Depends: processArgs(), yell(), vbm(), showUsage(), showVersion(), validatePosArgs() + local dom yc ymin ymax; + + # Check input + processArgs "$@"; + if ! validatePosArgs; then + die "FATAL:Invalid positional arguments:$(declare -p arrayPosArgs)"; + fi; + + # Define year range + if [[ ! $opIsoRange == "true" ]]; then + ## Default: Most recent 10 years + yc="10"; # count of years to consider + ymax="$(date +%Y)"; # highest year to consider + ymin="$((ymax - yc))"; # earliest year to consider + else + ## Provided via -r,--iso-range option + ymin="$(echo "$yearRange" | cut -d'/' -f1)"; + ymin="$((10#$ymin))"; # strip leading zeroes. See [2] + ymax="$(echo "$yearRange" | cut -d'/' -f2)"; # See [2] + ymax="$((10#$ymax))"; # strip leading zeroes. See [2] + yc="$((ymax - ymin + 1))"; + fi; + # yell "DEBUG:ymin:$ymin"; + # yell "DEBUG:ymax:$ymax"; + # yell "DEBUG:yc :$yc"; + + # Check year range + if ! [[ $(( ymax - ymin )) -ge 0 ]]; then die "FATAL:Invalid year range:$yearRange"; fi; + + # Print Output + ## Get day of month (first positional argument) + dom="${arrayPosArgs[0]}"; + for (( year = ymin; year <= ymax; year++ )); do + dstr="$year-$dom"; + date +%Y-%m-%d\ %A --date="$dstr"; + # printf "DEBUG:dom :%s\n" "$dom"; + # printf "DEBUG:ymax:%s\n" "$ymax"; + # printf "DEBUG:ymin:%s\n" "$ymin"; + # printf "DEBUG:year:%s\n" "$year"; + # printf "DEBUG:dstr:%s\n" "$dstr"; + done; +}; # main program + +main "$@"; + + + +# Author: Steven Baltakatei Sandoval +# License: GPLv3+ + +# Ref/Attrib (depends) + + # date (GNU coreutils) 8.32 + # Copyright (C) 2020 Free Software Foundation, Inc. + # License GPLv3+: GNU GPL version 3 or later . + # This is free software: you are free to change and redistribute it. + # There is NO WARRANTY, to the extent permitted by law. + + # Written by David MacKenzie. -- 2.30.2