MacOS top bar icon to track Deepseek and Alibaba Cloud off peak hours.
  • Swift 93.2%
  • Shell 3.7%
  • Python 3.1%
Find a file
2026-10-13 22:33:29 +02:00
Data/holiday-cn Add DSAliTimer: menu bar off-peak indicator 2026-10-11 18:55:47 +02:00
docs Add graphics 2026-10-13 22:33:29 +02:00
Resources Add DSAliTimer: menu bar off-peak indicator 2026-10-11 18:55:47 +02:00
Sources docs(StatusReport): drop the removed Copy status row from the header 2026-10-11 22:36:06 +02:00
Tests/OffPeakKitTests test(OffPeakKitTests): assert the verdict-led menu copy 2026-10-11 22:35:57 +02:00
Tools Add DSAliTimer: menu bar off-peak indicator 2026-10-11 18:55:47 +02:00
.gitignore Add DSAliTimer: menu bar off-peak indicator 2026-10-11 18:55:47 +02:00
build-app.sh Add DSAliTimer: menu bar off-peak indicator 2026-10-11 18:55:47 +02:00
Package.swift Add DSAliTimer: menu bar off-peak indicator 2026-10-11 18:55:47 +02:00
README.md Add graphics 2026-10-13 22:33:29 +02:00
test.sh Add DSAliTimer: menu bar off-peak indicator 2026-10-11 18:55:47 +02:00

DSAliTimer

A macOS menu bar app that shows whether right now is off-peak for DeepSeek and Alibaba Cloud Model Studio. Requires macOS 14 or later.

DSAliTimer menu at 12:13 in Budapest. DeepSeek is off-peak with 14h 46m left. Alibaba Model Studio is peak, with off-peak in 3h 46m.

Off-peak rules

Provider Schedule Weekends and holidays
DeepSeek Working days are peak 01:00–04:00 and 06:00–10:00 UTC, which is 09:00–12:00 and 14:00–18:00 in Beijing. Every other hour of a working day is off-peak. Off-peak all day. The day is the Beijing date.
Alibaba Model Studio Off-peak 22:00–08:00 UTC+8, which is 14:00–00:00 UTC, every day. No change.

China declares some weekends as make-up workdays (调休) to fund long holiday runs. Weekends stay off-peak, so a make-up workday counts as a weekend. Set OffPeakPolicy.makeupWorkdaysCountAsWorkingDays for the stricter reading.

Holiday data covers 2025 and 2026, generated from the State Council 放假安排 notices in Data/holiday-cn/. From 2027 on, days fall back to weekday and weekend rules until the schedule is published and the table regenerated:

python3 Tools/update_holidays.py --fetch 2027

Menu

The first row is the clock you are reading against. Each provider then gets two lines, its mark beside both:

DeepSeek                                  ○ in 2h 0m
Peak · next off-peak 04:00 → 06:00

Alibaba Model Studio                      ● 7h 36m left
Off-peak · ends 02:00 · next off-peak 16:00
  • The first line counts down the state you are in.
  • The second names that state and gives the clock times: when this run ends, and when the next off-peak starts.
  • A time carries a weekday label only once it has crossed midnight in the zone you are viewing.

--status prints the longer rule text, the reasoning, and the UTC and Beijing readings.

The open menu is built when you click it and does not tick, so the countdown is accurate to the moment you opened it. The menu bar updates every second, and immediately when the system clock changes.

Preferences

Settings, above Quit DSAliTimer, holds the two preferences.

Menu bar icon → Text labels swaps the marks for DS ● · ALI ○. Both carry the same information, and the app falls back to text on its own when a mark is missing. Text mode is stored as menuBarLabelStyle = text in the dev.ruben.dsalibtimer domain. Logos are the default, and that default is stored by deleting the key:

defaults delete dev.ruben.dsalibtimer menuBarLabelStyle

Times shown in → picks the zone the menu and --status print in: your Mac's zone, a pinned list, or every identifier macOS knows, each labelled with its real current offset so DST is visible. This is display only. The DeepSeek windows stay UTC and the Alibaba windows stay UTC+8 whatever you select. To go back to the system zone:

defaults delete dev.ruben.dsalibtimer displayTimeZoneIdentifier

Install and run

macOS 14 or later, and a Swift 6 toolchain (the package requires Swift tools 6.2), from Xcode or the Command Line Tools.

./build-app.sh              # release build -> dist/DSAliTimer.app
open dist/DSAliTimer.app    # lives in the menu bar; quit from its menu
./dist/DSAliTimer.app/Contents/MacOS/DSAliTimer --status
swift run DSAliTimer        # the same app unbundled, from the repo

The bundle is ad-hoc signed and not notarised, so a copy that arrives through a browser needs xattr -d com.apple.quarantine dist/DSAliTimer.app. To start it at login, move the bundle somewhere stable first, then add it under System Settings → General → Login Items.

Development

./test.sh
./test.sh -c release

test.sh exists because a Command Line Tools install ships Swift Testing without putting it on SwiftPM's framework search path, rpath, or dyld cache, and ships no XCTest at all. It wires those up, and behaves like plain swift test under a full Xcode.

Everything a user reads lives in OffPeakKit, wording included, so all of it is testable without AppKit. The suite sweeps every minute of the day for both providers, checks window edges and the Beijing-date basis against real 2026 holidays, and asserts the literal menu strings.

Sources/OffPeakKit/ is the logic: minute windows, civil dates, day kinds, the holiday table, the two provider rules, evaluation, time formatting, and menu copy. Sources/DSAliTimer/ is the menu bar and nothing else.

The verdict path does not use Calendar. An instant's Beijing date is integer arithmetic on epoch + 28800, so the day cannot follow your Mac's locale, its DST rules, or the zone you picked for display.

Brand marks

Resources/BrandIcons/ holds two SVGs that Tools/get_brand_icons.sh fetches from @lobehub/icons-static-svg on npm:

./Tools/get_brand_icons.sh          # default version, currently 1.95.1
./Tools/get_brand_icons.sh 1.96.0   # pin another

A file with the same name in ~/Library/Application Support/DSAliTimer/icons/ takes precedence over the bundled one.

Upstream sizes every icon width="1em" height="1em". AppKit resolves em to 1 pt, which in a status item is a one-point-wide invisible icon. BrandArtwork.normalizeSVG substitutes the viewBox numbers at load time, so the shipped files stay byte-identical to upstream.

The DeepSeek and Alibaba Cloud marks are trademarks of their owners. Upstream's MIT claim covers the icon collection, not the logos. See Resources/BrandIcons/NOTICE.md.