[docs] Extensions.md: Date, Data & Files section
This commit is contained in:
@@ -1389,7 +1389,288 @@ seen.insert(CGPoint(x: 1, y: 2))
|
||||
|
||||
## Date, Data & Files
|
||||
|
||||
<!-- batch 6 -->
|
||||
<details>
|
||||
<summary><b>Date</b> — components, comparisons, formatting, arithmetic, init</summary>
|
||||
|
||||
### Calendar-component accessors
|
||||
Read (and, where noted, write) individual components using the user's current calendar.
|
||||
|
||||
| Property | Get | Set |
|
||||
|---|---|---|
|
||||
| `year` | ✅ | ✅ |
|
||||
| `month` | ✅ | ✅ (clamped to valid range) |
|
||||
| `day` | ✅ | ✅ (clamped) |
|
||||
| `hour` / `minute` / `second` | ✅ | ✅ (clamped) |
|
||||
| `nanosecond` / `millisecond` | ✅ | ✅ (clamped) |
|
||||
| `weekday` / `weekOfMonth` / `weekOfYear` / `quarter` / `era` | ✅ | — |
|
||||
| `calendar` | ✅ (`Calendar.current`) | — |
|
||||
|
||||
```swift
|
||||
var d = Date()
|
||||
d.year = 2030 // shifts the date to 2030, keeping everything else
|
||||
d.minute = 0
|
||||
Date().weekday // 1 = Sunday (Gregorian)
|
||||
```
|
||||
|
||||
### Relative checks
|
||||
`isInFuture`, `isInPast`, `isInToday`, `isInYesterday`, `isInTomorrow`,
|
||||
`isInWeekend`, `isWorkday`, `isInCurrentWeek`, `isInCurrentMonth`, `isInCurrentYear`.
|
||||
|
||||
```swift
|
||||
someDate.isInToday // Bool
|
||||
someDate.isInWeekend // Bool
|
||||
```
|
||||
|
||||
### `func isInCurrent(_ component: Calendar.Component) -> Bool`
|
||||
Same granularity check, for an arbitrary component.
|
||||
|
||||
```swift
|
||||
Date().isInCurrent(.year) // true
|
||||
```
|
||||
|
||||
### `var iso8601String: String` / `var unixTimestamp: Double`
|
||||
`yyyy-MM-dd'T'HH:mm:ss.SSS` + `Z` (GMT); seconds since 1970.
|
||||
|
||||
```swift
|
||||
Date().iso8601String // "2026-08-29T14:51:29.574Z"
|
||||
```
|
||||
|
||||
### Rounding
|
||||
`nearestFiveMinutes`, `nearestTenMinutes`, `nearestQuarterHour`, `nearestHalfHour`, `nearestHour` — all return a new `Date`.
|
||||
|
||||
```swift
|
||||
var d = Date(); d.minute = 44
|
||||
d.nearestFiveMinutes // :45
|
||||
d.nearestHour // rounds up because minute ≥ 30
|
||||
```
|
||||
|
||||
### `var yesterday: Date` / `var tomorrow: Date`
|
||||
±1 day.
|
||||
|
||||
### `func adding(_:value:) -> Date` / `mutating func add(_:value:)`
|
||||
Add multiples of a calendar component.
|
||||
|
||||
```swift
|
||||
Date().adding(.day, value: 7) // one week later
|
||||
var d = Date(); d.add(.month, value: -1)
|
||||
```
|
||||
|
||||
### `func changing(_:value:) -> Date?`
|
||||
Set one component to a specific value (validated; `nil` if out of range).
|
||||
|
||||
```swift
|
||||
Date().changing(.hour, value: 9) // 9am today
|
||||
```
|
||||
|
||||
### `func beginning(of component:) -> Date?` / `func end(of component:) -> Date?`
|
||||
Start / end instant of the enclosing `.day` / `.month` / `.year` / `.hour` / week, etc.
|
||||
|
||||
```swift
|
||||
Date().beginning(of: .month) // 1st, 00:00:00
|
||||
Date().end(of: .day) // 23:59:59
|
||||
```
|
||||
|
||||
### Differences
|
||||
`secondsSince(_:)`, `minutesSince(_:)`, `hoursSince(_:)`, `daysSince(_:)` — signed `Double`.
|
||||
|
||||
```swift
|
||||
endDate.hoursSince(startDate) // e.g. 3.5
|
||||
```
|
||||
|
||||
### `func isBetween(_ start: Date, _ end: Date, includeBounds: Bool = false) -> Bool`
|
||||
Range check.
|
||||
|
||||
### `func isWithin(_ value: UInt, _ component: Calendar.Component, of date: Date) -> Bool`
|
||||
Whether two dates are within N components of each other.
|
||||
|
||||
```swift
|
||||
a.isWithin(3, .day, of: b) // true if ≤ 3 days apart
|
||||
```
|
||||
|
||||
### Formatting
|
||||
| Method | Example output |
|
||||
|---|---|
|
||||
| `string(withFormat: String = "dd/MM/yyyy HH:mm")` | `"29/08/2026 14:30"` |
|
||||
| `dateString(ofStyle: .medium)` | `"Aug 29, 2026"` |
|
||||
| `dateTimeString(ofStyle: .short)` | `"8/29/26, 2:30 PM"` |
|
||||
| `timeString(ofStyle: .short)` | `"2:30 PM"` |
|
||||
| `dayName(ofStyle: .full / .threeLetters / .oneLetter)` | `"Saturday"` / `"Sat"` / `"S"` |
|
||||
| `monthName(ofStyle: .full / .threeLetters / .oneLetter)` | `"August"` / `"Aug"` / `"A"` |
|
||||
|
||||
```swift
|
||||
Date().string(withFormat: "yyyy-MM-dd") // "2026-08-29"
|
||||
Date().dayName(ofStyle: .threeLetters) // "Sat"
|
||||
```
|
||||
|
||||
### Random dates
|
||||
`static func random(in: Range<Date>) -> Date`, plus `ClosedRange` and
|
||||
`using generator:` variants.
|
||||
|
||||
```swift
|
||||
Date.random(in: startDate...endDate)
|
||||
```
|
||||
|
||||
### Initializers
|
||||
- `init?(calendar:timeZone:era:year:month:day:hour:minute:second:nanosecond:)` — every field defaults to "now".
|
||||
- `init?(iso8601String:)` — parse `yyyy-MM-dd'T'HH:mm:ss.SSSZ`.
|
||||
- `init(unixTimestamp:)` — seconds since 1970.
|
||||
- `init?(integerLiteral:)` — parse a packed `yyyyMMdd` integer.
|
||||
|
||||
```swift
|
||||
Date(year: 2010, month: 1, day: 12)
|
||||
Date(iso8601String: "2026-01-12T16:48:00.959Z")
|
||||
Date(integerLiteral: 2026_12_25)
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Data</b> — JSON, hashing, hex, XOR, decoding</summary>
|
||||
|
||||
### `var prettyJson: String?`
|
||||
Pretty-printed JSON if the data is a valid JSON value.
|
||||
|
||||
```swift
|
||||
responseData.prettyJson
|
||||
```
|
||||
|
||||
### `var toDictionay: [String: Any]?`
|
||||
Parse a JSON object to a dictionary (note the spelling — `toDictionay`).
|
||||
|
||||
### `var toHexString: String` / `func toHexadecimalString() -> String`
|
||||
Lower-case hex representation of the bytes.
|
||||
|
||||
```swift
|
||||
Data([0x0f, 0xa0]).toHexString // "0fa0"
|
||||
```
|
||||
|
||||
### `var bool: Bool`
|
||||
`first != 0`.
|
||||
|
||||
### `init?(hexString:)`
|
||||
Parse a hex string (spaces allowed) to bytes; `nil` on an invalid nibble.
|
||||
|
||||
```swift
|
||||
Data(hexString: "0f a0") // 2 bytes
|
||||
```
|
||||
|
||||
### `func SHA256() -> Data` / `func SHA512() -> Data`
|
||||
CommonCrypto digests (empty `Data` if CommonCrypto is unavailable).
|
||||
|
||||
```swift
|
||||
Data("abc".utf8).SHA256().toHexString
|
||||
```
|
||||
|
||||
### `func HMACSHA512(key: Data) -> Data` — *iOS 13+*
|
||||
CryptoKit HMAC-SHA512.
|
||||
|
||||
```swift
|
||||
message.HMACSHA512(key: secret)
|
||||
```
|
||||
|
||||
### `func XOR(with other: Data) -> Data`
|
||||
Byte-wise XOR (result length = shorter of the two).
|
||||
|
||||
```swift
|
||||
a.XOR(with: pad)
|
||||
```
|
||||
|
||||
### `static func MD5(string:) -> Data` — *iOS 13+*
|
||||
MD5 of a string (insecure — legacy interop only). Returns the hex digest **as UTF-8 bytes**.
|
||||
|
||||
```swift
|
||||
Data.MD5(string: "Hello").toHexString
|
||||
```
|
||||
|
||||
### `func object<T: Codable & Sendable>() -> T?`
|
||||
Decode JSON data to `T`, `nil` + logs on failure.
|
||||
|
||||
```swift
|
||||
let user: User? = responseData.object()
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>URL</b></summary>
|
||||
|
||||
### `var params: [String: String]`
|
||||
Query items as a dictionary (missing values become `""`).
|
||||
|
||||
```swift
|
||||
URL(string: "https://x.com?a=1&b=2")!.params // ["a": "1", "b": "2"]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>FileManager</b> — Documents-directory helpers</summary>
|
||||
|
||||
### `func createDirectory(_ directoryName: String) -> URL?`
|
||||
Create (if missing) a folder under Documents; returns its URL.
|
||||
|
||||
```swift
|
||||
let dir = FileManager.default.createDirectory("cache")
|
||||
```
|
||||
|
||||
### `func retrieveFile(_ directoryAndFile: String) -> URL`
|
||||
Build a `file://` URL under Documents for the given relative path (no existence check).
|
||||
|
||||
### `func convertToURL(path: String) -> URL?`
|
||||
Directory URL under Documents, or `nil` if it can't be listed.
|
||||
|
||||
### `func saveFileToDirectory(_ sourceURL: URL, toPathURL: URL) -> Bool`
|
||||
`moveItem(at:to:)`, returning success.
|
||||
|
||||
### `func saveImageToDirectory(_ imageWithPath: String, imagem: UIImage) -> Bool` — *UIKit only*
|
||||
Write a `UIImage` as PNG to an absolute path.
|
||||
|
||||
```swift
|
||||
FileManager.default.saveImageToDirectory(path, imagem: photo)
|
||||
```
|
||||
|
||||
### `func removeFile(_ directoryAndFile: String) -> Bool`
|
||||
`removeItem(atPath:)`, returning success.
|
||||
|
||||
### `func retrieveAllFilesFromDirectory(directoryName: String) -> [String]?`
|
||||
File names in a Documents sub-folder (`.DS_Store` filtered out).
|
||||
|
||||
### `func directoryExistsAtPath(_ path: String) -> Bool`
|
||||
Exists **and** is a directory.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>UserDefaults</b> — Codable storage, common flags (<code>@MainActor</code>)</summary>
|
||||
|
||||
### `var isLoggedIn: Bool` / `var isFirstTimeOnApp: Bool`
|
||||
Ready-made boolean flags (keys `"isLoggedIn"` / `"isFirstTimeOnApp"`), auto-`synchronize()` on set.
|
||||
|
||||
```swift
|
||||
UserDefaults.standard.isFirstTimeOnApp = false
|
||||
```
|
||||
|
||||
### `func set<T: Codable>(object: T, forKey key: String, usingEncoder: = JSONEncoder())`
|
||||
Encode and store any `Codable` value.
|
||||
|
||||
### `func object<T: Codable>(_ type: T.Type, with key: String, usingDecoder: = JSONDecoder()) -> T?`
|
||||
Decode a stored `Codable` value.
|
||||
|
||||
```swift
|
||||
UserDefaults.standard.set(object: user, forKey: "user")
|
||||
let user = UserDefaults.standard.object(User.self, with: "user")
|
||||
```
|
||||
|
||||
### `func removeSavedObject(forKey:) -> Bool`
|
||||
Remove a value **only if it is a String**; returns whether it removed anything.
|
||||
|
||||
### `func removeAllSaved()`
|
||||
Wipe the app's entire persistent domain.
|
||||
|
||||
### `func showEverything() -> [String: Any]`
|
||||
Full `dictionaryRepresentation()` — handy for debugging.
|
||||
|
||||
</details>
|
||||
|
||||
## Encoding & Errors
|
||||
|
||||
|
||||
Reference in New Issue
Block a user