简体   繁体   中英

Swift - Create consecutive date arrays from array of dates

So I have an array of Date objects, for example:

[2020-09-07 00:00:00 +0000, 2020-09-14 00:00:00 +0000, 2020-09-15 00:00:00 +0000, 2020-09-16 00:00:00 +0000, 2020-09-23 00:00:00 +0000, 2020-10-12 00:00:00 +0000, 2020-10-13 00:00:00 +0000, 2020-10-14 00:00:00 +0000, 2020-10-15 00:00:00 +0000, 2020-10-16 00:00:00 +0000]

I have to split up this array into multiple arrays containing consecutive date ranges. The result should be like this:

[2020-09-07 00:00:00 +0000],
[2020-09-14 00:00:00 +0000, 2020-09-15 00:00:00 +0000, 2020-09-16 00:00:00 +0000], 
[2020-09-23 00:00:00 +0000], 
[2020-10-12 00:00:00 +0000, 2020-10-13 00:00:00 +0000, 2020-10-14 00:00:00 +0000, 2020-10-15 00:00:00 +0000, 2020-10-16 00:00:00 +0000]

What is the best way to achieve this in Swift?

You can create some helpers to get a time insensitive date and the date after a date to compare your dates for equality as shown in this post and group the dates as shown in this post :

extension Date {
    var dayAfter: Date { Calendar.current.date(byAdding: .day, value: 1, to: noon)! }
    var noon: Date { Calendar.current.date(bySettingHour: 12, minute: 0, second: 0, of: self)! }
}

extension Collection where Element == Date {
    var grouped: [[Element]] {
        return reduce(into: []) {
            $0.last?.last?.dayAfter == $1.noon ?
            $0[$0.index(before: $0.endIndex)].append($1) :
            $0.append([$1])
        }
    }
}

extension Formatter {
    static let iso8601: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
        formatter.timeZone = TimeZone.init(secondsFromGMT: 0)!
        return formatter
    }()
}

let arr = ["2020-09-07 00:00:00 +0000", "2020-09-14 00:00:00 +0000", "2020-09-15 00:00:00 +0000", "2020-09-16 00:00:00 +0000", "2020-09-23 00:00:00 +0000", "2020-10-12 00:00:00 +0000", "2020-10-13 00:00:00 +0000", "2020-10-14 00:00:00 +0000", "2020-10-15 00:00:00 +0000", "2020-10-16 00:00:00 +0000"]
let dates = arr.compactMap(Formatter.iso8601.date)
let grouped = dates.grouped
print(grouped)  // [[2020-09-07 00:00:00 +0000], [2020-09-14 00:00:00 +0000, 2020-09-15 00:00:00 +0000, 2020-09-16 00:00:00 +0000], [2020-09-23 00:00:00 +0000], [2020-10-12 00:00:00 +0000, 2020-10-13 00:00:00 +0000, 2020-10-14 00:00:00 +0000, 2020-10-15 00:00:00 +0000, 2020-10-16 00:00:00 +0000]]

 // to convert the dates back to strings:
 let dateStrings = grouped.map { $0.map(Formatter.iso8601.string) }
 print(dateStrings)  // [["2020-09-07 00:00:00 +0000"], ["2020-09-14 00:00:00 +0000", "2020-09-15 00:00:00 +0000", "2020-09-16 00:00:00 +0000"], ["2020-09-23 00:00:00 +0000"], ["2020-10-12 00:00:00 +0000", "2020-10-13 00:00:00 +0000", "2020-10-14 00:00:00 +0000", "2020-10-15 00:00:00 +0000", "2020-10-16 00:00:00 +0000"]]

Let's assume your String array is,

let arr = ["2020-09-07 00:00:00 +0000", "2020-09-14 00:00:00 +0000", "2020-09-15 00:00:00 +0000", "2020-09-16 00:00:00 +0000", "2020-09-23 00:00:00 +0000", "2020-10-12 00:00:00 +0000", "2020-10-13 00:00:00 +0000", "2020-10-14 00:00:00 +0000", "2020-10-15 00:00:00 +0000", "2020-10-16 00:00:00 +0000"]

1. Get dateArr of type [Date] using are ,

let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss Z"
let dateArr = arr.compactMap { formatter.date(from: $0) }

2. Sort the dateArr in ascending order,

let sortedDateArr = dateArr.sorted { $0.compare($1) == .orderedAscending }

3. You can now split up the sortedDateArr like so,

var result = [[String]]()
var tempArr = [String]()
for (index, date) in sortedDateArr.enumerated() {
    tempArr.append(formatter.string(from: date))
    if index+1 < sortedDateArr.count {
        if let days = Calendar.current.dateComponents([.day], from: date, to: sortedDateArr[index+1]).day, days > 1 {
            result.append(tempArr)
            tempArr = []
        }
    } else {
        result.append(tempArr)
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM