1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.health.connect; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 22 import java.time.Instant; 23 import java.time.LocalDateTime; 24 import java.time.ZoneOffset; 25 26 /** 27 * A helper class for {@link TimeRangeFilter} to handle possible time filter types. 28 * 29 * @hide 30 */ 31 public final class TimeRangeFilterHelper { 32 33 private static final ZoneOffset LOCAL_TIME_ZERO_OFFSET = ZoneOffset.UTC; 34 isLocalTimeFilter(@onNull TimeRangeFilter timeRangeFilter)35 public static boolean isLocalTimeFilter(@NonNull TimeRangeFilter timeRangeFilter) { 36 return (timeRangeFilter instanceof LocalTimeRangeFilter); 37 } 38 39 /** 40 * @return start time epoch milliseconds for Instant time filter and epoch milliseconds using 41 * UTC zoneOffset for LocalTime filter 42 */ 43 @SuppressWarnings("NullAway") // TODO(b/317029272): fix this suppression getFilterStartTimeMillis(@onNull TimeRangeFilter timeRangeFilter)44 public static long getFilterStartTimeMillis(@NonNull TimeRangeFilter timeRangeFilter) { 45 if (isLocalTimeFilter(timeRangeFilter)) { 46 return getMillisOfLocalTime(((LocalTimeRangeFilter) timeRangeFilter).getStartTime()); 47 } else if (timeRangeFilter instanceof TimeInstantRangeFilter) { 48 return ((TimeInstantRangeFilter) timeRangeFilter).getStartTime().toEpochMilli(); 49 } else { 50 throw new IllegalArgumentException( 51 "Invalid time filter object. Object should be either " 52 + "TimeInstantRangeFilter or LocalTimeRangeFilter."); 53 } 54 } 55 56 /** 57 * @return end time epoch milliseconds for Instant time filter and epoch milliseconds using UTC 58 * zoneOffset for LocalTime filter 59 */ 60 @SuppressWarnings("NullAway") // TODO(b/317029272): fix this suppression getFilterEndTimeMillis(@onNull TimeRangeFilter timeRangeFilter)61 public static long getFilterEndTimeMillis(@NonNull TimeRangeFilter timeRangeFilter) { 62 if (isLocalTimeFilter(timeRangeFilter)) { 63 return getMillisOfLocalTime(((LocalTimeRangeFilter) timeRangeFilter).getEndTime()); 64 } else if (timeRangeFilter instanceof TimeInstantRangeFilter) { 65 return ((TimeInstantRangeFilter) timeRangeFilter).getEndTime().toEpochMilli(); 66 } else { 67 throw new IllegalArgumentException( 68 "Invalid time filter object. Object should be either " 69 + "TimeInstantRangeFilter or LocalTimeRangeFilter."); 70 } 71 } 72 getLocalTimeFromMillis(Long localDateTimeMillis)73 public static LocalDateTime getLocalTimeFromMillis(Long localDateTimeMillis) { 74 return LocalDateTime.ofInstant( 75 Instant.ofEpochMilli(localDateTimeMillis), LOCAL_TIME_ZERO_OFFSET); 76 } 77 getMillisOfLocalTime(LocalDateTime time)78 public static long getMillisOfLocalTime(LocalDateTime time) { 79 return time.toInstant(LOCAL_TIME_ZERO_OFFSET).toEpochMilli(); 80 } 81 82 /** 83 * Converts the provided {@link LocalDateTime} to {@link Instant} using the provided {@link 84 * ZoneOffset} if it's not null, or using the system default zone offset otherwise. 85 */ getInstantFromLocalTime( @onNull LocalDateTime time, @Nullable ZoneOffset zoneOffset)86 public static Instant getInstantFromLocalTime( 87 @NonNull LocalDateTime time, @Nullable ZoneOffset zoneOffset) { 88 return zoneOffset != null 89 ? time.toInstant(zoneOffset) 90 : time.toInstant(ZoneOffset.systemDefault().getRules().getOffset(time)); 91 } 92 } 93