Я создал финансовое приложение и хочу, чтобы приложение показывало пользователю финансовый месяц. Финансовые месяцы обычно представляют собой день, когда пользователь получает зарплату или самый большой доход. Этот день может быть первым днем месяца, последним днем месяца или просто 15-м числом каждого месяца. Это значение настраивается в настройках.
Я попытался запустить два метода, которые вызываются в моей ViewModel, getFirstDayOfMonth
и getLastDayOfMonth
.
Чтобы лучше понять контекст, вот несколько примеров, за основу которых мы возьмем сегодняшнюю дату. 9 сентября 2020 г. Входное значение — это значение, которое я считываю из настроек, из которых пользователь может выбрать, представляет собой число от 1 до 31 включительно.
Примеры: Ввод: 5 Выход: 5 сентября 2020 г. в 00:00 для начала и 4 октября 2020 г. в 23:59:59 для окончания.
================
Ввод: 31 Выход: 31 августа 2020 г., 00:00 для начала и 30 сентября 2020 г., 23:59:59.
Загвоздка в том, что если в месяце нет этого дня, то он получит ближайший слева, например, если в качестве первого дня выбрано 31, а в месяце 30 дней, то 30 будет считаться первым днем, а также для даты окончания, если выбрано 31, а мы находимся в феврале, и у него всего 28 дней, будет выбрано 28.
До сих пор у меня есть этот код, но я чувствую, что его можно улучшить, а также он работает не так, как ожидалось.
fun getFirstDayOfMonth(date: LocalDateTime): Long {
var tempDate = date
val firstDayOfMonth = lastDay?.filter { it.isDigit() }!!.toInt()
if (firstDayOfMonth < tempDate.dayOfMonth) {
tempDate = tempDate.withDayOfMonth(firstDayOfMonth)
} else if (firstDayOfMonth > tempDate.dayOfMonth) {
tempDate = tempDate.minusMonths(1)
if (tempDate.monthValue == 12) {
//I don't know why minusMonths does not work in the same way as plusMonths, when I write .plusMonths(1) it also change the year if I am in december, with minusMonths if I am in January it does not change the year to minus one year.
tempDate = tempDate.minusYears(1)
}
if (firstDayOfMonth > tempDate.with(TemporalAdjusters.lastDayOfMonth()).dayOfMonth) {
tempDate.withDayOfMonth(tempDate.with(TemporalAdjusters.lastDayOfMonth()).dayOfMonth)
} else {
tempDate = tempDate.withDayOfMonth(firstDayOfMonth)
}
}
return tempDate.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
}
fun getLastDayOfMonth(date: LocalDateTime): Long {
var tempDate = date
val firstDayOfMonth = lastDay?.filter { it.isDigit() }!!.toInt()
if (firstDayOfMonth > tempDate.dayOfMonth && firstDayOfMonth <= tempDate.with(
TemporalAdjusters.lastDayOfMonth()
).dayOfMonth
) {
tempDate = tempDate.withDayOfMonth(firstDayOfMonth).minusDays(1)
} else {
tempDate = tempDate.plusMonths(1)
if (firstDayOfMonth > tempDate.with(TemporalAdjusters.lastDayOfMonth()).dayOfMonth) {
tempDate.withDayOfMonth(tempDate.with(TemporalAdjusters.lastDayOfMonth()).dayOfMonth)
} else {
tempDate = tempDate.withDayOfMonth(firstDayOfMonth).minusDays(1)
}
}
return tempDate.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()
}
В качестве примера я написал тест, который запускает сегодняшнюю дату и только меняет месяц с января на декабрь. Вот результат текущего алгоритма. 1-е число месяца — это дата, выбранная пользователем, которая также используется по умолчанию в приложении.
Todays date 09.01.2020
Running for month January
Running for 1 st of the month
01.01.2020
31.01.2020
===========================================
Todays date 09.02.2020
Running for month February
Running for 1 st of the month
01.02.2020
29.02.2020
===========================================
Todays date 09.03.2020
Running for month March
Running for 1 st of the month
01.03.2020
31.03.2020
===========================================
Todays date 09.04.2020
Running for month April
Running for 1 st of the month
01.04.2020
30.04.2020
===========================================
Todays date 09.05.2020
Running for month May
Running for 1 st of the month
01.05.2020
31.05.2020
===========================================
Todays date 09.06.2020
Running for month June
Running for 1 st of the month
01.06.2020
30.06.2020
===========================================
Todays date 09.07.2020
Running for month July
Running for 1 st of the month
01.07.2020
31.07.2020
===========================================
Todays date 09.08.2020
Running for month August
Running for 1 st of the month
01.08.2020
31.08.2020
===========================================
Todays date 09.09.2020
Running for month September
Running for 1 st of the month
01.09.2020
30.09.2020
===========================================
Todays date 09.10.2020
Running for month October
Running for 1 st of the month
01.10.2020
31.10.2020
===========================================
Todays date 09.11.2020
Running for month November
Running for 1 st of the month
01.11.2020
30.11.2020
===========================================
Todays date 09.12.2020
Running for month December
Running for 1 st of the month
01.12.2020
31.12.2021
===========================================
Process finished with exit code 0
Также для 31 избранного
Todays date 09.01.2020
Running for month January
Running for 31 th of the month
31.12.2019
30.01.2020
===========================================
Todays date 09.02.2020
Running for month February
Running for 31 th of the month
31.01.2020
30.03.2020
===========================================
Todays date 09.03.2020
Running for month March
Running for 31 th of the month
09.02.2020
30.03.2020
===========================================
Todays date 09.04.2020
Running for month April
Running for 31 th of the month
31.03.2020
30.05.2020
===========================================
Todays date 09.05.2020
Running for month May
Running for 31 th of the month
09.04.2020
30.05.2020
===========================================
Todays date 09.06.2020
Running for month June
Running for 31 th of the month
31.05.2020
30.07.2020
===========================================
Todays date 09.07.2020
Running for month July
Running for 31 th of the month
09.06.2020
30.07.2020
===========================================
Todays date 09.08.2020
Running for month August
Running for 31 th of the month
31.07.2020
30.08.2020
===========================================
Todays date 09.09.2020
Running for month September
Running for 31 th of the month
31.08.2020
30.10.2020
===========================================
Todays date 09.10.2020
Running for month October
Running for 31 th of the month
09.09.2020
30.10.2020
===========================================
Todays date 09.11.2020
Running for month November
Running for 31 th of the month
31.10.2020
30.12.2021
===========================================
Todays date 09.12.2020
Running for month December
Running for 31 th of the month
09.11.2020
30.12.2021
===========================================
Process finished with exit code 0