我正在尝试编写一种算法,该算法基于1到31(一个月中的一天)之间的数字,它将返回该日期/数字之前时刻的毫秒数。 该算法将始终使用今天的日期。
示例: 输入5 输出:1601845199000,即2020年10月4日23:59:59
================
输入:31 输出:1601499599000,这是2020年9月30日在23:59:59
因为月份没有31天,即使指定了31天,算法也会采用最接近的日期。
2月29日(29/30)也是如此
val calendar = Calendar.getInstance()
calendar.set(Calendar.HOUR_OF_DAY, 23)
calendar.set(Calendar.MINUTE, 59)
calendar.set(Calendar.SECOND, 59)
calendar.clear(Calendar.MILLISECOND)
val lastDayNumber = 31
var found = false
while (!found) {
if (calendar.get(Calendar.DAY_OF_MONTH) <= lastDayNumber) {
found = true
}
if (calendar.get(Calendar.DAY_OF_MONTH) < lastDayNumber) {
calendar.add(Calendar.DATE, 1)
}
}
问题是calendar.add(Calendar.DATE, 1)
根本无法工作。
此方法应找到将来给出的数字的前一天。我想念什么吗?我已经阅读了文档和其他StackOverflow答案,但仍然无法理解。
Edit1:我也尝试过calendar.add(Calendar.DAY_OF_MONTH, 1)
和+1,但是-1工作得很好。
Edit2:
看着GregorianCalendar.java
,我看到以下内容:
// Handle week, day and AM_PM fields which involves
// time zone offset change adjustment. Convert the
// given amount to the number of days.
case WEEK_OF_YEAR:
case WEEK_OF_MONTH:
case DAY_OF_WEEK_IN_MONTH:
delta *= 7;
break;
case DAY_OF_MONTH: // synonym of DATE
case DAY_OF_YEAR:
case DAY_OF_WEEK:
break;
如果我以WEEL_OF_YEAR
为例,则相同的代码还将在week_of_month和day_of_week_in_month运行,因为不间断,所有3个字段都通过相同的代码运行。
但是,我发现绝对没有代码可以在DAY_OF_MONTH
,DAY_OF_YEAR
和DAY_OF_WEEK
上运行。
P.S。我找不到DATE
字段
================================================ ===
使用LocalDateTime
fun getLastDayOfMonth(date: LocalDateTime): Long {
val lastDayNumber = lastDay?.filter { it.isDigit() }!!.toInt()
var found = false
while (!found) {
if (date.dayOfMonth <= lastDayNumber) {
found = true
} else {
date.plusDays(1)
}
}
return date.toEpochSecond(ZoneOffset.UTC)
}
date.plusDays(1) is not changing the date variable to be next day ...
答案 0 :(得分:2)
您可以使用java.time
,它为此提供了非常方便的方法。
请参见以下示例:
import java.time.LocalDate
fun main() {
val fourDaysAgo = findDate(4)
println(fourDaysAgo)
}
fun findDate(daysAgo: Long): LocalDate {
return LocalDate.now().minusDays(daysAgo)
}
它输出4天前的日期(今天/ 2020-09-07执行)
2020-09-03
LocalDate.now()
计算今天的日期(注意:仅是日期部分,不涉及一天中的时间,偏移量或时区),并返回具有方法LocalDate
的{{1}}如有必要,可以通过调整月份和年份来正确计算之前的日期。
如果您执行以下操作:
minusDays(long days)
输出为
println(LocalDate.of(2020, 1, 1).minusDays(1))
如果您还需要时间部分,甚至可能需要偏移量或时区来真正正确地减去天,小时,分钟或任何时间单位,请查看2019-12-31
中的其他类。
编辑:
如果输入7,今天是9月7日,则应该是10月6日。如果输入8,则应该是9月7日(今天)
java.time
注意:我猜想输入月份少于今天的情况是因为您没有为它指定任何行为。该案件的处理方式与每月(争论和今天)的天数相同。
答案 1 :(得分:1)
这是我的去。像deHaar一样,我强烈建议您使用java.time(现代的Java日期和时间API)进行日期和时间工作。您尝试使用的Calendar
类的设计很差,而且已经过时。
由于您希望将时间设为午夜前1秒钟,因此我们首先声明一个具有以下值的常量:
private static final Duration timeBeforeStartOfDay = Duration.ofSeconds(1);
如果您希望有一天,可以很容易地将其更改为1分钟,1毫秒或1纳秒。
我们需要考虑一些极端情况。我认为这段代码可以做到:
ZoneId zone = ZoneId.systemDefault();
int dayNumber = 31;
LocalDate today = LocalDate.now(zone);
YearMonth ym = YearMonth.from(today);
if (dayNumber <= today.getDayOfMonth()) {
// Next month
ym = ym.plusMonths(1);
}
ZonedDateTime targetDateTime;
if (dayNumber > ym.lengthOfMonth()) {
// Use end of month
targetDateTime = ym.plusMonths(1)
.atDay(1)
.atStartOfDay(zone)
.minus(timeBeforeStartOfDay);
} else {
// Use day number
targetDateTime = ym.atDay(dayNumber)
.atStartOfDay(zone)
.minus(timeBeforeStartOfDay);
}
long milliseconds = targetDateTime.toInstant().toEpochMilli();
System.out.println("Target date and time: " + targetDateTime);
System.out.println("Target milliseconds: " + milliseconds);
我们在哪个时区运行它会有所不同。我在欧洲/布加勒斯特时区运行过它,因为我想它可能是您的。今天(9月7日)的输出为:
Target date and time: 2020-09-30T23:59:59+03:00[Europe/Bucharest] Target milliseconds: 1601499599000
链接: Oracle tutorial: Date Time解释了如何使用java.time。