1 /**
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * ```
8 * http://www.apache.org/licenses/LICENSE-2.0
9 * ```
10 *
11 * Unless required by applicable law or agreed to in writing, software distributed under the License
12 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13 * or implied. See the License for the specific language governing permissions and limitations under
14 * the License.
15 */
16 package com.android.healthconnect.controller.utils
17
18 import java.time.Duration
19 import java.time.Instant
20 import java.time.Instant.ofEpochMilli
21 import java.time.LocalDate
22 import java.time.LocalDateTime
23 import java.time.LocalTime
24 import java.time.ZoneId
25 import java.time.temporal.ChronoUnit
26 import kotlin.random.Random
27
28 /**
29 * Returns an Instant with the specified year, month and day-of-month. The day must be valid for the
30 * year and month, otherwise an exception will be thrown.
31 *
32 * @param year the year to represent, from MIN_YEAR to MAX_YEAR
33 * @param month the month-of-year to represent, from 1 (January) to 12 (December)
34 * @param day the day-of-month to represent, from 1 to 31
35 */
getInstantnull36 fun getInstant(year: Int, month: Int, day: Int): Instant {
37 val date = LocalDate.of(year, month, day)
38 return date.atTime(LocalTime.MIDNIGHT).atZone(ZoneId.systemDefault()).toInstant()
39 }
40
Longnull41 fun Long.toInstant(): Instant {
42 return ofEpochMilli(this)
43 }
44
toLocalDatenull45 fun Instant.toLocalDate(): LocalDate {
46 return atZone(ZoneId.systemDefault()).toLocalDate()
47 }
48
Instantnull49 fun Instant.toLocalTime(): LocalTime {
50 return atZone(ZoneId.systemDefault()).toLocalTime()
51 }
52
Instantnull53 fun Instant.toLocalDateTime(): LocalDateTime {
54 return atZone(ZoneId.systemDefault()).toLocalDateTime()
55 }
56
Instantnull57 fun Instant.withinOneMinuteAfter(other: Instant): Boolean {
58 return this.minus(1, ChronoUnit.MINUTES).isBefore(other)
59 }
60
Instantnull61 fun Instant.withinOneHourAfter(other: Instant): Boolean {
62 return this.minus(1, ChronoUnit.HOURS).isBefore(other)
63 }
64
withinOneDayAfternull65 fun Instant.withinOneDayAfter(other: Instant): Boolean {
66 return this.minus(1, ChronoUnit.DAYS).isBefore(other)
67 }
68
Instantnull69 fun Instant.isOnSameDay(other: Instant): Boolean {
70 val localDate1 = this.toLocalDate()
71 val localDate2 = other.toLocalDate()
72 return localDate1 == localDate2
73 }
74
Instantnull75 fun Instant.isOnDayBefore(other: Instant): Boolean {
76 val localDate1 = this.toLocalDate()
77 val localDate2 = other.toLocalDate()
78 return localDate1 == localDate2.minusDays(1)
79 }
80
Instantnull81 fun Instant.isOnDayAfter(other: Instant): Boolean {
82 val localDate1 = this.toLocalDate()
83 val localDate2 = other.toLocalDate()
84 return localDate1 == localDate2.plusDays(1)
85 }
86
atStartOfDaynull87 fun Instant.atStartOfDay(): Instant {
88 return this.toLocalDate().atStartOfDay(ZoneId.systemDefault()).toInstant()
89 }
90
Instantnull91 fun Instant.isAtLeastOneDayAfter(other: Instant): Boolean {
92 val localDate1 = this.toLocalDate()
93 val localDate2 = other.toLocalDate()
94 return localDate1.isAfter(localDate2.plusDays(1)) || localDate1 == localDate2.plusDays(1)
95 }
96
Instantnull97 fun Instant.isLessThanOneYearAgo(timeSource: TimeSource): Boolean {
98 val oneYearAgo =
99 timeSource
100 .currentLocalDateTime()
101 .minusYears(1)
102 .toLocalDate()
103 .atStartOfDay(timeSource.deviceZoneOffset())
104 .toInstant()
105 return this.isAfter(oneYearAgo)
106 }
107
toInstantAtStartOfDaynull108 fun LocalDate.toInstantAtStartOfDay(): Instant {
109 return this.atStartOfDay(ZoneId.systemDefault()).toInstant()
110 }
111
withinOneYearAfternull112 fun LocalDate.withinOneYearAfter(other: LocalDate): Boolean {
113 return this.minusYears(1).isBefore(other)
114 }
115
LocalDatenull116 fun LocalDate.randomInstant(): Instant {
117 val startOfDay = this.toInstantAtStartOfDay()
118
119 // Calculate the number of seconds in a day, accounting for daylight saving changes
120 val duration = Duration.between(startOfDay, this.plusDays(1).toInstantAtStartOfDay())
121 val secondsInDay = duration.seconds
122
123 // Generate a random offset in seconds within the day
124 val randomSecondOffset = Random.nextLong(secondsInDay)
125
126 // Return the calculated instant
127 return startOfDay.plusSeconds(randomSecondOffset)
128 }
129
LocalDateTimenull130 fun LocalDateTime.toInstant(): Instant {
131 return atZone(ZoneId.systemDefault()).toInstant()
132 }
133