Created
August 31, 2025 00:36
-
-
Save nicholaslythall/927f0cc4c33c981ba8c4a599ad3fb183 to your computer and use it in GitHub Desktop.
Calculate how long and when you've been at your computer today.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| set -e | |
| # ANSI color codes | |
| GREEN="\033[0;32m" | |
| RED="\033[0;31m" | |
| BLUE="\033[0;34m" | |
| GREY="\033[0;90m" | |
| YELLOW="\033[0;33m" | |
| MAGENTA="\033[0;35m" | |
| BOLDWHITE="\033[1;37m" | |
| RESET="\033[0m" | |
| # Default to current day | |
| date_filter="$(date "+%Y-%m-%d")" | |
| # Parse aguments | |
| # -y Show the times for yesterday | |
| # -d yyyy-MM-dd Show the times for the given date | |
| while [[ $# -gt 0 ]]; do | |
| case "$1" in | |
| -y|--yesterday) | |
| date_filter="$(date -v-1d "+%Y-%m-%d")" | |
| shift | |
| ;; | |
| -d|--date) | |
| if [[ -n "$2" ]]; then | |
| date_filter="$2" | |
| shift 2 | |
| else | |
| echo "Error: --date requires and argument" >&2 | |
| exit 1 | |
| fi | |
| ;; | |
| *) | |
| echo "Unknown option: $1" >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| done | |
| # Check for -y or --yesterday flag | |
| if [[ "$1" == "-y" || "$1" == "--yesterday" ]]; then | |
| date_filter="$(date -v-1d "+%Y-%m-%d")" | |
| fi | |
| # Fetch the log for the current day | |
| log=$(pmset -g log | grep "$date_filter" | grep -e "Display is turned off" -e "Display is turned on") | |
| # Initialize variables | |
| previous_on_time="" | |
| previous_off_time="" | |
| total_minutes=0 | |
| while IFS= read -r line; do | |
| line=$(echo "$line" | sed 's/[[:space:]]*$//') | |
| timestamp=$(echo "$line" | awk '{print $1, $2}') | |
| timestamp_short=$(echo "$timestamp" | cut -c1-16) | |
| event=$(echo "$line" | grep -o "Display is turned \S*") | |
| if [[ "$event" == "Display is turned on" ]]; then | |
| # If there was a previous off event, calculate break time | |
| if [[ -n "$previous_off_time" ]]; then | |
| off_epoch=$(date -j -f "%Y-%m-%d %H:%M:%S" "$previous_off_time" +"%s" 2>/dev/null) | |
| on_epoch=$(date -j -f "%Y-%m-%d %H:%M:%S" "$timestamp" +"%s" 2>/dev/null) | |
| if [[ -n "$off_epoch" && -n "$on_epoch" ]]; then | |
| break_minutes=$(( (on_epoch - off_epoch) / 60 )) | |
| echo -e "${GREY}-- Break for $break_minutes minutes --${RESET}" | |
| fi | |
| fi | |
| echo -e "${GREEN}$timestamp_short Display turned on${RESET}" | |
| previous_on_time="$timestamp" | |
| previous_off_time="" | |
| elif [[ "$event" == "Display is turned off" ]]; then | |
| if [[ -n "$previous_on_time" ]]; then | |
| on_epoch=$(date -j -f "%Y-%m-%d %H:%M:%S" "$previous_on_time" +"%s" 2>/dev/null) | |
| off_epoch=$(date -j -f "%Y-%m-%d %H:%M:%S" "$timestamp" +"%s" 2>/dev/null) | |
| if [[ -n "$on_epoch" && -n "$off_epoch" ]]; then | |
| duration=$(( (off_epoch - on_epoch) / 60 )) | |
| echo -e "${RED}$timestamp_short Display turned off${MAGENTA} (was on for $duration minutes)${RESET}" | |
| total_minutes=$((total_minutes + duration)) | |
| else | |
| echo -e "${RED}$timestamp_short Display turned off${RESET}" | |
| fi | |
| else | |
| echo -e "${RED}$timestamp_short Display turned off${RESET}" | |
| fi | |
| previous_on_time="" | |
| previous_off_time="$timestamp" | |
| fi | |
| done <<< "$log" | |
| # Handle final unmatched "on" event (display is still on) | |
| if [[ -n "$previous_on_time" ]]; then | |
| now_epoch=$(date +"%s") | |
| on_epoch=$(date -j -f "%Y-%m-%d %H:%M:%S" "$previous_on_time" +"%s" 2>/dev/null) | |
| if [[ -n "$on_epoch" ]]; then | |
| duration=$(( (now_epoch - on_epoch) / 60 )) | |
| now_short=$(date "+%Y-%m-%d %H:%M") | |
| echo -e "${GREEN}$now_short Displays still on ${MAGENTA}(was on for $duration minutes so far)${RESET}" | |
| total_minutes=$((total_minutes + duration)) | |
| fi | |
| fi | |
| total_part_hours=$(( total_minutes / 60 )) | |
| total_part_minutes=$(( total_minutes % 60 )) | |
| # Fractional hours (e.g. 1.23) | |
| total_hours=$(awk "BEGIN { printf \"%.2f\", $total_minutes/60 }") | |
| echo -e "\n${BOLDWHITE}Total Time Today: ${total_hours}hrs (${total_part_hours}hr and ${total_part_minutes} minutes)${RESET}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment