【问题标题】:How to query a date property in Realm?如何在 Realm 中查询日期属性?
【发布时间】:2019-01-19 05:20:23
【问题描述】:

我有一个 Realm 数据库,其中的对象“Events”具有字符串类型的属性名称“occasion”,字符串类型的属性名称“venue”,另一个是 Date() 类型的“日期”。 我的问题是我们如何查询与今天(当天)日期相同的场合。我试过这段代码使用日期过滤器来检索场合,它确实有效:

let date = Date()
let dateFormatter = DateFormatter()
// dateFormatter.dateFormat = "dd/MM/yyyy"
dateFormatter.dateFormat = "d MMM yyyy"
let stringDate = dateFormatter.string(from: date)        

todayEvent = realm.objects(Events.self).filter("date = '\(stringDate)'").sorted(byKeyPath: "venue", ascending: true)

Realm 数据库中的日期以“2019 年 1 月 17 日上午 12:00:00”的格式显示日期,即使该日期以 dd/MM/yyyy 格式保存也是如此。我已经尝试更改日期格式,但仍然无法正常工作。或者我是否需要在我首先声明日期属性时为其设置格式?如果是这样,我该如何在 Realm 类对象中执行此操作?我试过了,但它给出了一个错误。我现在被困在这里。请帮忙

这就是我将数据保存到 Realm 数据库的方式:

@IBAction func addNewEventButtonPressed(_ sender: UIButton) {



    let newDataEntry = Events()

    newDataEntry.occasion = occasionTextFile.text!


    let dateString =  dateTextField.text!
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "dd/MM/yyyy"
    let dateFromString = dateFormatter.date(from: dateString)

    newDataEntry.date = dateFromString!

    do {
        try realm.write {
            realm.add(newDataEntry)
        }
    } catch {
        print("Error saving data \(error)")
    }


}

【问题讨论】:

  • 对不起,我不明白你的问题是什么?以您的格式保存日期有问题吗?或者如何找回它?
  • 请告诉我们如何保存领域对象的日期属性
  • 对不起,如果我不够清楚。问题在于使用查询检索数据。而且我不知道为什么保存在领域中的日期会改变格式,尽管以不同的格式保存,即 dd/mm/yyyy。
  • 好的。请更新您的问题并向我们展示您如何保存具有日期属性的领域对象
  • 我已经在编辑的问题中展示了保存在领域数据库中的案例。

标签: ios swift realm


【解决方案1】:

根据Realm docs(强调我的):

比较运算符 ==、=、>、!= 和 BETWEEN 是 支持 Int、Int8、Int16、Int32、Int64、Float、Double 和 Date 属性类型

因此,以下应该可以工作:

let date = Date()
todayEvent = realm.objects(Events.self)
    .filter("date == %@", date)
    .sorted(byKeyPath: "venue") // sorted in ascending order by default

【讨论】:

  • 我再次使用了您的代码。现在应用程序正常启动并且没有崩溃。但是我仍然没有得到表格中显示的查询结果。
  • 我为“todayEvent”添加了一条打印语句,以查看代码是否在 load func 中被调用,控制台显示“Optional(Results。我不知道它是否是有用的信息,但我希望这有助于解决问题。
  • 只是为了更新。当我只是在语法中没有过滤器的情况下进行普通查询时,表格会显示所有可用数据,包括日期。如果我将过滤器放在查询语法中,以便结果仅显示与当天具有相同日期的事件,则表返回空。所以它必须是语法。至少我是这么想的。
  • stackoverflow.com/a/35965216/10784781。在这里找到了答案。现在尝试将查询设置为“明天”。非常感谢。
【解决方案2】:

您正在使用带有时间和语言环境的Date 对象,因此仅与日期一起使用可以使用以下函数从日期对象中删除时间和语言环境:

   func reomveTimeFrom(date: Date) -> Date {
            let components = Calendar.current.dateComponents([.year, .month, .day], from: date)
            let date = Calendar.current.date(from: components)
            return date!
        }

现在使用此函数获取准确的日期对象并从realm 数据库中获取数据。

let today = self.reomveTimeFrom(date: Date())
let predicate = NSPredicate(format: "date ==  %@",today as NSDate)
let results = realm.objects(Events.self).filter(predicate)

填写source code on github

【讨论】:

  • @DávidPásztor- 更新 swift 的语法,之前的语法是 react-native。
  • Rocky 和 ​​Dan Karbayev,我已经尝试了这两个代码,并且应用程序在控制台中崩溃并显示以下消息:由于未捕获的异常“无效值”而终止应用程序,原因:“预期类型为日期的对象“事件”类型的对象的属性“日期”,但收到:19/01/2019'。当应用程序崩溃时,我什至没有机会输入任何日期。这个“19/01/2019”是从哪里来的?
  • @halim - 分享Events 表的架构。
  • 使用 Realm 数据库的事件类有 3 个属性。 1. String 类型的场合 2. String 类型的场所 3. Date() 类型的日期。
  • @Rocky 谢谢,但是当我使用新代码运行它时,应用程序仍然崩溃。我现在正在使用 Dan Karbayev 版本。虽然应用程序运行它仍然不会在我的表格视图中显示查询结果
【解决方案3】:

问题是您正在存储 Date 对象,但试图将该属性过滤为字符串。

这一行

let dateFromString = dateFormatter.date(from: dateString)

从字符串创建一个 Date() 对象,这就是存储在您的 Realm 属性中的内容。

Realm 日期对象如下所示

2019-01-18T05:00:00.000Z

这是你的过滤器:

let stringDate = dateFormatter.string(from: date)
todayEvent = realm.objects(Events.self).filter("date = '\(stringDate)'")

这是从一个日期对象创建一个字符串,Realm 不知道如何处理它。如果要过滤日期属性,请使用日期对象。

但重要的是 - 该行应该会因以下错误而崩溃

Expected object of type date for property 'date' on object of type 'Event', but received: 18 Jan 2019

解决方案是,如果您搜索的属性是日期,那么过滤器需要是日期对象。

一个以 mm/dd/yyyy 字符串开头的日期对象的示例

let aDateString = "01/20/2019"
let mmddyyyyFormatter = DateFormatter()
mmddyyyyFormatter.dateFormat = "MM/dd/yyyy"
if let dateObjectToStore = mmddyyyyFormatter.date(from: aDateString) {
    newDataEntry.date = dateObjectToStore
} else {
    print("could not create date object")
}

假设我们现在要查找带有“yyyymmdd”字符串的对象

let dateStringToFind = "20190120"
let yyyymmddFormatter = DateFormatter()
yyyymmddFormatter.dateFormat = "yyyyMMdd"
let dateObjectToFind = yyyymmddFormatter.date(from: dateStringToFind)
let results = realm.objects(MyObject.self).filter("date == %@", dateObjectToFind)
if results.count > 0 {
    for myObject in results {
        print(myObject)
    }
} else {
    print("no objects have that date")
}

如您所见,我们将日期存储为日期对象,然后在过滤时过滤为日期对象。

过滤有一些注意事项和一些例外情况,但您大致了解。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    • 1970-01-01
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多