Skip to content

Commit

Permalink
Rename GregorianTimeOfDay to just GregorianTime + add more Date integ…
Browse files Browse the repository at this point in the history
…ration
  • Loading branch information
Jeehut committed Nov 20, 2024
1 parent f392789 commit 53a5400
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 25 deletions.
22 changes: 21 additions & 1 deletion Sources/HandySwift/Extensions/DateExt.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,27 @@
import Foundation

extension Date {
/// Returns a date offset by the specified time interval from this date to the past.
/// Creates a new Date by combining a ``GregorianDay`` with a ``GregorianTime``.
///
/// This initializer allows you to create a Date instance from separate day and time components.
/// The resulting date will be in the specified timezone (defaulting to the current timezone).
///
/// Example:
/// ```swift
/// let day = GregorianDay(year: 2024, month: 3, day: 21)
/// let time = GregorianTime(hour: 14, minute: 30)
/// let eventTime = Date(day: day, time: time)
/// ```
///
/// - Parameters:
/// - day: The GregorianDay representing the date components.
/// - time: The GregorianTime representing the time components.
/// - timeZone: The timezone to use for the date creation. Defaults to the current timezone.
public init(day: GregorianDay, time: GregorianTime, timeZone: TimeZone = .current) {
self = time.date(day: day, timeZone: timeZone)
}

/// Returns a date offset by the specified time interval from this date to the past.
/// This method is useful when you need to calculate a date that occurred a certain duration before the current date instance.
/// For example, if you want to find out what the date was 2 hours ago from a given date, you can use this method by passing the time interval for 2 hours in seconds.
///
Expand Down
8 changes: 4 additions & 4 deletions Sources/HandySwift/HandySwift.docc/Essentials/New Types.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ let todayNextWeek = GregorianDay.today.advanced(by: 7)

> Note: `GregorianDay` conforms to all the protocols you would expect, such as `Codable`, `Hashable`, and `Comparable`. For encoding/decoding, it uses the ISO format as in "2014-07-13".
``GregorianTimeOfDay`` is the counterpart:
``GregorianTime`` is the counterpart:

```swift
let iPhoneAnnounceTime = GregorianTimeOfDay(hour: 09, minute: 41)
let anHourFromNow = GregorianTimeOfDay.now.advanced(by: .hours(1))
let iPhoneAnnounceTime = GregorianTime(hour: 09, minute: 41)
let anHourFromNow = GregorianTime.now.advanced(by: .hours(1))

let date = iPhoneAnnounceTime.date(day: GregorianDay.today) // => Date
```
Expand Down Expand Up @@ -120,7 +120,7 @@ Note that the ``Debouncer`` was stored in a property so ``Debouncer/cancelAll()`
### Date & Time

- ``GregorianDay``
- ``GregorianTimeOfDay``
- ``GregorianTime``

### UI Helpers

Expand Down
15 changes: 15 additions & 0 deletions Sources/HandySwift/Types/GregorianDay.swift
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,21 @@ public struct GregorianDay {
)
return components.date!
}

/// Returns a `Date` representing this day at the specified time.
///
/// - Parameters:
/// - timeOfDay: The time of day to set for the resulting date.
/// - timeZone: The time zone for which to calculate the date. Defaults to the users current timezone.
/// - Returns: A `Date` representing this day at the specified time.
///
/// Example:
/// ```swift
/// let noonToday = GregorianDay.today.date(timeOfDay: .noon) // today at 12:00
/// ```
public func date(timeOfDay: GregorianTime, timeZone: TimeZone = .current) -> Date {
timeOfDay.date(day: self, timeZone: timeZone)
}
}

extension GregorianDay: Codable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import Foundation

