#!/bin/bash yell() { echo "$0: $*" >&2; } # print script path and all args to stderr die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails dateDuration() { # Desc: Given two date strings, output seconds duration # Example: dateDuration 2012-06-30 2012-07-01 # Yields 86401 because leap second # Version 0.0.1 # Depends: GNU Coreutils 9.4 (date, sed), GNU Bash 5.2.21 # References: [1] “"right" tz database (zoneinfo) files and GPS-based NTP” https://www.ucolick.org/~sla/leapsecs/right+gps.html date1="$1"; date2="$2"; # Check args if [[ -z "$date1" ]]; then die "FATAL:Invalid first date provided:${date1}"; fi; if [[ -z "$date2" ]]; then die "FATAL:Invalid second date provided:${date2}"; fi; if [[ $# -gt 2 ]]; then die "FATAL:Too many arguments."; fi; ## Convert @-specified unix epoch into right unix epoch (rue) re='@.*'; if [[ "$date1" =~ $re ]] || [[ "$date2" =~ $re ]]; then die "FATAL:@-specified unix epoch detected. Why are you using me?"; fi; # Use right unix epoch to account for leap seconds. export TZ=right/UTC; # See [1] # Convert date strings into Unix epoch unixEpoch1="$(must date --date="$date1" +%s)"; unixEpoch2="$(must date --date="$date2" +%s)"; # Calculate duration duration="$((unixEpoch2 - unixEpoch1))"; duration="$(sed -e 's/^-//' <<<"$duration"; )"; printf "%s\n" "$duration"; }; # Examples dateDuration 2026-06-30 2026-07-01; # 86400 seconds dateDuration 2012-06-30 2012-07-01; # 86401 seconds (leap second)