I want my Fedora 42 (works with 41 I guess) to automatically switch to dark mode at night and light mode during the day. I’m already using the night mode to trigger the blue light filter at specific times.
Thanks to Adam I had a base to start with. He wrote a blog post on having the dark mode auto switch with hard coded times. You can read it here
This part of the code is what troubled me the most,
currenttime=$(date +%H:%M)
if [[ "$currenttime" > "17:00" || "$currenttime" < "09:00" ]]; then
set_theme dark
else
set_theme light
fi
To get the night mode times I used gsettings
tool. source
gsettings get org.gnome.settings-daemon.plugins.color night-light-schedule-from
gsettings get org.gnome.settings-daemon.plugins.color night-light-schedule-to
But the output is in decimal time format (e.g., 20.3 for 20:18). We need to convert the current time in HH:MM format to decimal format (and not the oher way around to avoid float errors). Here is a piece of code that does this conversion:
# convert from HH:MM format (20:18) to decimal format (20.3)
time_to_decimal() {
local time_format="$1"
if [[ ! $time_format =~ ^[0-9]{1,2}:[0-9]{2}$ ]]; then
echo "Error: Invalid format. Use HH:MM (ex: 20:18)"
return 1
fi
# split hours and minutes
local hours=$(echo "$time_format" | cut -d':' -f1)
local minutes=$(echo "$time_format" | cut -d':' -f2)
# convert minutes in fraction
# 18 minutes = 18/60 = 0.3 hour
local decimal_part=$(echo "scale=1; $minutes * 10 / 60" | bc)
echo "$hours.$decimal_part"
}
And the full result is
#!/bin/bash
set_theme() {
if [[ "$1" == "dark" ]]; then
new_gtk_theme="prefer-dark"
elif [[ "$1" == "light" ]]; then
new_gtk_theme="prefer-light"
else
echo "[!] Unsupported theme: $1"
return
fi
export DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS
echo "$DBUS_SESSION_BUS_ADDRESS"
current_gtk_theme=$(gsettings get org.gnome.desktop.interface color-scheme)
# echo "[.] Currently using ${current_gtk_theme}"
if [[ "${current_gtk_theme}" == "'${new_gtk_theme}'" ]]; then
echo "[i] Already using gtk '${new_gtk_theme}' theme"
else
echo "[-] Setting gtk theme to ${new_gtk_theme}"
gsettings set org.gnome.desktop.interface color-scheme ${new_gtk_theme}
echo "[✓] gtk theme changed to ${new_gtk_theme}"
fi
}
# convert from HH:MM format (20:18) to decimal format (20.3)
time_to_decimal() {
local time_format="$1"
if [[ ! $time_format =~ ^[0-9]{1,2}:[0-9]{2}$ ]]; then
echo "Error: Invalid format. Use HH:MM (ex: 20:18)"
return 1
fi
# split hours and minutes
local hours=$(echo "$time_format" | cut -d':' -f1)
local minutes=$(echo "$time_format" | cut -d':' -f2)
# convert minutes in fraction
# 18 minutes = 18/60 = 0.3 hour
local decimal_part=$(echo "scale=1; $minutes * 10 / 60" | bc)
echo "$hours.$decimal_part"
}
# If script run without argument
if [[ -z "$1" ]]; then
currenttime=$(time_to_decimal $(date +%H:%M))
starttime=$(gsettings get org.gnome.settings-daemon.plugins.color night-light-schedule-from)
endtime=$(gsettings get org.gnome.settings-daemon.plugins.color night-light-schedule-to)
if [[ "$currenttime" > "$starttime" && "$currenttime" < "$endtime" ]]; then
set_theme dark
else
set_theme light
fi
else
set_theme $1
fi
Once the script is ready I wanted to modify the timer to avoid hardcoded times. My timer will run every hour but you can increase the frequency if you want. source
[Unit]
Description=Auto adjusts GNOME theme between dark and light to match the time
[Timer]
OnBootSec=1min
OnUnitActiveSec=1h
[Install]
WantedBy=timers.target
Sources
Credits to Technowizardry for the initial idea and code.
EDIT: there is a GNOME extension that does this automatically: Night Theme Switcher. I didn’t know about it when I wrote this post.
Comments
To give feedback, send an email to percevalsa [at] outlook dot com.