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 kotlin.random.Random
26 
27 /**
28  * Returns an Instant with the specified year, month and day-of-month. The day must be valid for the
29  * year and month, otherwise an exception will be thrown.
30  *
31  * @param year the year to represent, from MIN_YEAR to MAX_YEAR
32  * @param month the month-of-year to represent, from 1 (January) to 12 (December)
33  * @param day the day-of-month to represent, from 1 to 31
34  */
getInstantnull35 fun getInstant(year: Int, month: Int, day: Int): Instant {
36     val date = LocalDate.of(year, month, day)
37     return date.atTime(LocalTime.MIDNIGHT).atZone(ZoneId.systemDefault()).toInstant()
38 }
39 
Longnull40 fun Long.toInstant(): Instant {
41     return ofEpochMilli(this)
42 }
43 
toLocalDatenull44 fun Instant.toLocalDate(): LocalDate {
45     return atZone(ZoneId.systemDefault()).toLocalDate()
46 }
47 
Instantnull48 fun Instant.toLocalTime(): LocalTime {
49     return atZone(ZoneId.systemDefault()).toLocalTime()
50 }
51 
Instantnull52 fun Instant.toLocalDateTime(): LocalDateTime {
53     return atZone(ZoneId.systemDefault()).toLocalDateTime()
54 }
55 
Instantnull56 fun Instant.isOnSameDay(other: Instant): Boolean {
57     val localDate1 = this.toLocalDate()
58     val localDate2 = other.toLocalDate()
59     return localDate1 == localDate2
60 }
61 
Instantnull62 fun Instant.isOnDayBefore(other: Instant): Boolean {
63     val localDate1 = this.toLocalDate()
64     val localDate2 = other.toLocalDate()
65     return localDate1 == localDate2.minusDays(1)
66 }
67 
Instantnull68 fun Instant.isOnDayAfter(other: Instant): Boolean {
69     val localDate1 = this.toLocalDate()
70     val localDate2 = other.toLocalDate()
71     return localDate1 == localDate2.plusDays(1)
72 }
73 
atStartOfDaynull74 fun Instant.atStartOfDay(): Instant {
75     return this.toLocalDate().atStartOfDay(ZoneId.systemDefault()).toInstant()
76 }
77 
Instantnull78 fun Instant.isAtLeastOneDayAfter(other: Instant): Boolean {
79     val localDate1 = this.toLocalDate()
80     val localDate2 = other.toLocalDate()
81     return localDate1.isAfter(localDate2.plusDays(1)) || localDate1 == localDate2.plusDays(1)
82 }
83 
toInstantAtStartOfDaynull84 fun LocalDate.toInstantAtStartOfDay(): Instant {
85     return this.atStartOfDay(ZoneId.systemDefault()).toInstant()
86 }
87 
LocalDatenull88 fun LocalDate.randomInstant(): Instant {
89     val startOfDay = this.toInstantAtStartOfDay()
90 
91     // Calculate the number of seconds in a day, accounting for daylight saving changes
92     val duration = Duration.between(startOfDay, this.plusDays(1).toInstantAtStartOfDay())
93     val secondsInDay = duration.seconds
94 
95     // Generate a random offset in seconds within the day
96     val randomSecondOffset = Random.nextLong(secondsInDay)
97 
98     // Return the calculated instant
99     return startOfDay.plusSeconds(randomSecondOffset)
100 }
101 
LocalDateTimenull102 fun LocalDateTime.toInstant(): Instant {
103     return atZone(ZoneId.systemDefault()).toInstant()
104 }
105