[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
|
## 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
|
## Encoding & Errors
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user