/// A time without date info.
///
/// `GregorianTimeOfDay` represents a time of day without any associated date information. It provides functionalities to work with time components like hour, minute, and second, and perform operations such as initializing from a given date, calculating durations, advancing, and reversing time.
/// `GregorianTime` represents a time of day without any associated date information. It provides functionalities to work with time components like hour, minute, and second, and perform operations such as initializing from a given date, calculating durations, advancing, and reversing time.
///
/// Example:
/// ```swift
/// // Initializing from a given date
/// let date = Date()
/// let timeOfDay = GregorianTimeOfDay(date: date)
/// let timeOfDay = GregorianTime(date: date)
///
/// // Calculating duration since the start of the day
/// let durationSinceStartOfDay: Duration = timeOfDay.durationSinceStartOfDay
Expand All @@ -20,7 +20,7 @@ import Foundation
/// // Reversing time by a duration
/// let reversedTime = timeOfDay.reversed(by: .minutes(15))
/// ```
public struct GregorianTimeOfDay {
public struct GregorianTime {
/// The number of days beyond the current day.
public var overflowingDays: Int
/// The hour component of the time.
Expand All @@ -30,7 +30,7 @@ public struct GregorianTimeOfDay {
/// The second component of the time.
public var second: Int

/// Initializes a `GregorianTimeOfDay` instance from a given date.
/// Initializes a `GregorianTime` instance from a given date.
///
/// - Parameter date: The date from which to extract time components.
public init(date: Date) {
Expand All @@ -41,7 +41,7 @@ public struct GregorianTimeOfDay {
self.second = components.second!
}

/// Initializes a `GregorianTimeOfDay` instance with the provided time components.
/// Initializes a `GregorianTime` instance with the provided time components.
///
/// - Parameters:
/// - hour: The hour component.
Expand All @@ -64,7 +64,7 @@ public struct GregorianTimeOfDay {
/// - day: The day to which the time belongs.
/// - timeZone: The time zone to use for the conversion (default is the current time zone).
/// - Returns: A `Date` object representing the time.
public func date(day: GregorianDay, timeZone: TimeZone = Calendar.current.timeZone) -> Date {
public func date(day: GregorianDay, timeZone: TimeZone = .current) -> Date {
let components = DateComponents(
calendar: Calendar(identifier: .gregorian),
timeZone: timeZone,
Expand All @@ -78,7 +78,7 @@ public struct GregorianTimeOfDay {
return components.date!.addingTimeInterval(.days(Double(self.overflowingDays)))
}

/// Initializes a `GregorianTimeOfDay` instance from the duration since the start of the day.
/// Initializes a `GregorianTime` instance from the duration since the start of the day.
///
/// - Parameter durationSinceStartOfDay: The duration since the start of the day.
@available(iOS 16, macOS 13, tvOS 16, visionOS 1, watchOS 9, *)
Expand All @@ -98,48 +98,65 @@ public struct GregorianTimeOfDay {
/// Advances the time by the specified duration.
///
/// - Parameter duration: The duration by which to advance the time.
/// - Returns: A new `GregorianTimeOfDay` instance advanced by the specified duration.
/// - Returns: A new `GregorianTime` instance advanced by the specified duration.
@available(iOS 16, macOS 13, tvOS 16, visionOS 1, watchOS 9, *)
public func advanced(by duration: Duration) -> Self {
GregorianTimeOfDay(durationSinceStartOfDay: self.durationSinceStartOfDay + duration)
GregorianTime(durationSinceStartOfDay: self.durationSinceStartOfDay + duration)
}

/// Reverses the time by the specified duration.
///
/// - Parameter duration: The duration by which to reverse the time.
/// - Returns: A new `GregorianTimeOfDay` instance reversed by the specified duration.
/// - Returns: A new `GregorianTime` instance reversed by the specified duration.
@available(iOS 16, macOS 13, tvOS 16, visionOS 1, watchOS 9, *)
public func reversed(by duration: Duration) -> Self {
GregorianTimeOfDay(durationSinceStartOfDay: self.durationSinceStartOfDay - duration)
GregorianTime(durationSinceStartOfDay: self.durationSinceStartOfDay - duration)
}
}

extension GregorianTimeOfDay: Codable, Hashable, Sendable {}
extension GregorianTimeOfDay: Identifiable {
extension GregorianTime: Codable, Hashable, Sendable {}
extension GregorianTime: Identifiable {
/// The unique identifier of the time, formatted as "hour:minute:second".
public var id: String { "\(self.hour):\(self.minute):\(self.second)" }
}

extension GregorianTimeOfDay: Comparable {
/// Compares two `GregorianTimeOfDay` instances.
extension GregorianTime: Comparable {
/// Compares two `GregorianTime` instances.
///
/// - Parameters:
/// - left: The left-hand side of the comparison.
/// - right: The right-hand side of the comparison.
/// - Returns: `true` if the left time is less than the right time; otherwise, `false`.
public static func < (left: GregorianTimeOfDay, right: GregorianTimeOfDay) -> Bool {
public static func < (left: GregorianTime, right: GregorianTime) -> Bool {
guard left.overflowingDays == right.overflowingDays else { return left.overflowingDays < right.overflowingDays }
guard left.hour == right.hour else { return left.hour < right.hour }
guard left.minute == right.minute else { return left.minute < right.minute }
return left.second < right.second
}
}

extension GregorianTimeOfDay {
extension GregorianTime {
/// The zero time of day (00:00:00).
public static var zero: Self { GregorianTimeOfDay(hour: 0, minute: 0, second: 0) }
public static var zero: Self { GregorianTime(hour: 0, minute: 0, second: 0) }
/// The current time of day.
public static var now: Self { GregorianTimeOfDay(date: Date()) }
public static var now: Self { GregorianTime(date: Date()) }
/// Noon (12:00:00).
public static var noon: Self { GregorianTime(hour: 12, minute: 0, second: 0) }
}

extension GregorianTimeOfDay: Withable {}
extension GregorianTime: Withable {}

/// Provides backward compatibility for the renamed `GregorianTime` type.
///
/// This type has been renamed to ``GregorianTime`` to better reflect its purpose and maintain consistency with other types in the framework.
///
/// Instead of using `GregorianTimeOfDay`, use ``GregorianTime``:
/// ```swift
/// // Old code:
/// let time = GregorianTimeOfDay(hour: 14, minute: 30)
///
/// // New code:
/// let time = GregorianTime(hour: 14, minute: 30)
/// ```
@available(*, deprecated, renamed: "GregorianTime", message: "Use GregorianTime instead. This type has been renamed for better clarity and consistency.")
public typealias GregorianTimeOfDay = GregorianTime

0 comments on commit 53a5400

Please sign in to comment.