我正在尝试编写一个算法,该算法基于一个从1到31的数字(一个月中的一天),它将返回该天/数字之前时刻的毫秒。算法将始终使用今天的日期。
例子:投入:5产出: 1601845199000,即2020年10月4日23:59:59
================
投入: 31产出: 1601499599000,即2020年9月30日23:59:59
因为这个月没有31天,即使给出31天,算法也会取最接近的日期。
同样的事情发生在2月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也会运行相同的代码,因为在相同的代码中运行的所有三个字段都没有中断。
但是,我认为绝对没有在DAY_OF_MONTH、DAY_OF_YEAR和DAY_OF_WEEK上运行的代码。
我找不到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 ...发布于 2020-09-07 13:54:01
您可以使用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-03LocalDate.now()计算今天的日期(注意:只计算日期部分,不涉及一天中的时间、偏移量或时区),并返回一个LocalDate,该方法具有方法minusDays(long days),该方法在必要时通过调整月份和年份来正确计算日期。
如果您做了以下操作:
println(LocalDate.of(2020, 1, 1).minusDays(1))输出将是
2019-12-31如果您需要一个时间部分,甚至是一个偏移量或时区,以真正正确地减去天、小时、分钟或任何单位的时间,请查看java.time中的其他类.
在您的问题下面的评论之后进行编辑:
如果你进入7号,今天是9月7日,你应该是10月6日。如果你进入8号,你将得到9月7日(今天)。
fun findDate(dayOfMonth: Int): LocalDate {
val now = LocalDate.now()
val currentDayOfMonth = now.getDayOfMonth()
if (currentDayOfMonth <= dayOfMonth) {
// use the current month with the given day of month
return now.withDayOfMonth(dayOfMonth)
// subtract a day (will change the month when dayOfMonth == 1)
.minusDays(1)
// and add a month
.plusMonths(1)
} else {
// otherwise just take the current month with the given day of month
return now.withDayOfMonth(dayOfMonth)
// and subtract a day
.minusDays(1)
}
}注意:我猜到了这样的情况,即月中的输入日少于今天的一天,因为您没有指定它的任何行为。这种情况的处理方式与月中相同的日(争论和今天)相同。
发布于 2020-09-07 17:49:05
这是我的行动。与deHaar一样,我强烈建议在您的日期和时间工作中使用java.time (现代Java和time )。您尝试使用的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);它决定了我们运行时区的不同。我在欧洲/布加勒斯特时区运行,因为我以为它是你的。今日(九月七日)的产出如下:
目标日期和时间:2020-09-30T23:59:59+03:00欧洲/布加勒斯特目标毫秒: 1601499599000
链接: Oracle教程:日期时间解释如何使用java.time。
https://stackoverflow.com/questions/63778008
复制相似问题