Search code examples
iosswifttimehealthkit

How to get exactly 24 hours of sleep data from a specific date with HealthKit?


I'm familiar with the typical means of getting sleep data, but it's proving somewhat more difficult to get hours of sleep for a specific 24 hour window.

I can setup a predicate to get samples that start or end within a certain time, but many times these samples cross date boundaries. If I go to bed at 10PM and wake up at 4AM, then sleep from 5AM to 8AM, it's difficult to scope the 10-4 sample to get just the part from yesterday.

A typical predicate might look something like this (using the following date extension):

extension Date {
    var today: Date {
        return Calendar.current.date(byAdding: .day, value: 0, to: midnight)!
    }
    var yesterday: Date {
        return Calendar.current.date(byAdding: .day, value: -1, to: midnight)!
    }
}

let predicate = HKQuery.predicateForSamples(withStart: Date().yesterday, end: Date().today, options: [])

And then get a sample, and do something to get the seconds/minutes/hours:

let seconds = sample.endDate.timeIntervalSince(sample.startDate)

But this causes issues when the start date isn't necessarily from yesterday, or the end date isn't necessarily before today.

I can start doing some special casing around start and end dates, but it gets somewhat complicated. Is there a simple way to just get the hours sleep from yesterday (the exact 24 hour window from midnight to midnight)? I feel like I must be misunderstanding some basic about sleep queries, or the time math around this.


Solution

  • HealthKit does not have a way to interpolate the results of queries for HKCategorySample types. Your queries must match the entirety of the sleep samples you want to work with, and you'll have to do the math yourself to figure out how much of the sample falls in the date interval you're interested in.