我已经创建了一个财务应用程序,并且希望该应用程序向用户显示财务月份。财务月通常代表用户获得薪水或最高收入的日子。那天可能是一个月的第一天,该月的最后一天,或者仅仅是每个月的15号。 该值可以在设置中配置。
我尝试运行在ViewModel中调用的两个方法getFirstDayOfMonth
和getLastDayOfMonth
为了更好地理解上下文,这里有一些示例,我们将以今天的日期作为参考。 2020年9月9日。“输入值”是我从设置中读取的值(用户可以从中选择),它是1到31之间的一个数字。
示例:输入:5输出:2020年9月5日开始于00:00,2020年10月4日在结束23:59:59
================
输入:31输出:2020年8月31日开始00:00和2020年9月30日23:59:59
要注意的是,如果月份中没有该天,它将获得最左侧的日期,例如,如果选择第一天为31,并且该月份有30天,则将计算30天。第一天,也包括结束日期,如果选择了31天并且我们在2月,并且只有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月更改为12月。这是当前算法的输出。 每月的第一天是用户选择的日期,该日期也在应用程序中默认设置。
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
答案 0 :(得分:1)
您的计算中有一些错误,一旦您理解了以下给出的解决方案,就可以很容易地发现它们。我在代码中添加了足够的注释,可以帮助您快速理解。
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.YearMonth;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
public class Main {
public static void main(String[] args) {
// Test for 31
int startDay = 31;
System.out.println(Instant.ofEpochMilli(getFirstDayOfMonth(startDay, YearMonth.of(2020, Month.SEPTEMBER))));
System.out.println(Instant.ofEpochMilli(getLastDayOfMonth(startDay, YearMonth.of(2020, Month.SEPTEMBER))));
System.out.println(Instant.ofEpochMilli(getFirstDayOfMonth(startDay, YearMonth.of(2020, Month.FEBRUARY))));
System.out.println(Instant.ofEpochMilli(getLastDayOfMonth(startDay, YearMonth.of(2020, Month.FEBRUARY))));
// Test for 30
startDay = 30;
System.out.println();
System.out.println(Instant.ofEpochMilli(getFirstDayOfMonth(startDay, YearMonth.of(2020, Month.SEPTEMBER))));
System.out.println(Instant.ofEpochMilli(getLastDayOfMonth(startDay, YearMonth.of(2020, Month.SEPTEMBER))));
System.out.println(Instant.ofEpochMilli(getFirstDayOfMonth(startDay, YearMonth.of(2020, Month.FEBRUARY))));
System.out.println(Instant.ofEpochMilli(getLastDayOfMonth(startDay, YearMonth.of(2020, Month.FEBRUARY))));
// Test for 28
startDay = 28;
System.out.println();
System.out.println(Instant.ofEpochMilli(getFirstDayOfMonth(startDay, YearMonth.of(2020, Month.SEPTEMBER))));
System.out.println(Instant.ofEpochMilli(getLastDayOfMonth(startDay, YearMonth.of(2020, Month.SEPTEMBER))));
System.out.println(Instant.ofEpochMilli(getFirstDayOfMonth(startDay, YearMonth.of(2020, Month.FEBRUARY))));
System.out.println(Instant.ofEpochMilli(getLastDayOfMonth(startDay, YearMonth.of(2020, Month.FEBRUARY))));
}
static long getFirstDayOfMonth(int startDay, YearMonth ym) {
// Get last day of the month
int lastDayOfTheMonth = ym.getMonth().length(ym.isLeapYear());
// Start of the day and on the first day of the month
LocalDateTime ldt = LocalDate.of(ym.getYear(), ym.getMonth(), 1)
.atStartOfDay();
if (startDay > lastDayOfTheMonth) {
ldt = ldt.minusMonths(1) // Go back to the last month
.with(TemporalAdjusters.lastDayOfMonth()); // Adjust to the last day of the obtained month
}
return ldt.toInstant(ZoneOffset.UTC).toEpochMilli();
}
static long getLastDayOfMonth(int startDay, YearMonth ym) {
return Instant.ofEpochMilli(getFirstDayOfMonth(startDay, ym))// Get the point to start with
.plus(ym.getMonth().length(ym.isLeapYear()), ChronoUnit.DAYS)// Add the no. of days of the given month
.atOffset(ZoneOffset.UTC)// Get OffsetDateTime in order to get LocalDate
.toLocalDate()// Convert to LocalDate
.atTime(LocalTime.of(23, 59, 59))// At 23:59:59
.toInstant(ZoneOffset.UTC)// Convert to Instant
.toEpochMilli();
}
}
输出:
2020-08-31T00:00:00Z
2020-09-30T23:59:59Z
2020-01-31T00:00:00Z
2020-02-29T23:59:59Z
2020-09-01T00:00:00Z
2020-10-01T23:59:59Z
2020-01-31T00:00:00Z
2020-02-29T23:59:59Z
2020-09-01T00:00:00Z
2020-10-01T23:59:59Z
2020-02-01T00:00:00Z
2020-03-01T23:59:59Z
答案 1 :(得分:0)
该LocalDateTime类似乎具有您需要内置的所有功能。检查minusDays和plusDays方法。