Skip to content

Instantly share code, notes, and snippets.

@nicholaslythall
Last active August 31, 2025 00:35
Show Gist options
  • Select an option

  • Save nicholaslythall/64c7a241b10c3dd0d9d607c2e14746c8 to your computer and use it in GitHub Desktop.

Select an option

Save nicholaslythall/64c7a241b10c3dd0d9d607c2e14746c8 to your computer and use it in GitHub Desktop.
Calculate how long and when you've been at your computer today.
#!/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
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