mirror of
https://github.com/sudoxnym/habitica-android.git
synced 2026-07-09 13:58:45 +00:00
improve edgecases for reminder scheduling
This commit is contained in:
parent
d91be2d7fe
commit
3254ce9f96
2 changed files with 298 additions and 279 deletions
|
|
@ -368,12 +368,13 @@ open class Task : RealmObject, BaseMainObject, Parcelable, BaseTask {
|
|||
*/
|
||||
fun getNextReminderOccurrences(
|
||||
remindersItem: RemindersItem?,
|
||||
occurrences: Int
|
||||
occurrences: Int,
|
||||
today: ZonedDateTime? = null
|
||||
): List<ZonedDateTime>? {
|
||||
if (remindersItem == null) return null
|
||||
|
||||
val reminderTime = remindersItem.time?.parseToZonedDateTime() ?: return null
|
||||
var dateTimeOccurenceToSchedule: ZonedDateTime
|
||||
var nextOccurence: ZonedDateTime
|
||||
val occurrencesList = mutableListOf<ZonedDateTime>()
|
||||
|
||||
// If the reminder is a todo, only schedule sole dueDate/time occurrence. Otherwise, schedule multiple occurrences in advance
|
||||
|
|
@ -385,7 +386,7 @@ open class Task : RealmObject, BaseMainObject, Parcelable, BaseTask {
|
|||
)
|
||||
return occurrencesList
|
||||
}
|
||||
val now = ZonedDateTime.now().withZoneSameInstant(ZoneId.systemDefault())
|
||||
val now = today ?: ZonedDateTime.now().withZoneSameInstant(ZoneId.systemDefault())
|
||||
var startDate = this.startDate?.toInstant()?.atZone(ZoneId.systemDefault()) ?: return null
|
||||
val weekInMonth = getWeeksOfMonth()?.firstOrNull()?.toLong()
|
||||
val weekdayInMonth = startDate.dayOfWeek
|
||||
|
|
@ -396,52 +397,52 @@ open class Task : RealmObject, BaseMainObject, Parcelable, BaseTask {
|
|||
}
|
||||
val repeatDays = this.repeat
|
||||
startDate = startDate.withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
dateTimeOccurenceToSchedule = startDate
|
||||
nextOccurence = startDate
|
||||
if (frequency == Frequency.MONTHLY) {
|
||||
daysOfMonth?.let {
|
||||
if (it.isEmpty()) return@let
|
||||
dateTimeOccurenceToSchedule = dateTimeOccurenceToSchedule.withDayOfMonth(it.first())
|
||||
if (dateTimeOccurenceToSchedule.isBefore(startDate)) {
|
||||
dateTimeOccurenceToSchedule = dateTimeOccurenceToSchedule.plusMonths(1)
|
||||
nextOccurence = nextOccurence.withDayOfMonth(it.first())
|
||||
if (nextOccurence.isBefore(startDate)) {
|
||||
nextOccurence = nextOccurence.plusMonths(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (occurrencesList.size < occurrences) {
|
||||
// Increment currentDate based on the frequency
|
||||
dateTimeOccurenceToSchedule =
|
||||
nextOccurence =
|
||||
when (frequency) {
|
||||
Frequency.DAILY -> {
|
||||
while (dateTimeOccurenceToSchedule.isBefore(now)) {
|
||||
dateTimeOccurenceToSchedule = dateTimeOccurenceToSchedule.plusDays(everyX)
|
||||
while (nextOccurence.isBefore(now)) {
|
||||
nextOccurence = nextOccurence.plusDays(everyX)
|
||||
}
|
||||
val todayWithTime = dateTimeOccurenceToSchedule
|
||||
val todayWithTime = nextOccurence
|
||||
.withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
dateTimeOccurenceToSchedule = if (occurrencesList.isEmpty() && todayWithTime.isAfter(now)) {
|
||||
nextOccurence = if (occurrencesList.isEmpty() && todayWithTime.isAfter(now)) {
|
||||
todayWithTime
|
||||
} else {
|
||||
dateTimeOccurenceToSchedule.plusDays(everyX)
|
||||
nextOccurence.plusDays(everyX)
|
||||
.withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
}
|
||||
dateTimeOccurenceToSchedule
|
||||
nextOccurence
|
||||
}
|
||||
|
||||
Frequency.WEEKLY -> {
|
||||
// Set to start date if current date is earlier
|
||||
if (repeatDays?.hasAnyDaySelected() == true) {
|
||||
if (dateTimeOccurenceToSchedule.isBefore(now)) {
|
||||
dateTimeOccurenceToSchedule =
|
||||
dateTimeOccurenceToSchedule.plusDays(1)
|
||||
while (!dateTimeOccurenceToSchedule.matchesRepeatDays(repeatDays)) {
|
||||
dateTimeOccurenceToSchedule =
|
||||
dateTimeOccurenceToSchedule.plusDays(1)
|
||||
if (nextOccurence.isBefore(now)) {
|
||||
var occurenceNowWeekday = nextOccurence.minusDays((nextOccurence.dayOfWeek.value - now.dayOfWeek.value).toLong())
|
||||
while (occurenceNowWeekday.isBefore(now) && occurenceNowWeekday.dayOfYear != now.dayOfYear) {
|
||||
occurenceNowWeekday = occurenceNowWeekday.plusDays(everyX * 7)
|
||||
}
|
||||
nextOccurence = occurenceNowWeekday
|
||||
while (!nextOccurence.matchesRepeatDays(repeatDays)) {
|
||||
nextOccurence =
|
||||
nextOccurence.plusDays(1)
|
||||
}
|
||||
}
|
||||
while (dateTimeOccurenceToSchedule.isBefore(now)) {
|
||||
dateTimeOccurenceToSchedule = dateTimeOccurenceToSchedule.plusDays(everyX * 7)
|
||||
}
|
||||
var nextDueDate =
|
||||
dateTimeOccurenceToSchedule.withHour(reminderTime.hour)
|
||||
nextOccurence.withHour(reminderTime.hour)
|
||||
.withMinute(reminderTime.minute)
|
||||
// If the next due date already happened for today, increment it by one day. Otherwise, it will be scheduled for today.
|
||||
if (nextDueDate.isBefore(now) && occurrencesList.size == 0) {
|
||||
|
|
@ -475,58 +476,58 @@ open class Task : RealmObject, BaseMainObject, Parcelable, BaseTask {
|
|||
}
|
||||
}
|
||||
|
||||
dateTimeOccurenceToSchedule = nextDueDate
|
||||
nextOccurence = nextDueDate
|
||||
}
|
||||
// Set time to the reminder time
|
||||
dateTimeOccurenceToSchedule.withHour(reminderTime.hour)
|
||||
nextOccurence.withHour(reminderTime.hour)
|
||||
.withMinute(reminderTime.minute)
|
||||
}
|
||||
|
||||
Frequency.MONTHLY -> {
|
||||
while (dateTimeOccurenceToSchedule.isBefore(now)) {
|
||||
dateTimeOccurenceToSchedule = dateTimeOccurenceToSchedule.plusMonths(everyX)
|
||||
while (nextOccurence.isBefore(now)) {
|
||||
nextOccurence = nextOccurence.plusMonths(everyX)
|
||||
if (weekInMonth != null && weekdayInMonth != null) {
|
||||
dateTimeOccurenceToSchedule = dateTimeOccurenceToSchedule.withDayOfMonth(1)
|
||||
while (dateTimeOccurenceToSchedule.dayOfWeek != weekdayInMonth) {
|
||||
dateTimeOccurenceToSchedule = dateTimeOccurenceToSchedule.plusDays(1)
|
||||
nextOccurence = nextOccurence.withDayOfMonth(1)
|
||||
while (nextOccurence.dayOfWeek != weekdayInMonth) {
|
||||
nextOccurence = nextOccurence.plusDays(1)
|
||||
}
|
||||
dateTimeOccurenceToSchedule = dateTimeOccurenceToSchedule.plusWeeks(weekInMonth)
|
||||
nextOccurence = nextOccurence.plusWeeks(weekInMonth)
|
||||
}
|
||||
}
|
||||
val todayWithTime = dateTimeOccurenceToSchedule
|
||||
val todayWithTime = nextOccurence
|
||||
.withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
if (occurrencesList.isEmpty() && todayWithTime.isAfter(now)) {
|
||||
todayWithTime
|
||||
} else if (weekInMonth != null && weekdayInMonth != null) {
|
||||
dateTimeOccurenceToSchedule = dateTimeOccurenceToSchedule.plusMonths(everyX)
|
||||
nextOccurence = nextOccurence.plusMonths(everyX)
|
||||
.withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
.withDayOfMonth(1)
|
||||
while (dateTimeOccurenceToSchedule.dayOfWeek != weekdayInMonth) {
|
||||
dateTimeOccurenceToSchedule = dateTimeOccurenceToSchedule.plusDays(1)
|
||||
while (nextOccurence.dayOfWeek != weekdayInMonth) {
|
||||
nextOccurence = nextOccurence.plusDays(1)
|
||||
}
|
||||
dateTimeOccurenceToSchedule.plusWeeks(weekInMonth)
|
||||
nextOccurence.plusWeeks(weekInMonth)
|
||||
} else {
|
||||
dateTimeOccurenceToSchedule.plusMonths(everyX)
|
||||
nextOccurence.plusMonths(everyX)
|
||||
.withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
}
|
||||
}
|
||||
|
||||
Frequency.YEARLY -> {
|
||||
while (dateTimeOccurenceToSchedule.isBefore(now)) {
|
||||
dateTimeOccurenceToSchedule = dateTimeOccurenceToSchedule.plusYears(everyX)
|
||||
while (nextOccurence.isBefore(now)) {
|
||||
nextOccurence = nextOccurence.plusYears(everyX)
|
||||
}
|
||||
val todayWithTime = dateTimeOccurenceToSchedule
|
||||
val todayWithTime = nextOccurence
|
||||
.withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
if (occurrencesList.isEmpty() && todayWithTime.isAfter(now)) {
|
||||
todayWithTime
|
||||
} else {
|
||||
dateTimeOccurenceToSchedule.plusYears(everyX)
|
||||
nextOccurence.plusYears(everyX)
|
||||
.withHour(reminderTime.hour).withMinute(reminderTime.minute)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
occurrencesList.add(dateTimeOccurenceToSchedule)
|
||||
occurrencesList.add(nextOccurence)
|
||||
}
|
||||
|
||||
return occurrencesList
|
||||
|
|
|
|||
|
|
@ -8,286 +8,304 @@ import io.kotest.core.spec.style.WordSpec
|
|||
import io.kotest.matchers.shouldBe
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
|
||||
class TaskTest : WordSpec({
|
||||
"getNextReminderOccurrences" When {
|
||||
var daily = Task()
|
||||
var reminder = RemindersItem()
|
||||
var calendar = Calendar.getInstance()
|
||||
beforeEach {
|
||||
daily = Task()
|
||||
daily.type = TaskType.DAILY
|
||||
|
||||
reminder = RemindersItem()
|
||||
|
||||
calendar = Calendar.getInstance()
|
||||
}
|
||||
"dailies repeating daily" should {
|
||||
listOf(
|
||||
Date(),
|
||||
Calendar.getInstance().apply {
|
||||
set(2025, 1, 1)
|
||||
}.time,
|
||||
Calendar.getInstance().apply {
|
||||
set(2024, Calendar.DECEMBER, 23)
|
||||
}.time
|
||||
).forEach { day ->
|
||||
"getNextReminderOccurrences on $day" When {
|
||||
var daily = Task()
|
||||
var reminder = RemindersItem()
|
||||
var calendar = Calendar.getInstance()
|
||||
calendar.time = day
|
||||
val fakeZDT = day.toZonedDateTime()
|
||||
beforeEach {
|
||||
daily.frequency = Frequency.DAILY
|
||||
daily = Task()
|
||||
daily.type = TaskType.DAILY
|
||||
|
||||
reminder = RemindersItem()
|
||||
|
||||
calendar = Calendar.getInstance()
|
||||
calendar.time = day
|
||||
}
|
||||
"return occurrences according to everyX = 2" {
|
||||
calendar.add(Calendar.DATE, -2)
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 2
|
||||
calendar.add(Calendar.DATE, 4)
|
||||
reminder.time = calendar.time.toZonedDateTime()?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4)
|
||||
occurrences?.size shouldBe 4
|
||||
occurrences?.forEach {
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
calendar.add(Calendar.DATE, 2)
|
||||
"dailies repeating daily" should {
|
||||
beforeEach {
|
||||
daily.frequency = Frequency.DAILY
|
||||
}
|
||||
}
|
||||
"return occurrences according to everyX = 2" {
|
||||
calendar.add(Calendar.DATE, -2)
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 2
|
||||
calendar.add(Calendar.DATE, 4)
|
||||
reminder.time = fakeZDT?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
"return occurrences according to everyX = 1" {
|
||||
calendar.add(Calendar.DATE, -2)
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 1
|
||||
calendar.add(Calendar.DATE, 3)
|
||||
reminder.time = calendar.time.toZonedDateTime()?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4)
|
||||
occurrences?.size shouldBe 4
|
||||
occurrences?.forEach {
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4, fakeZDT)
|
||||
occurrences?.size shouldBe 4
|
||||
occurrences?.forEach {
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
calendar.add(Calendar.DATE, 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"return occurrences according to everyX = 5" {
|
||||
calendar.add(Calendar.DATE, -33)
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 5
|
||||
reminder.time = calendar.time.toZonedDateTime()?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
"return occurrences according to everyX = 1" {
|
||||
calendar.add(Calendar.DATE, -2)
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 1
|
||||
calendar.add(Calendar.DATE, 3)
|
||||
reminder.time = fakeZDT?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4)
|
||||
occurrences?.size shouldBe 4
|
||||
calendar.add(Calendar.DATE, 35)
|
||||
occurrences?.forEach {
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
calendar.add(Calendar.DATE, 5)
|
||||
}
|
||||
}
|
||||
}
|
||||
"dailies repeating weekly" should {
|
||||
beforeEach {
|
||||
daily.frequency = Frequency.WEEKLY
|
||||
}
|
||||
"return occurrences if active every day" {
|
||||
daily.startDate = calendar.time
|
||||
daily.repeat = Days()
|
||||
daily.everyX = 1
|
||||
|
||||
reminder.time = calendar.time.toZonedDateTime()?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4)
|
||||
occurrences?.size shouldBe 4
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
occurrences?.forEach {
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
}
|
||||
|
||||
"return occurrences if active tuesdays" {
|
||||
calendar.add(Calendar.DATE, -63)
|
||||
daily.startDate = calendar.time
|
||||
daily.repeat = Days(t = true, default = false)
|
||||
daily.everyX = 1
|
||||
|
||||
reminder.time = calendar.time.toZonedDateTime()?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4)
|
||||
occurrences?.size shouldBe 4
|
||||
calendar.add(Calendar.DATE, 63)
|
||||
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.TUESDAY) {
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
occurrences?.forEach {
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
calendar.add(Calendar.DATE, 7)
|
||||
}
|
||||
}
|
||||
|
||||
"return occurrences if active every second friday" {
|
||||
calendar.add(Calendar.DATE, -23)
|
||||
daily.startDate = calendar.time
|
||||
daily.repeat = Days(f = true, default = false)
|
||||
daily.everyX = 2
|
||||
|
||||
reminder.time = calendar.time.toZonedDateTime()?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4)
|
||||
occurrences?.size shouldBe 4
|
||||
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.FRIDAY) {
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
calendar.add(Calendar.DATE, 28)
|
||||
occurrences?.forEach {
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
calendar.add(Calendar.DATE, 14)
|
||||
}
|
||||
}
|
||||
|
||||
"return occurrences if active multiple days a week" {
|
||||
calendar.add(Calendar.DATE, -23)
|
||||
daily.startDate = calendar.time
|
||||
daily.repeat = Days(t = true, f = true, s = true, default = false)
|
||||
daily.everyX = 1
|
||||
|
||||
reminder.time = calendar.time.toZonedDateTime()?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4)
|
||||
occurrences?.size shouldBe 4
|
||||
calendar.add(Calendar.DATE, 23)
|
||||
occurrences?.forEach {
|
||||
while (!calendar.matchesRepeatDays(daily.repeat)) {
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4, fakeZDT)
|
||||
occurrences?.size shouldBe 4
|
||||
occurrences?.forEach {
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
|
||||
"return occurrences according to everyX = 5" {
|
||||
calendar.add(Calendar.DATE, -33)
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 5
|
||||
reminder.time = fakeZDT?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4, fakeZDT)
|
||||
occurrences?.size shouldBe 4
|
||||
calendar.add(Calendar.DATE, 35)
|
||||
occurrences?.forEach {
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
calendar.add(Calendar.DATE, 5)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"dailies repeating weekly" should {
|
||||
beforeEach {
|
||||
daily.frequency = Frequency.WEEKLY
|
||||
}
|
||||
"return occurrences if active every day" {
|
||||
daily.startDate = calendar.time
|
||||
daily.repeat = Days()
|
||||
daily.everyX = 1
|
||||
|
||||
"dailies repeating monthly" should {
|
||||
beforeEach {
|
||||
daily.frequency = Frequency.MONTHLY
|
||||
}
|
||||
reminder.time = fakeZDT?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
"return occurrences if active every 10th of the month" {
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 1
|
||||
daily.setDaysOfMonth(listOf(10))
|
||||
|
||||
reminder.time = calendar.time.toZonedDateTime()?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4)
|
||||
occurrences?.size shouldBe 4
|
||||
occurrences?.forEach {
|
||||
while (calendar.get(Calendar.DAY_OF_MONTH) != 10) {
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4, fakeZDT)
|
||||
occurrences?.size shouldBe 4
|
||||
occurrences?.forEach {
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
it.year shouldBe calendar.get(Calendar.YEAR)
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
}
|
||||
|
||||
"return occurrences if active every third month on the 5th" {
|
||||
calendar.add(Calendar.MONDAY, -8)
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 3
|
||||
daily.setDaysOfMonth(listOf(5))
|
||||
"return occurrences if active tuesdays" {
|
||||
calendar.add(Calendar.DATE, -63)
|
||||
daily.startDate = calendar.time
|
||||
daily.repeat = Days(t = true, default = false)
|
||||
daily.everyX = 1
|
||||
|
||||
reminder.time = calendar.time.toZonedDateTime()?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
reminder.time = fakeZDT?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4)
|
||||
calendar.add(Calendar.MONTH, 9)
|
||||
occurrences?.size shouldBe 4
|
||||
occurrences?.forEach {
|
||||
while (calendar.get(Calendar.DAY_OF_MONTH) != 5) {
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
it.year shouldBe calendar.get(Calendar.YEAR)
|
||||
calendar.add(Calendar.MONTH, 3)
|
||||
}
|
||||
}
|
||||
|
||||
"return occurrences if active every month on the third tuesday" {
|
||||
calendar.set(Calendar.YEAR, 2025)
|
||||
calendar.set(Calendar.MONTH, Calendar.JANUARY)
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 21)
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 1
|
||||
daily.setWeeksOfMonth(listOf(2))
|
||||
|
||||
reminder.time = calendar.time.toZonedDateTime()?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4)
|
||||
occurrences?.size shouldBe 4
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1)
|
||||
occurrences?.forEach {
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4, fakeZDT)
|
||||
occurrences?.size shouldBe 4
|
||||
calendar.add(Calendar.DATE, 63)
|
||||
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.TUESDAY) {
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
calendar.add(Calendar.DATE, 14)
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
it.year shouldBe calendar.get(Calendar.YEAR)
|
||||
calendar.add(Calendar.MONTH, 1)
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1)
|
||||
occurrences?.forEach {
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
calendar.add(Calendar.DATE, 7)
|
||||
}
|
||||
}
|
||||
|
||||
"return occurrences if active every second friday" {
|
||||
daily.startDate = calendar.time
|
||||
daily.repeat = Days(f = true, default = false)
|
||||
daily.everyX = 2
|
||||
|
||||
reminder.time = fakeZDT?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4, fakeZDT)
|
||||
occurrences?.size shouldBe 4
|
||||
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.FRIDAY) {
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
occurrences?.forEach {
|
||||
it.dayOfMonth shouldBe calendar.get(Calendar.DAY_OF_MONTH)
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
calendar.add(Calendar.DATE, 14)
|
||||
}
|
||||
}
|
||||
|
||||
"return occurrences if active multiple days a week" {
|
||||
calendar.add(Calendar.DATE, -23)
|
||||
daily.startDate = calendar.time
|
||||
daily.repeat = Days(t = true, f = true, s = true, default = false)
|
||||
daily.everyX = 1
|
||||
|
||||
reminder.time = fakeZDT?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4, fakeZDT)
|
||||
occurrences?.size shouldBe 4
|
||||
// One day in the future since the time for today is already too late
|
||||
calendar.add(Calendar.DATE, 23)
|
||||
occurrences?.forEach {
|
||||
while (!calendar.matchesRepeatDays(daily.repeat)) {
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"return occurrences if active every fifth month on the second wednesday" {
|
||||
calendar.add(Calendar.MONTH, -8)
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1)
|
||||
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.WEDNESDAY) {
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
"dailies repeating monthly" should {
|
||||
beforeEach {
|
||||
daily.frequency = Frequency.MONTHLY
|
||||
}
|
||||
calendar.add(Calendar.DATE, 7)
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 5
|
||||
daily.setWeeksOfMonth(listOf(1))
|
||||
|
||||
reminder.time = calendar.time.toZonedDateTime()?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
"return occurrences if active every 10th of the month" {
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 1
|
||||
daily.setDaysOfMonth(listOf(10))
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4)
|
||||
occurrences?.size shouldBe 4
|
||||
calendar.add(Calendar.MONTH, 10)
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1)
|
||||
occurrences?.forEach {
|
||||
reminder.time = fakeZDT?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4, fakeZDT)
|
||||
occurrences?.size shouldBe 4
|
||||
occurrences?.forEach {
|
||||
while (calendar.get(Calendar.DAY_OF_MONTH) != 10) {
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
it.year shouldBe calendar.get(Calendar.YEAR)
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
}
|
||||
|
||||
"return occurrences if active every third month on the 5th" {
|
||||
calendar.add(Calendar.MONDAY, -8)
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 3
|
||||
daily.setDaysOfMonth(listOf(5))
|
||||
|
||||
reminder.time = fakeZDT?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4, fakeZDT)
|
||||
calendar.add(Calendar.MONTH, 9)
|
||||
occurrences?.size shouldBe 4
|
||||
occurrences?.forEach {
|
||||
while (calendar.get(Calendar.DAY_OF_MONTH) != 5) {
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
it.year shouldBe calendar.get(Calendar.YEAR)
|
||||
calendar.add(Calendar.MONTH, 3)
|
||||
}
|
||||
}
|
||||
|
||||
"return occurrences if active every month on the third tuesday" {
|
||||
val storedTime = calendar.time
|
||||
calendar.set(Calendar.YEAR, 2024)
|
||||
calendar.set(Calendar.MONTH, Calendar.DECEMBER)
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 17)
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 1
|
||||
daily.setWeeksOfMonth(listOf(2))
|
||||
calendar.time = storedTime
|
||||
if (calendar.get(Calendar.DAY_OF_MONTH) > 17) {
|
||||
calendar.add(Calendar.MONTH, 1)
|
||||
}
|
||||
|
||||
reminder.time = fakeZDT?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4, fakeZDT)
|
||||
occurrences?.size shouldBe 4
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1)
|
||||
occurrences?.forEach {
|
||||
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.TUESDAY) {
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
calendar.add(Calendar.DATE, 14)
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
it.year shouldBe calendar.get(Calendar.YEAR)
|
||||
calendar.add(Calendar.MONTH, 1)
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1)
|
||||
}
|
||||
}
|
||||
|
||||
"return occurrences if active every fifth month on the second wednesday" {
|
||||
calendar.add(Calendar.MONTH, -8)
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1)
|
||||
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.WEDNESDAY) {
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
calendar.add(Calendar.DATE, 7)
|
||||
print(daily.startDate)
|
||||
print(it)
|
||||
println(calendar.time)
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
it.year shouldBe calendar.get(Calendar.YEAR)
|
||||
calendar.add(Calendar.MONTH, 5)
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 5
|
||||
daily.setWeeksOfMonth(listOf(1))
|
||||
|
||||
reminder.time = fakeZDT?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4, fakeZDT)
|
||||
occurrences?.size shouldBe 4
|
||||
calendar.add(Calendar.MONTH, 10)
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1)
|
||||
occurrences?.forEach {
|
||||
while (calendar.get(Calendar.DAY_OF_WEEK) != Calendar.WEDNESDAY) {
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
}
|
||||
calendar.add(Calendar.DATE, 7)
|
||||
print(daily.startDate)
|
||||
print(it)
|
||||
println(calendar.time)
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
it.year shouldBe calendar.get(Calendar.YEAR)
|
||||
calendar.add(Calendar.MONTH, 5)
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"dailies repeating yearly" should {
|
||||
beforeEach {
|
||||
daily.frequency = Frequency.YEARLY
|
||||
}
|
||||
"return occurrences if active every year" {
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 1
|
||||
reminder.time = calendar.time.toZonedDateTime()?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
"dailies repeating yearly" should {
|
||||
beforeEach {
|
||||
daily.frequency = Frequency.YEARLY
|
||||
}
|
||||
"return occurrences if active every year" {
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 1
|
||||
reminder.time = fakeZDT?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4)
|
||||
occurrences?.size shouldBe 4
|
||||
calendar.add(Calendar.YEAR, 1)
|
||||
occurrences?.forEach {
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
it.year shouldBe calendar.get(Calendar.YEAR)
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4, fakeZDT)
|
||||
occurrences?.size shouldBe 4
|
||||
calendar.add(Calendar.YEAR, 1)
|
||||
occurrences?.forEach {
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
it.year shouldBe calendar.get(Calendar.YEAR)
|
||||
calendar.add(Calendar.YEAR, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"return occurrences if active every 3 years" {
|
||||
calendar.add(Calendar.YEAR, -3)
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 3
|
||||
reminder.time = calendar.time.toZonedDateTime()?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
"return occurrences if active every 3 years" {
|
||||
calendar.add(Calendar.YEAR, -3)
|
||||
calendar.add(Calendar.DATE, 1)
|
||||
daily.startDate = calendar.time
|
||||
daily.everyX = 3
|
||||
reminder.time = fakeZDT?.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)
|
||||
|
||||
calendar.add(Calendar.YEAR, 3)
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4)
|
||||
occurrences?.size shouldBe 4
|
||||
occurrences?.forEach {
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
it.year shouldBe calendar.get(Calendar.YEAR)
|
||||
calendar.add(Calendar.YEAR, 3)
|
||||
val occurrences = daily.getNextReminderOccurrences(reminder, 4, fakeZDT)
|
||||
occurrences?.size shouldBe 4
|
||||
occurrences?.forEach {
|
||||
it.dayOfYear shouldBe calendar.get(Calendar.DAY_OF_YEAR)
|
||||
it.year shouldBe calendar.get(Calendar.YEAR)
|
||||
calendar.add(Calendar.YEAR, 3)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue