0

I am fetching records from Core Data between two timestamps which represent the start and end of the day using the following predicate:

let timeStampPredicate = NSPredicate(format: "timestamp >= %f AND timestamp < %f", startTimeStamp, endTimeStamp)

The above predicate works perfectly until 11:59:00 PM, but any record saved after it, like at 11:59:22 PM are not returned by the predicate.

Example:

Records in Core Data :

Record 1:

Timestamp: 1631816962.0 
Date: 2021-09-16 18:29:22 +0000 // My TimeZone is +0530
Challenge ID: 1 
Value: 100.0

Record 2:

Timestamp: 1631816902.0
Date: 2021-09-16 18:28:22 +0000 // My TimeZone is +0530
Challenge ID: 1
Value: 100.0

Passed Values to the predicate:

startTimeStamp : 1631730600.0 // 2021-09-15 18:30:00 +0000 

endTimeStamp : 1631817000.0 // 2021-09-16 18:30:00 +0000 

When I execute the predicate only 1 record is returned which is inserted before 11:59:00 PM

Can anyone help me understand what's happening or what I am doing wrong.

Nikhil Muskur
  • 208
  • 1
  • 11
  • Enable Core Data verbose logging (see e.g. https://stackoverflow.com/q/12306343/1187415) – Martin R Sep 16 '21 at 14:55
  • @MartinR The SQLite query also shows only 1 returned row :( . Can I structure the predicate in any other way ? – Nikhil Muskur Sep 16 '21 at 15:41
  • In your sample, the Challenge Id is the same, you don't care about unicity about it, right? Could you do the request with no predicate and then try to apply your predicate to the result? Maybe piece by piece (in 2 predicates, not only the first one), and check why the second record is not valid? – Larme Sep 16 '21 at 17:05
  • @Larme I do care about the challenge ID, since I could be querying for a different challenge. Filtering after fetching all data for a challenge ID is working as expected. Kudos for mentioning it. – Nikhil Muskur Sep 22 '21 at 12:01
  • Did you filter using NSPredicate & `evaluate()` with the same predicate that failed before? – Larme Sep 22 '21 at 12:12
  • You need to debug, you can see https://pastebin.com/ffhTFAVe which are sample tests to run and try to understand which one has unexpected result... – Larme Sep 22 '21 at 15:40
  • @Larme Thanks I'll create a new paste bin with results – Nikhil Muskur Sep 22 '21 at 16:15
  • @Larme Ran all the test [pastebin.com/QdfBMCPp](https://pastebin.com/QdfBMCPp). Still the same output of skipping any record between 11:59:00 PM 11:59:59 PM – Nikhil Muskur Sep 22 '21 at 17:00
  • @Larme I was again debugging this issue and if I pull back the end time by 60 seconds (from 12:00AM to 11:59 PM) then the predicate works perfectly : https://pastebin.com/Y1UrHVz3 – Nikhil Muskur Sep 23 '21 at 11:18
  • Using this predicate also works `NSPredicate(format: "%K BETWEEN {%f, %f}", argumentArray: [#keyPath(CaloriesData.timestamp), startTimeStamp, endTimeStamp])` but it also includes the records entered @ 12AM for the next day – Nikhil Muskur Sep 25 '21 at 08:50

1 Answers1

0

I am still not sure as what's causing the problem as the Predicate seems to be fine.

To rule out all possibilities I even tried using NSComparisonPredicate but still the same result.

As @Larme suggested in the comments, I tried filtering the data once I get all back from Core Data.

Did a simple filter(_:) on the fetched array.This approach is working as expected.

If anyone can confirm if filter is the way to go on an array which won't contain more than 300 records.

Update 1:

If I use the BETWEEN Predicate it kinda works :

let predicate = NSPredicate(format: "%K BETWEEN {%f, %f}", argumentArray: [#keyPath(CD_Model.timestamp), startTimeStamp, endTimeStamp])

But it also includes records entered for the next day @ 12 AM which kinda defeats the purpose. I could maybe filter for records after fetching the records but I feel that may create it own edge cases

Nikhil Muskur
  • 208
  • 1
  • 11
  • 1
    Well, it's still better to filter in the request than the result, because if you fetch 400k elements to get after filtering only 2, it's memory/optimization issue... – Larme Sep 22 '21 at 12:11