Atomic Clock is a small SwiftUI app that displays UTC and local time adjusted by measurements from several public Network Time Protocol (NTP) servers. It is useful for setting a watch or comparing a device clock with network time.
The app:
- queries five NTP servers concurrently over UDP port 123;
- selects the three responses with the lowest round-trip delay;
- applies the median of those offsets to the displayed time;
- refreshes automatically every five minutes and supports pull-to-refresh; and
- has no third-party dependencies, accounts, analytics, or advertising.
- A Mac capable of running Xcode 16 or newer
- Xcode with iOS platform support installed
- iOS 17.0 or newer for a physical iPhone or iPad
- An Apple Account added to Xcode to install on a physical device
A paid Apple Developer Program membership is not required for personal use. Apple's free Personal Team provisioning expires periodically, so a locally installed build may need to be rebuilt and installed again.
Clone this repository, then open the project:
git clone https://github.com/anemitz/ios-atomic-clock.git
cd ios-atomic-clock
open AtomicClock.xcodeprojIn Xcode, select the AtomicClock scheme and an iPhone simulator, then click
Run or press Command+R.
The simulator is useful for checking the interface. Test on a physical device for results that reflect the device's actual network and clock.
-
Open Xcode and choose Xcode > Settings > Accounts. Add your Apple Account if it is not already listed.
-
Connect your unlocked device to the Mac. Accept the Trust This Computer prompt if it appears. Xcode can use the device wirelessly after it has been paired.
-
Create your ignored local signing configuration:
cp Config/Signing.local.xcconfig.example Config/Signing.local.xcconfig open -e Config/Signing.local.xcconfig
-
Replace
com.yourname.AtomicClockwith a unique reverse-domain bundle identifier. -
Replace
YOUR_TEAM_IDwith your 10-character Apple Team ID:-
Apple Developer Program members can find it under Membership details in their developer account.
-
For a free Personal Team, select your account under Xcode > Settings > Accounts and use Manage Certificates to create an Apple Development certificate if needed. Then run:
security find-identity -v -p codesigning
Use the 10-character value in parentheses after the matching
Apple Developmentidentity.
-
-
Open
AtomicClock.xcodeproj. Automatic signing reads your local configuration; avoid selecting a team in Signing & Capabilities, because doing so writes that personal value into the shared project file. -
In the Xcode toolbar, select the
AtomicClockscheme and your device as the run destination. Click Run or press Command+R. -
If requested, enable Developer Mode on the device under Settings > Privacy & Security > Developer Mode, restart it, and confirm the prompt after it restarts. Run the app from Xcode again.
With a free Personal Team, Apple currently limits provisioning profiles to seven days. Rebuild the app from Xcode when the installed copy expires.
Apple references: running an app on a physical device, enabling Developer Mode, and Personal Team limits.
Config/Signing.local.xcconfig is ignored by Git. Simulator and unsigned CI
builds use the public defaults in Config/Signing.xcconfig, while each
contributor can use a different local team and bundle identifier.
Command Line Tools alone are not sufficient; select a full Xcode installation first if necessary:
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
xcodebuild -versionBuild without code signing:
xcodebuild \
-project AtomicClock.xcodeproj \
-scheme AtomicClock \
-destination 'generic/platform=iOS Simulator' \
-derivedDataPath /tmp/AtomicClockDerivedData \
CODE_SIGNING_ALLOWED=NO \
buildRun the unit tests from Product > Test in Xcode, or substitute the name of an installed simulator in this command:
xcodebuild \
-project AtomicClock.xcodeproj \
-scheme AtomicClock \
-destination 'platform=iOS Simulator,name=YOUR_SIMULATOR_NAME' \
-derivedDataPath /tmp/AtomicClockTestDerivedData \
CODE_SIGNING_ALLOWED=NO \
testThe default servers are:
time.apple.comtime.google.comtime.cloudflare.compool.ntp.orgtime.nist.gov
Some Wi-Fi networks, VPNs, cellular providers, and firewalls block outbound UDP port 123. The app reports each failed server request and continues when at least one server responds.
NTP packets are not authenticated, and this app does not change the iPhone's system clock. The displayed adjustment is a best-effort estimate intended for human time comparison—not for security, scientific measurement, navigation, or other safety-critical use.
AtomicClock/NetworkTimeClient.swiftbuilds and validates NTP packets.AtomicClock/ClockSyncModel.swiftselects samples and owns synchronization state.AtomicClock/ContentView.swiftcontains the SwiftUI interface.AtomicClockTests/AtomicClockTests.swiftcovers packet validation and sample selection.
Issues and pull requests are welcome. See CONTRIBUTING.md before submitting a change.
This project is source-available under the Elastic License 2.0. ELv2 permits use, modification, and redistribution subject to its limitations; it is not an OSI-approved open-source license.