到目前为止,我的解决方案是将日期转换为格式化的字符串并对其进行排序。
例如:
extension Date {
// Helper
func formatted(_ format: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
return dateFormatter.string(from: self)
}
}
let sortedDates = myDates.sorted { $0.formatted("MM/dd") < $1.formatted("MM/dd") }
在不处理字符串的情况下,有没有更好的方法来实现这一点?
答案 0 :(得分:1)
您可以创建一个结构体 MonthDay
,它具有 month
/day
的整数值,并使其符合 Comparable
以便在排序逻辑中使用。< /p>
import Foundation
extension Date {
struct MonthDay: Comparable {
let month: Int
let day: Int
init(date: Date) {
let comps = Calendar.current.dateComponents([.month,.day], from: date)
self.month = comps.month ?? 0
self.day = comps.day ?? 0
}
static func <(lhs: MonthDay, rhs: MonthDay) -> Bool {
return (lhs.month < rhs.month || (lhs.month == rhs.month && lhs.day < rhs.day))
}
}
}
有了上面的内容,您可以通过读取 month
中的 day
/Date
值来轻松排序,如下所示。
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let date1 = dateFormatter.date(from: "2020-07-30")!
let date2 = dateFormatter.date(from: "2021-07-01")!
let date3 = dateFormatter.date(from: "2019-07-28")!
let date4 = dateFormatter.date(from: "2021-06-30")!
let date5 = dateFormatter.date(from: "2016-10-13")!
let dates = [date1, date2, date3, date4, date5]
print(dates.map { dateFormatter.string(from: $0) })
// ["2020-07-30", "2021-07-01", "2019-07-28", "2021-06-30", "2016-10-13"]
let sorted = dates.sorted(by: {
Date.MonthDay(date: $0) < Date.MonthDay(date: $1)
})
print(sorted.map { dateFormatter.string(from: $0) })
// ["2021-06-30", "2021-07-01", "2019-07-28", "2020-07-30", "2016-10-13"]
答案 1 :(得分:1)
如果有人想尝试,这里有一个适用于 Swift 5.5/Xcode 13 beta 的解决方案。
let monthDay = Date.FormatStyle()
.day(.twoDigits)
.month(.twoDigits)
.locale(Locale(identifier: "en_US_POSIX"))
let sortedDates = myDates
.map { ($0.formatted(monthDay), $0) }
.sorted { $0.0 < $1.0 }
.map(\.1)
示例
let day = 24.0 * 60.0 * 60.0
let month = day * 31
let year = day * 365
let myDates: [Date] = [.now,
.now.advanced(by: (year + day)),
.now.advanced(by: -(year + day)),
.now.advanced(by: -3 * day),
.now.advanced(by: 3 * day)
]
收益
<块引用>[2021-06-30 09:57:51 +0000, 2020-07-02 09:57:51 +0000, 2021-07-03 09:57:51 +0000, 2022-07-04 09: 57:51 +0000, 2021-07-06 09:57:51 +0000]
答案 2 :(得分:0)
如果您想避免每次通过排序块时都创建新对象,那么您可以创建一个 Dictionary
,将原始 Date
作为 Key,将 Day/Month 组件作为值.然后可以对其进行排序并作为原始日期的 Array
返回。
func sortDatesByDayMonth(_ dates: [Date]) -> [Date] {
let calendar = Calendar.current
var datesWithDayMonthOnly = [Date : Date]()
for date in dates {
var dateComponents = DateComponents()
dateComponents = calendar.dateComponents([.day, .month], from: date)
let dayMonthDate = calendar.date(from: dateComponents)
datesWithDayMonthOnly[date] = dayMonthDate
}
return datesWithDayMonthOnly.sorted { $0.1 < $1.1 }.map { $0.key }
}
或者作为 Array
的 Tuples
,这将处理两个日期完全相同的罕见情况:
func sortDatesByDayMonth(_ dates: [Date]) -> [Date] {
let calendar = Calendar.current
var datesWithDayMonthOnly = [(date: Date, dayMonthDate: Date)]()
for date in dates {
var dateComponents = DateComponents()
dateComponents = calendar.dateComponents([.day, .month], from: date)
if let dayMonthDate = calendar.date(from: dateComponents) {
datesWithDayMonthOnly.append((date: date, dayMonthDate: dayMonthDate))
}
}
return datesWithDayMonthOnly.sorted { $0.dayMonthDate < $1.dayMonthDate }.map { $0.date }
}
示例:
var dates = [Date]()
for _ in 1...20 {
dates.append(Date(timeIntervalSince1970: Double.random(in: 0...Date().timeIntervalSince1970)))
}
sortDatesByDayMonth(dates)
示例输出:
[2005-01-08 18:26:45 +0000,
1994-01-13 15:13:10 +0000,
1986-01-26 03:48:43 +0000,
1992-02-15 10:40:06 +0000,
2005-03-20 12:33:41 +0000,
1998-04-04 13:23:33 +0000,
1982-04-25 17:21:55 +0000,
1976-05-16 20:59:00 +0000,
1995-05-20 03:53:41 +0000,
2006-07-23 06:50:19 +0000,
2017-08-23 08:16:49 +0000,
1989-08-30 17:47:49 +0000,
1986-09-07 03:05:49 +0000,
1990-09-08 16:09:47 +0000,
2007-10-14 03:46:24 +0000,
1974-10-16 16:06:53 +0000,
1977-11-04 14:15:43 +0000,
1974-11-09 08:55:11 +0000,
2011-12-02 07:23:57 +0000,
1983-12-31 00:22:57 +0000]
答案 3 :(得分:-1)
let date1 = DateComponents(calendar: .current, year: 2022, month: 07, day: 28, hour: 0, minute: 0).date!
let date2 = Date()
let date3 = DateComponents(calendar: .current, year: 1997, month: 06, day: 22, hour: 0, minute: 0).date!
let date4 = DateComponents(calendar: .current, year: 2000, month: 07, day: 02, hour: 0, minute: 0).date!
let date5 = DateComponents(calendar: .current, year: 1997, month: 07, day: 28, hour: 0, minute: 0).date!
let date6 = DateComponents(calendar: .current, year: 2050, month: 08, day: 28, hour: 0, minute: 0).date!
let calendar = Calendar.current
let components = calendar.dateComponents([.month, .day], from: date1)
let components2 = calendar.dateComponents([.month, .day], from: date2)
let components3 = calendar.dateComponents([.month, .day], from: date3)
let components4 = calendar.dateComponents([.month, .day], from: date4)
let components5 = calendar.dateComponents([.month, .day], from: date5)
let components6 = calendar.dateComponents([.month, .day], from: date6)
var arrDate = [components,components2,components3,components4,components5,components6]
arrDate.sort { lhs, rhs in
if lhs.month! > rhs.month! {
return true
}else if lhs.month! < rhs.month!{
return false
}else if lhs.month! == rhs.month!{
if lhs.day! > rhs.day! {
return true
}else if lhs.day! < rhs.day! {
return false
}else {
return false
}
}
return true
}
print(arrDate)
这样检查:)