Sometimes I expect a command to be quick, but I type it and wait minutes or hours, then I wish I had recorded the start date of the command to know how long the command took.

Zsh has a hook that runs before a command is executed, and a hook that runs before the prompt is displayed. Using these hooks, we can determine if a command took a long time to display information about the execution duration.

I have chosen 5 seconds as the amount of time I start caring about the execution duration.

print_long_command_duration_preexec() {
    _date_start=${(%):-%D{%s}}
}
[[ -z "$preexec_functions" ]] && preexec_functions=()
preexec_functions+=(print_long_command_duration_preexec)

print_long_command_duration_precmd() {
    _date_end=${(%):-%D{%s}}
    pretty_print_date_difference "$_date_end" "${_date_start:-$_date_end}"
    unset _date_start
    unset _date_end
}
[[ -z "$precmd_functions" ]] && precmd_functions=()
precmd_functions+=(print_long_command_duration_precmd)

pretty_print_date_difference() {
    setopt LOCAL_OPTIONS NO_FORCE_FLOAT NO_C_PRECEDENCES &>/dev/null  # Old zsh does not have FORCE_FLOAT
    local date_end="$1"
    local date_start="$2"
    (( date_end - date_start < 5 )) && return
    if ( date --version 2>&1; true; ) | grep -q -e GNU -e BusyBox; then
        local date_start_iso="$(date -u -d @"$date_start" +%FT%TZ)"
        local date_end_iso="$(date -u -d @"$date_end" +%FT%TZ)"
        local date_start_local="$(date -d @"$date_start" '+%F %T')"
        local date_end_local="$(date -d @"$date_end" '+%F %T')"
    else
        local date_start_iso="$(date -u -r "$date_start" +%FT%TZ)"
        local date_end_iso="$(date -u -r "$date_end" +%FT%TZ)"
        local date_start_local="$(date -r "$date_start" '+%F %T')"
        local date_end_local="$(date -r "$date_end" '+%F %T')"
    fi
    local wall_time
    local d=$(( (date_end - date_start) / 86400 ))
    local h=$(( (date_end - date_start) % 86400 / 3600 ))
    local m=$(( (date_end - date_start) % 86400 % 3600 / 60 ))
    local s=$(( (date_end - date_start) % 86400 % 3600 % 60 ))
    if [[ "$d" -gt 0 ]]; then
        wall_time="$(printf '%dd %.02d:%.02d:%.02d' "$d" "$h" "$m" "$s")"
    else
        wall_time="$(printf '%.02d:%.02d:%.02d' "$h" "$m" "$s")"
    fi
    {
        local local_time_zone="$(date +%Z)"
        if [[ "$local_time_zone" = UTC ]]; then
            echo "Wall time: $wall_time\tStart: $date_start_iso\tStop: $date_end_iso"
        else
            local wall_time_prefix="Wall time: $wall_time"
            local local_time_prefix="${(l(${#wall_time_prefix})( )):-Local time ($local_time_zone)}"
            echo "$wall_time_prefix\tStart: $date_start_iso\tStop: $date_end_iso"
            echo "$local_time_prefix\t     : $date_start_local\t    : $date_end_local"
        fi
    } | if command -v column &>/dev/null; then column -t -s $'\t'; else cat; fi
}