#!/usr/bin/env bash # Description: Outputs days until next timezone discontinuity # Depends: GNU Coreutils 8.32 (date), zdump 2.35, Bash 5.1.16 # BK-2020-03: yell(), die(), must() # Version: 0.1.0 # User config script_tz="America/Los_Angeles"; # Timezone to check for discontinuities yell() { echo "$0: $*" >&2; } # Yell, Die, Try Three-Fingered Claw technique; # Ref/Attrib: https://stackoverflow.com/a/25515370 die() { yell "$*"; exit 111; } must() { "$@" || die "cannot $*"; } main() { declare -a datesDiscontArray; #array # plumbing script_year="$(date +%Y)"; script_year_next="$(( script_year + 1 ))"; script_year_next2="$(( script_year + 2 ))"; script_run_date_seconds="$(date +%s)"; # Get discontinuity dates from zdump (see https://stackoverflow.com/a/613580 ) datesDiscont="$(zdump -c "$script_year","$script_year_next2" -v $script_tz | \ grep "$script_year\|$script_year_next" | \ awk '{ print $2 " " $3 " " $4 " " $5 " " $6 " " $7 }'; echo)"; # get dates if [[ -z "$datesDiscont" ]]; then yell "STATUS:No time discontinuity this year."; exit 1; fi; # Convert datesDiscont into array while read -r line; do tunix="$(date --date="$line" +%s)"; # get unix epoch seconds datesDiscontArray+=("$tunix"); done < <(printf "%s\n" "$datesDiscont"); # Sort datesDiscontArray while read -r line; do datesDiscontArray+=("$line"); done < <(printf "%s\n" "${datesDiscontArray[@]}" | sort); # # Get earliest date in datesDiscontArray that isn't in the past. for discontinuityDate in "${datesDiscontArray[@]}"; do if [[ $discontinuityDate -gt $script_run_date_seconds ]]; then nextDiscontDate="$discontinuityDate"; break; fi; done; # Check that nextDiscontDate is not empty if [[ -z "$nextDiscontDate" ]]; then die "FATAL:nextDiscontDate empty"; fi; # Calculate days until next discontinuity date output="$(( ( nextDiscontDate - script_run_date_seconds )/86400 )) days"; printf "%s\n" "$output"; }; # main program main "$@"; # Author: Steven Baltakatei Sandoval # License: GPLv3+