diff --git a/nag b/nag index c9ed76b..71f15aa 100755 --- a/nag +++ b/nag @@ -1181,6 +1181,87 @@ _first_occurrence() { fi } +# Usage: +# _unskip_timestamp +# +# Description: +# Compute the next natural occurrence of a repeating alarm from now. +# Handles each rule type appropriately: day-of-week rules use today's +# date at alarm's time, month preserves day-of-month, year preserves +# month and day. For comma-separated rules, returns the earliest. +_unskip_timestamp() { + local _timestamp="${1}" _rules="${2}" + local _now + _now="$(date +%s)" + + local _time_of_day _alarm_day _alarm_month + _time_of_day="$(date -d "@${_timestamp}" +%H:%M:%S)" + _alarm_day="$(date -d "@${_timestamp}" +%-d)" + _alarm_month="$(date -d "@${_timestamp}" +%-m)" + + local _earliest="" + local IFS="," + local _rule + for _rule in ${_rules} + do + local _candidate="" + case "${_rule}" in + hour) + _candidate="$((_now - (_now % 3600) + $(date -d "@${_timestamp}" +%s) % 3600))" + if (( _candidate <= _now )); then + _candidate=$((_candidate + 3600)) + fi + ;; + day) + _candidate="$(date -d "$(date +%Y-%m-%d) ${_time_of_day}" +%s)" + if (( _candidate <= _now )); then + _candidate="$(date -d "$(date +%Y-%m-%d) + 1 day ${_time_of_day}" +%s)" + fi + ;; + month) + local _year_now _month_now + _year_now="$(date +%Y)" + _month_now="$(date +%-m)" + _candidate="$(date -d "$(printf "%04d-%02d-%02d %s" "${_year_now}" "${_month_now}" "${_alarm_day}" "${_time_of_day}")" +%s 2>/dev/null)" || _candidate=0 + if (( _candidate <= _now )); then + if (( _candidate == 0 )); then + _candidate="$(date -d "$(date +%Y-%m-%d) ${_time_of_day}" +%s)" + fi + _candidate="$(_next_month "${_candidate}" "${_time_of_day}")" + fi + ;; + year) + local _year_now + _year_now="$(date +%Y)" + _candidate="$(date -d "$(printf "%04d-%02d-%02d %s" "${_year_now}" "${_alarm_month}" "${_alarm_day}" "${_time_of_day}")" +%s 2>/dev/null)" || _candidate=0 + if (( _candidate <= _now )); then + if (( _candidate == 0 )); then + _candidate="$(date -d "$(date +%Y-%m-%d) ${_time_of_day}" +%s)" + fi + _candidate="$(_next_year "${_candidate}" "${_time_of_day}")" + fi + ;; + *) + # Day-of-week rules (weekday, weekend, mon-sun, week). + local _today_at_alarm_time + _today_at_alarm_time="$(date -d "$(date +%Y-%m-%d) ${_time_of_day}" +%s)" + _candidate="$(_first_occurrence "${_rule}" "${_today_at_alarm_time}")" + if (( _candidate <= _now )); then + _candidate="$(_next_occurrence "${_rule}" "${_candidate}")" + fi + ;; + esac + + if [[ -n "${_candidate}" ]] && (( _candidate > 0 )); then + if [[ -z "${_earliest}" ]] || (( _candidate < _earliest )); then + _earliest="${_candidate}" + fi + fi + done + + printf "%s" "${_earliest}" +} + # Usage: # _timestamp_matches_rule # @@ -1385,6 +1466,7 @@ Usage: ${_ME} every