I am trying to build a swiftui app, i am trying to get the hours from the dates, so my dates are: 09.12.2022 09:00-09.13.2022 09:00
I have got it to tell me that there is 24 hours between the dates but i want to show the dates like 09:00,10:00,11:00,12:00,13:00 and so on until it reaches the closing date
this is my code so far. Its returning the hours to build a foreachloop on my screen.
func getHours(times:String)-> Int{
let fullNameArr : [String] = times.components(separatedBy: "-")
print(fullNameArr[0])
print(fullNameArr[1])
// Create Date Formatter
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MM.dd.yyyy HH:mm"
let date1 = dateFormatter.date(from: fullNameArr[0])!
let date2 = dateFormatter.date(from: fullNameArr[1])!
let cal = Calendar.current
let components = cal.dateComponents([.hour], from: date1, to: date2)
let diff = components.hour!
for i in stride(from: 0, to: diff, by: 1) {
print(i)
}
return diff
}
CodePudding user response:
What you need is to use Calendar method nextDate(after:)
and match component minute equal to zero:
func getHours(times: String)-> [String] {
let components = times.components(separatedBy: "-")
guard components.count == 2,
var start = DateFormatter.custom.date(from: components[0]),
let end = DateFormatter.custom.date(from: components[1]),
start < end else {
return []
}
var dates: [Date] = []
if start.minute == 0 {
dates.append(start)
}
while start < end {
guard let date = Calendar(identifier: .iso8601).nextDate(after: start, matching: DateComponents(minute: 0), matchingPolicy: .strict) else {
continue
}
if date < end { // If you want to include the end date as well just remove this condition
dates.append(date)
}
start = date
}
return dates.map(DateFormatter.time.string)
}
You will need those date formatters
extension DateFormatter {
static let custom: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.calendar = .init(identifier: .iso8601)
dateFormatter.locale = .init(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "MM.dd.yyyy HH:mm"
return dateFormatter
}()
static let time: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.calendar = .init(identifier: .iso8601)
dateFormatter.locale = .init(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "HH:mm"
return dateFormatter
}()
}
And this Date extension:
extension Date {
var minute: Int {
Calendar(identifier: .iso8601).component(.minute, from: self)
}
}
usage:
let times = "09.12.2022 09:00-09.13.2022 09:00"
print(getHours(times: times))
This will print
["09:00", "10:00", "11:00", "12:00", "13:00", "14:00", "15:00", "16:00", "17:00", "18:00", "19:00", "20:00", "21:00", "22:00", "23:00", "00:00", "01:00", "02:00", "03:00", "04:00", "05:00", "06:00", "07:00", "08:00"]
CodePudding user response:
You already know how to get the hour difference:
let endDate = Date()
let startDate = endDate - 24.0 * 60.0 * 60.0
let diffHours = Calendar.current
.dateComponents([.hour], from: startDate, to: endDate)
Now we are going to make a Range
of hours from zero to diffHours
. Then we are going to map that range of hours to an Array
of Date
ranging from startDate
to endDate
Then we are going to map to an Array
of hour values. Then we are going to map to an Array
of String
formatted as 01:00
.
let hours = (0...(diffHours.hour ?? 0))
.compactMap { Calendar.current.date(byAdding: .hour, value: $0, to: startDate) }
.map { Calendar.current.component(.hour, from: $0) }
.map { String(format: "d:00", $0) }
%d
tells the formatter you want an integer
d
tells the formatter you want two digits with a leading zero
Now let's see what we have:
print("ZZZ range:", (startDate..<endDate).formatted())
print("ZZZ hours:", hours)
Prints:
ZZZ range: 6/17/22, 1:50 PM – 6/18/22, 1:50 PM
ZZZ hours: ["13:00", "14:00", "15:00", "16:00", "17:00", "18:00", "19:00", "20:00", "21:00", "22:00", "23:00", "00:00", "01:00", "02:00", "03:00", "04:00", "05:00", "06:00", "07:00", "08:00", "09:00", "10:00", "11:00", "12:00", "13:00"]