如何使用 NSPredicate 比较对象数组中的两个日期字符串?
How can I compare two date string in array of Objects using NSPredicate?
我想使用 NSPredicate
比较每个对象的日期。如果对象具有相同的创建日期,它将 return 具有相同日期的对象数组。
在下面的字典数组中,索引 0 的日期与另一个索引的日期不同,我怎样才能得到这样的数据。
例如:
{
"Data": [
{
"id": "c9967156ad8945fba8cc482cd8aad900",
"description": "Hi",
"dateCreated": "2018-03-20T06:15:11.000+0000",
},
{
"id": "343e70818044457b884f7ad1907803fa",
"description": "The only ",
"dateCreated": "2018-03-16T17:22:50.000+0000",
},
{
"id": "dd542edfaa364e40ae0ef0562b6831be",
"description": "The new ",
"dateCreated": "2018-03-16T17:10:36.000+0000",
},
{
"id": "090f43c83e5b42039f70b133d031e715",
"description": "The new version ",
"dateCreated": "2018-03-16T17:08:07.000+0000",
},
{
"id": "b2ddb8fa990843a28f0670d2b88e3d01",
"description": "Add to the test",
"dateCreated": "2018-03-16T17:08:07.000+0000",
}
]
}
#Edit1:
我正在将 dateCreated String
对象转换为 Date
,然后我使用 NSPredicate
获取所需数据。目前,我正在尝试 NSPredicate
#Edit2
目前,我没有使用 NSPredicate。我正在迭代数组的每个元素并比较其日期
if let dateCur = dateCreated.dateFromISO8601 {
if let datePrev = dateCreatedPrev.dateFromISO8601 {
let curLocal = ISO8601.getStringDate(dateCur). // dd/MM/yyyy
let prevLocal = ISO8601.getStringDate(datePrev). // dd/MM/yyyy
if (curLocal.compare(prevLocal) != .orderedSame {
//diffrent
}else {
//same
}
}
}
我正在使用扩展来实现它
extension Date {
func getFormatter() -> DateFormatter {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .gregorian)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
return formatter
}
var iso8601: String {
return Formatter.iso8601.string(from: self)
}
extension String {
var dateFromISO8601: Date? {
return Formatter.iso8601.date(from: self) // "Mar 22, 2017, 10:22 AM"
}
}
你能帮帮我吗
首先没有必要在Swift中使用NSPredicate
(除了需要NSPredicate
的API)。
原生的filter
方法比较合适
我建议解码 JSON
let jsonString = """
{
"Data": [
{"id": "c9967156ad8945fba8cc482cd8aad900", "description": "Hi", "dateCreated": "2018-03-20T06:15:11.000+0000"},
{"id": "343e70818044457b884f7ad1907803fa", "description": "The only ", "dateCreated": "2018-03-16T17:22:50.000+0000"},
{"id": "dd542edfaa364e40ae0ef0562b6831be", "description": "The new ", "dateCreated": "2018-03-16T17:10:36.000+0000"},
{"id": "090f43c83e5b42039f70b133d031e715", "description": "The new version ", "dateCreated": "2018-03-16T17:08:07.000+0000"},
{"id": "b2ddb8fa990843a28f0670d2b88e3d01", "description": "Add to the test", "dateCreated": "2018-03-16T17:08:07.000+0000"}
]
}
"""
进入自定义结构
struct Root : Decodable {
private enum CodingKeys : String, CodingKey { case items = "Data" }
let items : [Item]
}
struct Item : Decodable {
let id, description : String
let dateCreated : Date
}
解码器使用自定义日期格式化程序正确解码 ISO8601 日期
let data = Data(jsonString.utf8)
let decoder = JSONDecoder()
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SZ"
decoder.dateDecodingStrategy = .formatted(dateFormatter)
do {
let result = try decoder.decode(Root.self, from: data)
数组在result.items
中。现在您可以 filter
特定日期的数组。在此示例中,参考日期创建为 hard-coded 和 DateComponents
。
let components = DateComponents(timeZone: TimeZone(secondsFromGMT: 0), year:2018, month:03, day:16, hour:17, minute:8, second:7)
let date = Calendar.current.date(from: components)!
let filteredItems = result.items.filter { [=13=].dateCreated == date }
print(filteredItems)
} catch { print(error) }
如果您想在数组中查找给定日期的所有匹配记录,请使用循环
for item in result.items {
let filteredItems = result.items.filter { [=14=].dateCreated == item.dateCreated }
if filteredItems.count > 1 { print(filteredItems) }
}
您可以查看 Dictionary
的初始化程序 init(grouping:by:)
,它在 Swift 4.
中引入
你应该有你的对象数组。然后你可以将它们分组到 [String:Object]
其中 key
将是你的 Date
yyyy-MM-dd
格式为 String
.
Prerequisites: Your dateCreated
property should be in Date
format.
let groupedObjectBySameDate = Dictionary(grouping: objects) { (object) -> String in
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter.string(from: object.dateCreated)
}
一个例子:
由于我不了解您的数据结构,因此我提供了一个简单的示例,可以帮助您了解正在发生的事情。
var dateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SZ"
formatter.locale = Locale(identifier: "en_US_POSIX")
return formatter
}
let stringDates = ["2018-03-20T06:15:11.000+0000", "2018-03-16T17:22:50.000+0000", "2018-03-16T17:10:36.000+0000", "2018-03-16T17:08:07.000+0000", "2018-03-16T17:08:07.000+0000"]
let dates = stringDates.map { (each) -> Date in
return dateFormatter.date(from: each) ?? Date(timeIntervalSinceReferenceDate: 0)
}
let groupedObjectBySameDate = Dictionary(grouping: dates) { (date) -> String in
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter.string(from: date)
}
print(groupedObjectBySameDate)
// This will produce:
// [
// "2018-03-20": [2018-03-20 06:15:11 +0000],
// "2018-03-16": [2018-03-16 17:22:50 +0000, 2018-03-16 17:10:36 +0000, 2018-03-16 17:08:07 +0000, 2018-03-16 17:08:07 +0000]
// ]
我想使用 NSPredicate
比较每个对象的日期。如果对象具有相同的创建日期,它将 return 具有相同日期的对象数组。
在下面的字典数组中,索引 0 的日期与另一个索引的日期不同,我怎样才能得到这样的数据。
例如:
{
"Data": [
{
"id": "c9967156ad8945fba8cc482cd8aad900",
"description": "Hi",
"dateCreated": "2018-03-20T06:15:11.000+0000",
},
{
"id": "343e70818044457b884f7ad1907803fa",
"description": "The only ",
"dateCreated": "2018-03-16T17:22:50.000+0000",
},
{
"id": "dd542edfaa364e40ae0ef0562b6831be",
"description": "The new ",
"dateCreated": "2018-03-16T17:10:36.000+0000",
},
{
"id": "090f43c83e5b42039f70b133d031e715",
"description": "The new version ",
"dateCreated": "2018-03-16T17:08:07.000+0000",
},
{
"id": "b2ddb8fa990843a28f0670d2b88e3d01",
"description": "Add to the test",
"dateCreated": "2018-03-16T17:08:07.000+0000",
}
]
}
#Edit1:
我正在将 dateCreated String
对象转换为 Date
,然后我使用 NSPredicate
获取所需数据。目前,我正在尝试 NSPredicate
#Edit2 目前,我没有使用 NSPredicate。我正在迭代数组的每个元素并比较其日期
if let dateCur = dateCreated.dateFromISO8601 {
if let datePrev = dateCreatedPrev.dateFromISO8601 {
let curLocal = ISO8601.getStringDate(dateCur). // dd/MM/yyyy
let prevLocal = ISO8601.getStringDate(datePrev). // dd/MM/yyyy
if (curLocal.compare(prevLocal) != .orderedSame {
//diffrent
}else {
//same
}
}
}
我正在使用扩展来实现它
extension Date {
func getFormatter() -> DateFormatter {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .gregorian)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
return formatter
}
var iso8601: String {
return Formatter.iso8601.string(from: self)
}
extension String {
var dateFromISO8601: Date? {
return Formatter.iso8601.date(from: self) // "Mar 22, 2017, 10:22 AM"
}
}
你能帮帮我吗
首先没有必要在Swift中使用NSPredicate
(除了需要NSPredicate
的API)。
原生的filter
方法比较合适
我建议解码 JSON
let jsonString = """
{
"Data": [
{"id": "c9967156ad8945fba8cc482cd8aad900", "description": "Hi", "dateCreated": "2018-03-20T06:15:11.000+0000"},
{"id": "343e70818044457b884f7ad1907803fa", "description": "The only ", "dateCreated": "2018-03-16T17:22:50.000+0000"},
{"id": "dd542edfaa364e40ae0ef0562b6831be", "description": "The new ", "dateCreated": "2018-03-16T17:10:36.000+0000"},
{"id": "090f43c83e5b42039f70b133d031e715", "description": "The new version ", "dateCreated": "2018-03-16T17:08:07.000+0000"},
{"id": "b2ddb8fa990843a28f0670d2b88e3d01", "description": "Add to the test", "dateCreated": "2018-03-16T17:08:07.000+0000"}
]
}
"""
进入自定义结构
struct Root : Decodable {
private enum CodingKeys : String, CodingKey { case items = "Data" }
let items : [Item]
}
struct Item : Decodable {
let id, description : String
let dateCreated : Date
}
解码器使用自定义日期格式化程序正确解码 ISO8601 日期
let data = Data(jsonString.utf8)
let decoder = JSONDecoder()
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SZ"
decoder.dateDecodingStrategy = .formatted(dateFormatter)
do {
let result = try decoder.decode(Root.self, from: data)
数组在result.items
中。现在您可以 filter
特定日期的数组。在此示例中,参考日期创建为 hard-coded 和 DateComponents
。
let components = DateComponents(timeZone: TimeZone(secondsFromGMT: 0), year:2018, month:03, day:16, hour:17, minute:8, second:7)
let date = Calendar.current.date(from: components)!
let filteredItems = result.items.filter { [=13=].dateCreated == date }
print(filteredItems)
} catch { print(error) }
如果您想在数组中查找给定日期的所有匹配记录,请使用循环
for item in result.items {
let filteredItems = result.items.filter { [=14=].dateCreated == item.dateCreated }
if filteredItems.count > 1 { print(filteredItems) }
}
您可以查看 Dictionary
的初始化程序 init(grouping:by:)
,它在 Swift 4.
你应该有你的对象数组。然后你可以将它们分组到 [String:Object]
其中 key
将是你的 Date
yyyy-MM-dd
格式为 String
.
Prerequisites: Your
dateCreated
property should be inDate
format.
let groupedObjectBySameDate = Dictionary(grouping: objects) { (object) -> String in
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter.string(from: object.dateCreated)
}
一个例子:
由于我不了解您的数据结构,因此我提供了一个简单的示例,可以帮助您了解正在发生的事情。
var dateFormatter: DateFormatter {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SZ"
formatter.locale = Locale(identifier: "en_US_POSIX")
return formatter
}
let stringDates = ["2018-03-20T06:15:11.000+0000", "2018-03-16T17:22:50.000+0000", "2018-03-16T17:10:36.000+0000", "2018-03-16T17:08:07.000+0000", "2018-03-16T17:08:07.000+0000"]
let dates = stringDates.map { (each) -> Date in
return dateFormatter.date(from: each) ?? Date(timeIntervalSinceReferenceDate: 0)
}
let groupedObjectBySameDate = Dictionary(grouping: dates) { (date) -> String in
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter.string(from: date)
}
print(groupedObjectBySameDate)
// This will produce:
// [
// "2018-03-20": [2018-03-20 06:15:11 +0000],
// "2018-03-16": [2018-03-16 17:22:50 +0000, 2018-03-16 17:10:36 +0000, 2018-03-16 17:08:07 +0000, 2018-03-16 17:08:07 +0000]
// ]