I would like to create a tuple list of times like so; every hour going from 0 to 23.
tuple = [(2017-03-24 00:00:00 +0000, 0.0), (2017-03-24 00:01:00 +0000, 0.0), (2017-03-24 00:02:00 +0000, 0.0), (2017-03-24 00:03:00 +0000, 0.0)]
I have tried to use this code which will give me the hours and minutes, however I cannot seem to figure out how to either add the current month, day and year. Or adjust the date format in the Struct.
Thank you for your help. Here is the Struct that I'm using...
import Foundation
struct TimeDay {
let start: TimeInterval
let end: TimeInterval
let interval: TimeInterval
init(start: TimeInterval, interval: TimeInterval, end: TimeInterval) {
self.start = start
self.interval = interval
self.end = end
}
init(startHour: TimeInterval, intervalMinutes: TimeInterval, endHour: TimeInterval) {
self.start = startHour * 60 * 60
self.end = endHour * 60 * 60
self.interval = intervalMinutes * 60
}
var timeRepresentations: [String] {
let dateComponentFormatter = DateComponentsFormatter()
dateComponentFormatter.unitsStyle = .positional
dateComponentFormatter.allowedUnits = [.minute, .hour]
let dateComponent = NSDateComponents()
return timeIntervals.map { timeInterval in
dateComponent.second = Int(timeInterval)
return dateComponentFormatter.string(from: dateComponent as DateComponents)!
}
}
var timeIntervals: [TimeInterval]{
return Array(stride(from: start, through: end, by: interval))
}
}
A month can have between 28 to 31 days. You can't convert it into an exact number of seconds. Use DateComponents
to store your step:
struct TimeDay {
var startDate: Date
var endDate: Date
var step: DateComponents
var calendar = Calendar.autoupdatingCurrent
var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
return formatter
}()
init(startDate: Date, endDate: Date, step: DateComponents) {
self.startDate = startDate
self.endDate = endDate
self.step = step
}
var timeIntervals : [Date] {
guard self.startDate <= self.endDate else {
return []
}
var result = [self.startDate]
var date = self.startDate
while date < self.endDate {
date = self.calendar.date(byAdding: step, to: date)!
result.append(date)
}
return result
}
var timeRepresentation : [String] {
return self.timeIntervals.map { self.dateFormatter.string(from: $0) }
}
}
Example 1: iterate by hour
let startDate1 = DateComponents(calendar: .current, year: 2017, month: 3, day: 24).date!
let endDate1 = DateComponents(calendar: .current, year: 2017, month: 3, day: 25).date!
let t1 = TimeDay(startDate: startDate1, endDate: endDate1, step: DateComponents(hour: 1))
print(t1.timeRepresentation)
Example 2: iterate by month
// Iterate by month
let startDate2 = DateComponents(calendar: .current, year: 2017, month: 1, day: 1).date!
let endDate2 = DateComponents(calendar: .current, year: 2017, month: 12, day: 31).date!
let t2 = TimeDay(startDate: startDate2, endDate: endDate2, step: DateComponents(month: 1))
print(t2.timeRepresentation)
Example 3: you can also mix up the time units and iterate by 1 month and 5 days:
let t3 = TimeDay(startDate: startDate2, endDate: endDate2, step: DateComponents(month: 1, day: 5))
print(t3.timeRepresentation)
Edit:
If you want to find the closest hour: (1) move forward to the next hour; (2) move backward to the last hour; (3) select the one that's closest to the specified date
let date = Date()
let closestHour = ([.backward, .forward] as [Calendar.SearchDirection])
.flatMap { Calendar.current.nextDate(after: date, matching: DateComponents(minute: 0), matchingPolicy: .nextTime, repeatedTimePolicy: .first, direction: $0) }
.min { abs($0.timeIntervalSince(date)) < abs($1.timeIntervalSince(date)) }