├── 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 |
--------------------------------------------------------------------------------