Home > Software engineering >  Get Array Of Hours from Two Dates
Get Array Of Hours from Two Dates

Time:06-19

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"]
  • Related