Есть много способов снять шкуру с кошки, но я мог бы определить доступность как подсчет дня и диапазон времени:
struct Availability {
let dayOfWeek: DayOfWeek
let timeRange: TimeRange
}
Ваш день недели может быть:
enum DayOfWeek: String, CaseIterable {
case sunday, monday, tuesday, wednesday, thursday, friday, saturday
}
Или вы также можете сделать:
enum DayOfWeek: Int, CaseIterable {
case sunday = 0, monday, tuesday, wednesday, thursday, friday, saturday
}
Это плюсы и минусы как Int
, так и String
.Строковое представление легче читать в веб-интерфейсе Firestore.Целочисленное представление предлагает более легкий потенциал сортировки.
Ваш временной диапазон:
typealias Time = Double
typealias TimeRange = Range<Time>
extension TimeRange {
static let allCases: [TimeRange] = [
6 ..< 9,
9 ..< 12,
12 ..< 15,
15 ..< 18,
18 ..< 21,
21 ..< 24,
24 ..< 30
]
}
С точки зрения взаимодействия с Firebase он не понимает перечисления и диапазоны, поэтому я бы определил init
метод и dictionary
свойство для отображения в и из [String: Any]
словарей, которые вы можете обмениваться с Firebase:
struct Availability {
let dayOfWeek: DayOfWeek
let timeRange: TimeRange
init(dayOfWeek: DayOfWeek, timeRange: TimeRange) {
self.dayOfWeek = dayOfWeek
self.timeRange = timeRange
}
init?(dictionary: [String: Any]) {
guard
let dayOfWeekRaw = dictionary["dayOfWeek"] as? DayOfWeek.RawValue,
let dayOfWeek = DayOfWeek(rawValue: dayOfWeekRaw),
let startTime = dictionary["startTime"] as? Double,
let endTime = dictionary["endTime"] as? Double
else {
return nil
}
self.dayOfWeek = dayOfWeek
self.timeRange = startTime ..< endTime
}
var dictionary: [String: Any] {
return [
"dayOfWeek": dayOfWeek.rawValue,
"startTime": timeRange.lowerBound,
"endTime": timeRange.upperBound
]
}
}
Вы также можете определить несколько расширений, чтобы было легче работать сНапример,
extension Availability {
func overlaps(_ availability: Availability) -> Bool {
return dayOfWeek == availability.dayOfWeek && timeRange.overlaps(availability.timeRange)
}
}
extension TimeRange {
private func string(forHour hour: Int) -> String {
switch hour % 24 {
case 0: return NSLocalizedString("Midnight", comment: "Hour text")
case 1...11: return "\(hour % 12)" + NSLocalizedString("am", comment: "Hour text")
case 12: return NSLocalizedString("Noon", comment: "Hour text")
default: return "\(hour % 12)" + NSLocalizedString("pm", comment: "Hour text")
}
}
var text: String {
return string(forHour: Int(lowerBound)) + "-" + string(forHour: Int(upperBound))
}
}
extension DayOfWeek {
var text: String {
switch self {
case .sunday: return NSLocalizedString("Sunday", comment: "DayOfWeek text")
case .monday: return NSLocalizedString("Monday", comment: "DayOfWeek text")
case .tuesday: return NSLocalizedString("Tuesday", comment: "DayOfWeek text")
case .wednesday: return NSLocalizedString("Wednesday", comment: "DayOfWeek text")
case .thursday: return NSLocalizedString("Thursday", comment: "DayOfWeek text")
case .friday: return NSLocalizedString("Friday", comment: "DayOfWeek text")
case .saturday: return NSLocalizedString("Saturday", comment: "DayOfWeek text")
}
}
}
Если вы не хотите использовать Range
, вы можете просто определить TimeRange
как struct
:
enum DayOfWeek: String, CaseIterable {
case sunday, monday, tuesday, wednesday, thursday, friday, saturday
}
extension DayOfWeek {
var text: String {
switch self {
case .sunday: return NSLocalizedString("Sunday", comment: "DayOfWeek text")
case .monday: return NSLocalizedString("Monday", comment: "DayOfWeek text")
case .tuesday: return NSLocalizedString("Tuesday", comment: "DayOfWeek text")
case .wednesday: return NSLocalizedString("Wednesday", comment: "DayOfWeek text")
case .thursday: return NSLocalizedString("Thursday", comment: "DayOfWeek text")
case .friday: return NSLocalizedString("Friday", comment: "DayOfWeek text")
case .saturday: return NSLocalizedString("Saturday", comment: "DayOfWeek text")
}
}
}
struct TimeRange {
typealias Time = Double
let startTime: Time
let endTime: Time
}
extension TimeRange {
static let allCases: [TimeRange] = [
TimeRange(startTime: 6, endTime: 9),
TimeRange(startTime: 9, endTime: 12),
TimeRange(startTime: 12, endTime: 15),
TimeRange(startTime: 15, endTime: 18),
TimeRange(startTime: 18, endTime: 21),
TimeRange(startTime: 21, endTime: 24),
TimeRange(startTime: 24, endTime: 30)
]
func overlaps(_ availability: TimeRange) -> Bool {
return (startTime ..< endTime).overlaps(availability.startTime ..< availability.endTime)
}
}
extension TimeRange {
private func string(forHour hour: Int) -> String {
switch hour % 24 {
case 0: return NSLocalizedString("Midnight", comment: "Hour text")
case 1...11: return "\(hour % 12)" + NSLocalizedString("am", comment: "Hour text")
case 12: return NSLocalizedString("Noon", comment: "Hour text")
default: return "\(hour % 12)" + NSLocalizedString("pm", comment: "Hour text")
}
}
var text: String {
return string(forHour: Int(startTime)) + "-" + string(forHour: Int(endTime))
}
}
struct Availability {
let dayOfWeek: DayOfWeek
let timeRange: TimeRange
init(dayOfWeek: DayOfWeek, timeRange: TimeRange) {
self.dayOfWeek = dayOfWeek
self.timeRange = timeRange
}
init?(dictionary: [String: Any]) {
guard
let dayOfWeekRaw = dictionary["dayOfWeek"] as? DayOfWeek.RawValue,
let dayOfWeek = DayOfWeek(rawValue: dayOfWeekRaw),
let startTime = dictionary["startTime"] as? Double,
let endTime = dictionary["endTime"] as? Double
else {
return nil
}
self.dayOfWeek = dayOfWeek
self.timeRange = TimeRange(startTime: startTime, endTime: endTime)
}
var dictionary: [String: Any] {
return [
"dayOfWeek": dayOfWeek.rawValue,
"startTime": timeRange.startTime,
"endTime": timeRange.endTime
]
}
}
extension Availability {
func overlaps(_ availability: Availability) -> Bool {
return dayOfWeek == availability.dayOfWeek && timeRange.overlaps(availability.timeRange)
}
}