├── .gitignore
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── contents.xcworkspacedata
├── LICENSE
├── Package.swift
├── README.md
├── Sources
└── appletime
│ └── main.swift
└── makefile
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | /*.xcodeproj
5 | xcuserdata/
6 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Paul Hudson
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.
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.3
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "appletime",
8 | platforms: [
9 | .macOS(.v10_13)
10 | ],
11 | dependencies: [
12 | // Dependencies declare other packages that this package depends on.
13 | // .package(url: /* package url */, from: "1.0.0"),
14 | ],
15 | targets: [
16 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
17 | // Targets can depend on other targets in this package, and on products in packages this package depends on.
18 | .target(
19 | name: "appletime",
20 | dependencies: [])
21 | ]
22 | )
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AppleTime
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | A tiny program that sets the clock in your iOS and iPadOS simulators to be 9:41, which is the time Apple usually uses in its device screenshots. For more information on the back story behind 9:41, [check out this Engadget article](https://www.engadget.com/2014-04-14-why-9-41-am-is-the-always-the-time-displayed-on-iphones-and-ipad.html).
11 |
12 | **Note:** Setting the simulator time is not supported on either tvOS or watchOS.
13 |
14 |
15 | ## Installation
16 |
17 | If you want to install AppleTime, you have three options: [Homebrew](https://brew.sh), [Mint](https://github.com/yonaskolb/Mint), or building it from the command line yourself.
18 |
19 | **Regardless of which installation approach you choose, you must have Xcode installed in order to adjust the simulator time.**
20 |
21 | Use this command for Homebrew:
22 |
23 | ```bash
24 | brew install twostraws/brew/appletime
25 | ```
26 |
27 | Using Homebrew allows you to run `appletime` directly from the command line.
28 |
29 | For Mint, install and run AppleTime with these command:
30 |
31 | ```bash
32 | mint install twostraws/AppleTime@main
33 | mint run appletime@main
34 | ```
35 |
36 | And finally, to build and install the command line tool yourself, clone the repository and run `make install`:
37 |
38 | ```bash
39 | git clone https://github.com/twostraws/AppleTime
40 | cd AppleTime
41 | make install
42 | ```
43 |
44 | As with the Homebrew option, building the command line tool yourself allows you to use the `appletime` command directly from the command line.
45 |
46 |
47 | ## Usage
48 |
49 | Once installed, you can use AppleTime like this:
50 |
51 | * `appletime` sets all running simulator devices to 9:41.
52 | * `appletime reset` resets all simulator devices to default time.
53 | * `appletime "Custom String"` sets a custom message for the time.
54 |
55 | If you need more power – if you want to control the WiFi bars, set a virtual map location, simulate push notifications, and more – you should use my free app [Control Room](https://github.com/twostraws/ControlRoom) instead.
56 |
57 |
58 | ## Credits
59 |
60 | AppleTime was built by Paul Hudson, and is copyright © Paul Hudson 2021.
61 |
62 | AppleTime is licensed under the MIT license; for the full license please see the [LICENSE file](LICENSE). AppleTime is built on top of Apple’s **simctl** command – the team who built that deserve the real credit here.
63 |
64 | Swift, the Swift logo, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries. For the avoidance of doubt, this repository is not affiliated with or sponsored by Apple.
65 |
66 | If you find AppleTime useful, you might find my website full of Swift tutorials equally useful: [Hacking with Swift](https://www.hackingwithswift.com).
67 |
--------------------------------------------------------------------------------
/Sources/appletime/main.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | struct JSONOutput: Decodable {
4 | let devices: [String: [Device]]
5 | }
6 |
7 | struct Device: Decodable {
8 | let udid: String
9 | let state: String
10 | let name: String
11 | }
12 |
13 | /// Handles running one command and sending back its output.
14 | @discardableResult
15 | func run(_ command: String, with arguments: [String]) -> Data {
16 | let task = Process()
17 | task.launchPath = command
18 | task.arguments = arguments
19 |
20 | let pipe = Pipe()
21 | task.standardOutput = pipe
22 |
23 | do {
24 | try task.run()
25 | let data = pipe.fileHandleForReading.readDataToEndOfFile()
26 | return data
27 | } catch {
28 | print("Running simctl failed; please ensure you have Xcode installed.")
29 | print("")
30 | print("Alternatively, run `xcode-select -p` and make sure it points to")
31 | print("your Xcode installation.")
32 | exit(1)
33 | }
34 | }
35 |
36 | /// Prints usage information for AppleTime.
37 | func printHelp() {
38 | print("You can use AppleTime like this:")
39 | print(" appletime \t\t\t Sets all devices to 9:41")
40 | print(" appletime reset \t\t Resets all devices to default time")
41 | print(" appletime \"Custom String\" \t Sets a custom message for the time")
42 | print("")
43 | print("Note: Adjusting the simulator time is not supported on tvOS or watchOS.")
44 | exit(0)
45 | }
46 |
47 | // Start by fetching all simulator data.
48 | let xcrun = "/usr/bin/xcrun"
49 | let listArguments = ["simctl", "list", "devices", "-j"]
50 | let jsonOutput = run(xcrun, with: listArguments)
51 | let decoded = try JSONDecoder().decode(JSONOutput.self, from: jsonOutput)
52 |
53 | // Now figure out which are actually booted.
54 | var bootedDevices = [Device]()
55 |
56 | for device in decoded.devices {
57 | if device.key.contains("watchOS") || device.key.contains("tvOS") { continue }
58 | bootedDevices += device.value.filter { $0.state == "Booted" }
59 | }
60 |
61 | // Assume 9:41 for the new time; we might overwrite this based on user input.
62 | var newTime = "9:41"
63 |
64 | switch CommandLine.arguments.count {
65 | case 2:
66 | // If we're asked to clear, do it and exit.
67 | if CommandLine.arguments[1] == "reset" {
68 | for device in bootedDevices {
69 | let statusBarArguments = ["simctl", "status_bar", device.udid, "clear"]
70 | run(xcrun, with: statusBarArguments)
71 | }
72 |
73 | print("All devices set back to default time.")
74 | } else if CommandLine.arguments[1] == "help" || CommandLine.arguments[1] == "--help" {
75 | // For two special commands print out help then exit
76 | printHelp()
77 | } else {
78 | // Use their input as the new time, then proceed with the next case to update the status bar
79 | newTime = CommandLine.arguments[1]
80 | fallthrough
81 | }
82 |
83 | case 1:
84 | // it's Apple Time, baby!
85 | for device in bootedDevices {
86 | let statusBarArguments = ["simctl", "status_bar", device.udid, "override", "--time", newTime]
87 | run(xcrun, with: statusBarArguments)
88 | }
89 |
90 | print("All devices set to \(newTime).")
91 |
92 | default:
93 | // Ignore all other uses.
94 | printHelp()
95 | }
96 |
--------------------------------------------------------------------------------
/makefile:
--------------------------------------------------------------------------------
1 | install:
2 | swift build -c release
3 | install .build/release/appletime /usr/local/bin/appletime
--------------------------------------------------------------------------------