public final class HealthInterval
- Object
- HealthInterval
The bucket width of an AggregateQuery – “per hour”, “per calendar
day”, “per calendar month”.
Fixed durations and calendar periods are not the same thing
A calendar day is 23 or 25 hours across a daylight-saving transition,
and a month is 28 to 31 days. Bucketing by a fixed 86400000 therefore
drifts against the dates a user sees in your UI, silently, twice a
year. Both platforms model the distinction natively – Health Connect
splits aggregateGroupByDuration from aggregateGroupByPeriod, and
HealthKit takes DateComponents – so this API keeps it too.
Calendar-based intervals require an explicit ZoneId. Nothing
here reads the JVM default, because a server-side default of UTC would put
a user’s evening walk into the wrong day.
Methods
Inherited methods
Method details
millis
public static HealthInterval millis(long millis)minutes
public static HealthInterval minutes(int minutes)hours
public static HealthInterval hours(int hours)calendarDays
public static HealthInterval calendarDays(int days, ZoneId zone)zone, aligned to local midnight. Correct across
daylight-saving transitions.calendarWeeks
public static HealthInterval calendarWeeks(int weeks, ZoneId zone, int firstDayOfWeek)zone, aligned to firstDayOfWeek (a
java.util.Calendar day constant such as Calendar.MONDAY).
The first day of the week is explicit because it differs by locale
and silently guessing it shifts every bucket boundary.calendarMonths
public static HealthInterval calendarMonths(int months, ZoneId zone)zone, aligned to local midnight on the first of
the month.isCalendarBased
public boolean isCalendarBased()true when this interval follows the calendar rather than a fixed
number of milliseconds.getFixedMillis
public long getFixedMillis()isCalendarBased().getZone
public ZoneId getZone()The zone calendar boundaries are computed in, or null for a fixed-duration interval.
A ZoneId rather than a java.util.TimeZone, and immutable,
so it can be handed out as-is. The mutable type needed a caveat instead
of an answer: an interval built from a SimpleTimeZone that was later
reconfigured moved its bucket boundaries, putting the same samples in
different days, and the compile target could not defend against it –
the CLDC 1.1 subset exposes no public TimeZone.clone(), and
getTimeZone(getID()) answers GMT for an unrecognised id, which would
have silently discarded the rules of the very zone being protected.
getDuration
public Duration getDuration()This interval as a Duration, or null when it is calendar-based.
A calendar day is 23, 24 or 25 hours depending on the transition it spans, so a calendar interval has no fixed length and saying otherwise would be the drift this API takes an explicit zone to avoid.
of
public static HealthInterval of(Duration length)length.bucketStart
public long bucketStart(long millis, long anchorMillis)millis. For a fixed
interval this is anchored on anchorMillis; for a calendar
interval it snaps to the local period boundary and anchorMillis
is ignored.nextBoundary
public long nextBoundary(long bucketStartMillis)bucketStartMillis. Bucket n’s exclusive end is bucket n+1’s
inclusive start, so buckets tile with no gap and no overlap even
when their widths differ.toString
public String toString()