├── LICENSE ├── README.md └── menu-bar-clock.sh /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Steve Ward 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # menu-bar-clock 2 | 3 | [^1]: Known as System Preferences prior to macOS Ventura 13 4 | [^2]: Since macOS Ventura 13 5 | [^3]: Since macOS Monterey 12.4 6 | 7 | 8 | Compatible with macOS Big Sur 11 and later. 9 | 10 | ~~IMPORTANT: Until I have the opportunity to fix it, please note that [changes in macOS Monterey 12.4 have temporarily broken this script](https://github.com/tech-otaku/menu-bar-clock/issues/9).~~ 11 | 12 | ## Purpose 13 | 14 | Set the date and time format of the menu bar clock from the command line in macOS Big Sur 11 and later. 15 | 16 | Please note, the script simply mimics what can otherwise be achieved by setting the format through System Settings[^1] ~~System Preferences~~. It is therefore limited to the formats defined by Apple. 17 | 18 | ## Instructions 19 | 20 | 1. Download [menu-bar-clock-main.zip](https://github.com/tech-otaku/menu-bar-clock/archive/main.zip) 21 | 22 | 1. Double-click `~/Downloads/menu-bar-clock-main.zip` in the Finder to unzip it (Safari may do this automatically) 23 | 24 | 1. Open the Terminal application in macOS 25 | 26 | 1. At a Terminal prompt: 27 | 28 | 1. type `cd ~/Downloads/menu-bar-clock-main` and press enter 29 | 30 | 1. type `chmod +x menu-bar-clock.sh` and press enter to make the script executable 31 | 32 | 1. use one of the commands under the *Command Line* heading in the table below to set the required date and time format 33 | 34 | ## Changes in macOS Monterey 12.4 35 | 36 | Starting with macOS Monterey 12.4, Apple have made changes to the *Show date* option in System Settings > Desktop & Dock > Clock Options...[^2] ~~System Preferences > Dock & Menu Bar > Clock~~. Previously, it was either checked or unchecked and set the value of the `ShowDayOfMonth` key in the `com.apple.menuextra.clock` domain to either `true` or `false` respectively. This key now appears redundant. Instead, the *Show date* option offers 3 new choices which are written to a new key in the `com.apple.menuextra.clock` domain named `ShowDate`. 37 | 38 | | *Show date* | `ShowDate` | 39 | |-------------------|-----------:| 40 | | when space allows | `0` | 41 | | always | `1` | 42 | | never | `2` | 43 | 44 | 45 | ## Usage 46 | 47 | To support the changes to the *Show date* option in macOS Monterey 12.4, the script accepts a new option: `-s`. The option need only be passed to the script when the desired date format contains `d MMM` i.e. `18 Aug` **and** you want that date portion displayed *when space allows*. In all other circumstances it can be omitted, as per the table below. 48 | If the option is passed to the script it will be ignored when the date format doesn't contain `d MMM` or the installed macOS version is macOS Monterey 12.3.1 or earlier or macOS Big Sur 11. 49 | 50 | | Menu Bar Clock | Show date [^3] | Command Line | 51 | |-------------------------:|:------------------|:----------------------------------------------| 52 | | `Thu 18 Aug 23:46:18` | always | `./menu-bar-clock.sh "EEE d MMM HH:mm:ss"` | 53 | | `Thu 18 Aug 23:46:18` | when space allows | `./menu-bar-clock.sh "EEE d MMM HH:mm:ss" -s` | 54 | | `Thu 23:46:18` | N/A | `./menu-bar-clock.sh "EEE HH:mm:ss"` | 55 | | `18 Aug 23:46:18` | always | `./menu-bar-clock.sh "d MMM HH:mm:ss"` | 56 | | `18 Aug 23:46:18` | when space allows | `./menu-bar-clock.sh "d MMM HH:mm:ss" -s` | 57 | | `23:46:18` | N/A | `./menu-bar-clock.sh "HH:mm:ss"` | 58 | | `Thu 18 Aug 11:46:18 pm` | always | `./menu-bar-clock.sh "EEE d MMM h:mm:ss a"` | 59 | | `Thu 18 Aug 11:46:18 pm` | when space allows | `./menu-bar-clock.sh "EEE d MMM h:mm:ss a" -s`| 60 | | `Thu 11:46:18 pm` | N/A | `./menu-bar-clock.sh "EEE h:mm:ss a"` | 61 | | `18 Aug 11:46:18 pm` | always | `./menu-bar-clock.sh "d MMM h:mm:ss a"` | 62 | | `18 Aug 11:46:18 pm` | when space allows | `./menu-bar-clock.sh "d MMM h:mm:ss a" -s` | 63 | | `11:46:18 pm` | N/A | `./menu-bar-clock.sh "h:mm:ss a"` | 64 | | `Thu 18 Aug 11:46:18` | always | `./menu-bar-clock.sh "EEE d MMM h:mm:ss"` | 65 | | `Thu 18 Aug 11:46:18` | when space allows | `./menu-bar-clock.sh "EEE d MMM h:mm:ss" -s` | 66 | | `Thu 11:46:18` | N/A | `./menu-bar-clock.sh "EEE h:mm:ss"` | 67 | | `18 Aug 11:46:18` | always | `./menu-bar-clock.sh "d MMM h:mm:ss"` | 68 | | `18 Aug 11:46:18` | when space allows | `./menu-bar-clock.sh "d MMM h:mm:ss" -s` | 69 | | `11:46:18` | N/A | `./menu-bar-clock.sh "h:mm:ss"` | 70 | | `Thu 18 Aug 23:46` | always | `./menu-bar-clock.sh "EEE d MMM HH:mm"` | 71 | | `Thu 18 Aug 23:46` | when space allows | `./menu-bar-clock.sh "EEE d MMM HH:mm" -s` | 72 | | `Thu 23:46` | N/A | `./menu-bar-clock.sh "EEE HH:mm"` | 73 | | `18 Aug 23:46` | always | `./menu-bar-clock.sh "d MMM HH:mm"` | 74 | | `18 Aug 23:46` | when space allows | `./menu-bar-clock.sh "d MMM HH:mm" -s` | 75 | | `23:46` | N/A | `./menu-bar-clock.sh "HH:mm"` | 76 | | `Thu 18 Aug 11:46 pm` | always | `./menu-bar-clock.sh "EEE d MMM h:mm a"` | 77 | | `Thu 18 Aug 11:46 pm` | when space allows | `./menu-bar-clock.sh "EEE d MMM h:mm a" -s` | 78 | | `Thu 11:46 pm` | N/A | `./menu-bar-clock.sh "EEE h:mm a"` | 79 | | `18 Aug 11:46 pm` | always | `./menu-bar-clock.sh "d MMM h:mm a"` | 80 | | `18 Aug 11:46 pm` | when space allows | `./menu-bar-clock.sh "d MMM h:mm a" -s` | 81 | | `11:46 pm` | N/A | `./menu-bar-clock.sh "h:mm a"` | 82 | | `Thu 18 Aug 11:46` | always | `./menu-bar-clock.sh "EEE d MMM h:mm"` | 83 | | `Thu 18 Aug 11:46` | when space allows | `./menu-bar-clock.sh "EEE d MMM h:mm" -s` | 84 | | `Thu 11:46` | N/A | `./menu-bar-clock.sh "EEE h:mm"` | 85 | | `18 Aug 11:46` | always | `./menu-bar-clock.sh "d MMM h:mm"` | 86 | | `18 Aug 11:46` | when space allows | `./menu-bar-clock.sh "d MMM h:mm" -s` | 87 | | `11:46` | N/A | `./menu-bar-clock.sh "h:mm"` | 88 | 89 |
90 | 91 | The **Menu Bar Clock** values in the table above are localised and based on a *Region* setting of *United Kingdom* in System Settings > General > Language & Region[^2] ~~System Preferences > Language & Region > General~~. Other *Regions* may display the same date and time format differently. For example, the format `"EEE d MMM HH:mm"` is displayed differently for the following *Region* settings: 92 | 93 | | Region Setting | Display | 94 | |----------------|-----------------------| 95 | | United Kingdom | `Thu 18 Aug 23:46` | 96 | | United States | `Thu Aug 28 23:46` | 97 | | France | `Thu 28 Aug at 23:46` | 98 | | Germany | `Thu 28. Aug 23:46` | 99 | | Czechia | `Thu 28. 8. 23:46` | 100 | 101 | In addition, the primary preferred language setting also in System Settings > General > Language & Region[^2] ~~System Preferences > Language & Region > General~~ [may affect how the date and time is displayed](https://github.com/tech-otaku/menu-bar-clock/issues/8#issuecomment-1019289477). 102 | 103 | ## Background 104 | 105 | Prior to macOS Big Sur 11, setting the [date and time format of the menu bar clock](https://www.tech-otaku.com/mac/setting-the-date-and-time-format-for-the-macos-menu-bar-clock-using-terminal/) from the command line was relatively trivial. 106 | 107 | Challenges to setting the date and time format of the menu bar clock introduced in macOS Big Sur 11 include: 108 | 109 | - Additional keys in the `com.apple.menuextra.clock` domain. 110 | 111 | - A (re-purposed?) *24-Hour Time* option in System Settings[^1] ~~System Preferences~~ which overrides time settings. 112 | 113 | - The `SystemUIServer` process no longer appears responsible for displaying the date and time in the menu bar. 114 | 115 | 116 | 117 | ### Additional Keys 118 | 119 | In macOS Big Sur 11 and later, the structure of `com.apple.menuextra.clock.plist` has changed: 120 | 121 | ``` 122 | 123 | 124 | 125 | 126 | DateFormat 127 | EEE d MMM HH:mm 128 | FlashDateSeparators 129 | 130 | IsAnalog 131 | 132 | Show24Hour 133 | 134 | ShowAMPM 135 | 136 | ShowDate <--- New key as of macOS Monterey 12.4 137 | 0 138 | ShowDayOfMonth <--- Appears redundant as of macOS Monterey 12.4 139 | 140 | ShowDayOfWeek 141 | 142 | ShowSeconds 143 | 144 | 145 | 146 | ``` 147 | 148 |
149 | 150 | The additional keys are `Show24Hour`, `ShowAMPM`, `ShowDate` [^3], ~~`ShowDayOfMonth`~~[^3], `ShowDayOfWeek` and `ShowSeconds`. 151 | 152 | Prior to macOS Big Sur 11, only the `DateFormat` key need be set using a single `defaults write` command. Now, multiple `defaults write` commands are required to set the `DateFormat` key together with the 5 additional keys. 153 | 154 | 155 | ### *24-Hour Time* Option 156 | 157 | This option can be found in System Settings > General > Date & Time[^2] ~~System Preferences > Language & Region > General~~ and may override the keys `Show24Hour` and `ShowAMPM` depending on their values. It is also used to format the display of dates and times in the Finder. This option exists in Catalina too, but doesn't appear to assert the same control as it does in macOS Big Sur 11 and later. 158 | 159 | While this option can be turned on ~~checked~~ or off ~~unchecked~~ from within System Settings[^1] ~~System Preferences~~, it can be toggled from the command line using the `AppleICUForce12HourTime` key in the `.GlobalPreferences` domain. 160 | 161 | When the option is *off* ~~*unchecked*~~, the `AppleICUForce12HourTime` key has a boolean value of `true`. When *on* ~~*checked*~~, the key is deleted from the `.GlobalPreferences` domain. 162 | 163 | Any attempt to set the date and time format from the command line should ensure that this key exists or not based on the values of the `Show24Hour` and `ShowAMPM` keys, or vice versa. 164 | 165 | 166 | ### SystemUIServer Process 167 | 168 | Prior to macOS Big Sur 11, restarting the `SystemUIServer` process updated the date and time format of the menu bar clock with any changes to the `DateFormat` key. 169 | 170 | This is no longer true in macOS Big Sur 11 and later. The process that controls the menu bar clock is `ControlCenter` which needs to be restarted (killed) after changes have been made to the `com.apple.menuextra.clock` and `.GlobalPreferences` domains. 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /menu-bar-clock.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # AUTHOR: Steve Ward [steve at tech-otaku dot com] 4 | # URL: https://github.com/tech-otaku/menu-bar-clock.git 5 | # README: https://github.com/tech-otaku/menu-bar-clock/blob/master/README.md 6 | 7 | # USAGE: ./menu-bar-clock.sh FORMATSTRING [-s] 8 | # EXAMPLE: ./menu-bar-clock.sh "EEE d MMM HH:mm" -s 9 | # ./menu-bar-clock.sh -s "d MMM HH:mm" 10 | # ./menu-bar-clock.sh "EEE HH:mm" 11 | 12 | 13 | # Exit with error if installed macOS version is not macOS 11 Big Sur or later 14 | if [ $(system_profiler SPSoftwareDataType | awk '/System Version/ {print $4}' | cut -d . -f 1) -lt 11 ]; then 15 | printf "\nERROR: * * * For use with macOS 11 Big Sur or later * * * \n\n" 16 | exit 1 17 | fi 18 | 19 | 20 | # # # # # # # # # # # # # # # # # # # # 21 | # FUNCTION DECLARATIONS 22 | # 23 | 24 | # Function to display usage help 25 | function usage() { 26 | cat << EOF 27 | 28 | Syntax: 29 | ./$(basename $0) -h 30 | ./$(basename $0) FORMATSTRING [-s] 31 | ./$(basename $0) [-s] FORMATSTRING 32 | 33 | Options: 34 | -h This help message. 35 | -s Show the date ($(date +'%-d %b')) in the menu bar when space allows. 36 | FORMATSTRING A valid Apple-supplied date and time string. 37 | 38 | Example: ./$(basename $0) "EEE d MMM HH:mm" -s 39 | 40 | See https://github.com/tech-otaku/menu-bar-clock/blob/main/README.md for more examples. 41 | 42 | EOF 43 | } 44 | 45 | 46 | 47 | # # # # # # # # # # # # # # # # # # # # 48 | # COMMAND-LINE OPTIONS 49 | # 50 | 51 | # The script expects one option, either '-h' or '-s' and one positional parameter when using '-s' that defines the date and time format. The options are processed by getopts. The positional parameter(s) are processed outside of the getopts loop. Positional parameter(s) can be placed before or after options. 52 | 53 | # Exit with error if no command line options given 54 | if [[ ! $# -gt 0 ]]; then 55 | printf "\nERROR: * * * No options given * * *\n" 56 | usage 57 | exit 1 58 | fi 59 | 60 | while [ $# -gt 0 ]; do 61 | OPTIND=1 # OPTIND is (re)set to 1, so getopts can be called more than once. 62 | while getopts ':hs' opt; do 63 | # Process options 64 | case $opt in 65 | h) 66 | usage 67 | exit 1 68 | ;; 69 | s) 70 | SHOWDATE=true 71 | ;; 72 | ?) 73 | printf "\nERROR: * * * Invalid option: '-%s' * * *\n" $OPTARG 74 | usage 75 | exit 1 76 | ;; 77 | esac 78 | done 79 | # Process positional parameter(s) 80 | shift "$((OPTIND-1))" 81 | # The script expects only one positional parameter, but let's create an array of all the positional parameters just in case there are 2 or more! 82 | if [[ ! -z "${1// }" ]]; then 83 | positional+=("$1") 84 | fi 85 | if [ $# -gt 0 ]; then # If parsed by zsh, stops the error: "shift count must be <= $#" 86 | shift 87 | fi 88 | done 89 | 90 | 91 | 92 | # # # # # # # # # # # # # # # # # # # # 93 | # VALIDATION 94 | # 95 | 96 | # No positional parameters passed to the script i.e. ./menu-bar-clock.sh -s 97 | if [ "${#positional[@]}" -eq 0 ]; then 98 | printf "\nERROR: * * * No date and time format string given * * *\n" 99 | usage 100 | exit 1 101 | # 2 or more positional parameters passed to the script i.e. ./menu-bar-clock.sh 'EEE d MMM HH:mm' -s 'd MMM HH:mm' 102 | elif [ "${#positional[@]}" -gt 1 ]; then 103 | printf "\nERROR: * * * Too many parameters * * *\n" 104 | usage 105 | exit 1 106 | # 1 positional parameter passed to the script i.e ./menu-bar-clock.sh 'EEE d MMM HH:mm' -s 107 | else 108 | FORMATSTRING="${positional[@]:0:1}" # Works for both bash and zsh 109 | fi 110 | 111 | # Create an array of valid date and time format strings 112 | valid=("EEE d MMM HH:mm:ss" "EEE HH:mm:ss" "d MMM HH:mm:ss" "HH:mm:ss" "EEE d MMM h:mm:ss a" "EEE h:mm:ss a" "d MMM h:mm:ss a" "h:mm:ss a" "EEE d MMM h:mm:ss" "EEE h:mm:ss" "d MMM h:mm:ss" "h:mm:ss" "EEE d MMM HH:mm" "EEE HH:mm" "d MMM HH:mm" "HH:mm" "EEE d MMM h:mm a" "EEE h:mm a" "d MMM h:mm a" "h:mm a" "EEE d MMM h:mm" "EEE h:mm" "d MMM h:mm" "h:mm") 113 | 114 | # Check if the date and time format string passed to the script (FORMATSTRING) is valid 115 | invalid=true 116 | if printf '%s\0' "${valid[@]}" | grep -Fxzq "$FORMATSTRING"; then # See https://stackoverflow.com/a/47541882 117 | unset invalid 118 | fi 119 | 120 | 121 | 122 | # # # # # # # # # # # # # # # # # # # # 123 | # SET MENU BAR CLOCK DISPLAY 124 | # 125 | 126 | # Process the new format string 127 | if [ -z $invalid ]; then # If $invalid is unset, the format string is valid 128 | 129 | # The script takes different actions depending on the version of macOS, so determine the major and minor versions of the installed OS e.g. 12.4 130 | major=$(system_profiler SPSoftwareDataType | awk '/System Version/ {print $4}' | cut -d . -f 1) 131 | minor=$(system_profiler SPSoftwareDataType | awk '/System Version/ {print $4}'| cut -d . -f 2) 132 | 133 | # Quit System Settings (previously System Preferences prior to macOS Ventura 13) 134 | SETTINGS="System Settings" 135 | if [[ $major -lt 13 ]]; then 136 | SETTINGS="System Preferences" 137 | fi 138 | 139 | killall "$SETTINGS" 2> /dev/null # Write STDERR to /dev/null to supress message if process isn't running 140 | 141 | # The date and time format is irrelevant unless the menu bar displays a digital clock 142 | defaults write com.apple.menuextra.clock.plist IsAnalog -bool false 143 | 144 | # Set the new format string 145 | defaults write com.apple.menuextra.clock.plist DateFormat -string "$FORMATSTRING" 146 | 147 | # Set the various keys based upon the new format string 148 | # Day (Thu) 149 | if [[ "$FORMATSTRING" == *"EEE"* ]]; then 150 | defaults write com.apple.menuextra.clock.plist ShowDayOfWeek -bool true 151 | else 152 | defaults write com.apple.menuextra.clock.plist ShowDayOfWeek -bool false 153 | fi 154 | 155 | # Date (18 Aug) 156 | if [[ $major -ge 13 || ($major -eq 12 && $minor -ge 4) ]]; then 157 | # macOS Monterey 12.4 and later 158 | if [[ "$FORMATSTRING" == *"d MMM"* ]]; then 159 | if [ ! -z "$SHOWDATE" ]; then 160 | defaults write com.apple.menuextra.clock.plist ShowDate -int 0 161 | else 162 | defaults write com.apple.menuextra.clock.plist ShowDate -int 1 163 | fi 164 | else 165 | defaults write com.apple.menuextra.clock.plist ShowDate -int 2 166 | fi 167 | else 168 | # macOS macOS Monterey 12.3.1 and earlier 169 | if [[ "$FORMATSTRING" == *"d MMM"* ]]; then 170 | defaults write com.apple.menuextra.clock.plist ShowDayOfMonth -bool true 171 | else 172 | defaults write com.apple.menuextra.clock.plist ShowDayOfMonth -bool false 173 | fi 174 | fi 175 | 176 | # 24-hour time (23:46) 177 | if [[ "$FORMATSTRING" == *"HH:mm"* ]]; then 178 | defaults delete -g AppleICUForce12HourTime > /dev/null 2>&1 179 | defaults write com.apple.menuextra.clock.plist Show24Hour -bool true 180 | fi 181 | 182 | # 12-hour time (11:46) 183 | if [[ "$FORMATSTRING" == *"h:mm"* ]]; then 184 | defaults write -g AppleICUForce12HourTime -bool true 185 | defaults write com.apple.menuextra.clock.plist Show24Hour -bool false 186 | fi 187 | 188 | # Seconds (:18) 189 | if [[ "$FORMATSTRING" == *"ss"* ]]; then 190 | defaults write com.apple.menuextra.clock.plist ShowSeconds -bool true 191 | else 192 | defaults write com.apple.menuextra.clock.plist ShowSeconds -bool false 193 | fi 194 | 195 | # AM/PM (am|pm) 196 | if [[ "$FORMATSTRING" == *"a"* ]]; then 197 | defaults write com.apple.menuextra.clock.plist ShowAMPM -bool true 198 | else 199 | defaults write com.apple.menuextra.clock.plist ShowAMPM -bool false 200 | fi 201 | 202 | # Restart the ControlCenter process for changes to take effect 203 | killall ControlCenter 204 | 205 | printf "The menu bar clock format has been set to '%s'.\n" "$FORMATSTRING" 206 | if [[ $major -ge 13 || ($major -eq 12 && $minor -ge 4) ]]; then 207 | if [ $(defaults read com.apple.menuextra.clock.plist ShowDate) -eq 0 ]; then 208 | printf "The date portion (%s) will be shown %s.\n" "$(date +'%-d %b')" "when space allows" 209 | elif [ $(defaults read com.apple.menuextra.clock.plist ShowDate) -eq 1 ]; then 210 | printf "The date portion (%s) will %s be shown.\n" "$(date +'%-d %b')" "always" 211 | fi 212 | fi 213 | 214 | else # If $invalid is set, the format string is invalid 215 | 216 | printf "\nERROR: * * * '%s' is NOT a valid Apple-defined date and time format string for the menu bar clock * * *\n\n" "$FORMATSTRING" 217 | 218 | fi 219 | --------------------------------------------------------------------------------