首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >添加未按预期工作的日历日

添加未按预期工作的日历日
EN

Stack Overflow用户
提问于 2020-09-07 12:52:58
回答 2查看 202关注 0票数 0

我正在尝试编写一个算法,该算法基于一个从1到31的数字(一个月中的一天),它将返回该天/数字之前时刻的毫秒。算法将始终使用今天的日期。

例子:投入:5产出: 1601845199000,即2020年10月4日23:59:59

================

投入: 31产出: 1601499599000,即2020年9月30日23:59:59

因为这个月没有31天,即使给出31天,算法也会取最接近的日期。

同样的事情发生在2月29日/30日。

代码语言:javascript
复制
    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,我看到以下内容:

代码语言:javascript
复制
        // 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_MONTHDAY_OF_YEARDAY_OF_WEEK上运行的代码。

我找不到DATE字段

==================================================

使用LocalDateTime

代码语言:javascript
复制
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 ...
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-09-07 13:54:01

您可以使用java.time,它提供了非常方便的方法。

参见此示例:

代码语言:javascript
复制
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执行)

代码语言:javascript
复制
2020-09-03

LocalDate.now()计算今天的日期(注意:只计算日期部分,不涉及一天中的时间、偏移量或时区),并返回一个LocalDate,该方法具有方法minusDays(long days),该方法在必要时通过调整月份和年份来正确计算日期。

如果您做了以下操作:

代码语言:javascript
复制
println(LocalDate.of(2020, 1, 1).minusDays(1))

输出将是

代码语言:javascript
复制
2019-12-31

如果您需要一个时间部分,甚至是一个偏移量或时区,以真正正确地减去天、小时、分钟或任何单位的时间,请查看java.time中的其他类.

在您的问题下面的评论之后进行编辑:

如果你进入7号,今天是9月7日,你应该是10月6日。如果你进入8号,你将得到9月7日(今天)。

代码语言:javascript
复制
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)
    }
}

注意:我猜到了这样的情况,即月中的输入日少于今天的一天,因为您没有指定它的任何行为。这种情况的处理方式与月中相同的日(争论和今天)相同。

票数 2
EN

Stack Overflow用户

发布于 2020-09-07 17:49:05

这是我的行动。与deHaar一样,我强烈建议在您的日期和时间工作中使用java.time (现代Java和time )。您尝试使用的Calendar类设计很差,而且已经过时了。

由于您希望午夜前1秒的时间,让我们首先使用以下值声明一个常量:

代码语言:javascript
复制
private static final Duration timeBeforeStartOfDay = Duration.ofSeconds(1); 

如果你喜欢某一天,它很容易改变,比如说,1分钟,1毫秒或1纳秒。

有些案件我们需要考虑。我认为这个代码是这样的:

代码语言:javascript
复制
    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。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63778008

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档