当前位置: 首页 > 知识库问答 >
问题:

Java日期-闰年-奇怪的行为

周通
2023-03-14

该表包含每个月的内容:第一天、最后一天以及这两天之间的天数。

预期成果:

/**

英国标准时间2016年9月30日(星期五)00:00:00-英国标准时间2016年10月29日(星期六)23:59:59

2016年10月30日太阳00:00:00英国标准时间2016年11月29日星期二23:59:59 GMT 2016-31

格林尼治时间2016年11月30日00:00:00-格林尼治时间2016年12月29日星期四23:59:59

2016年2月29日星期一00:00:00欧洲东部时间::::2016年3月28日星期一23:59:59欧洲东部时间::::28

2016年3月29日星期二00:00:00(东部时间):::::2016年4月28日星期四23:59:59(东部时间)::::30

2016年4月29日星期五00:00:00(东部时间2016年5月28日星期六)23:59:59(东部时间2016年4月29日)::::29

2016年9月29日星期四00:00:00(东部时间)::::2016年10月28日星期五23:59:59(东部时间)::::29

2016年10月29日星期六00:00:00(东部时间2016年11月28日星期一23:59:59(东部时间2016年)::::31

2016年11月29日星期二00:00:00欧洲东部时间:::::2016年12月28日星期三23:59:59欧洲东部时间::::29

这是我的代码

import org.apache.commons.lang.time.DateUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class Main {

    public static void main(String[] args) throws ParseException {
        String startDate = "30 Jan 2016";
        String endDate = "29 Jan 2017"; // current not using this ?!
        SimpleDateFormat formatter = new SimpleDateFormat("dd MMM yyyy");

        Date start = formatter.parse(startDate);

        List<Item> items = new ArrayList<>();

        for (int i = 0; i < 12; i++) {
            Date end = DateUtils.addMonths(start, 1);
            end = DateUtils.addSeconds(end, -1);
            items.add(new Item(start, end));
            start = DateUtils.addMonths(start, 1);
        }

        items.forEach(item -> {
            System.out.println(item.getStart() + " ::::: " + item.getEnd() + " ::::: " + getDifferenceDays(item.getStart(), item.getEnd()));
        });

    }

    public static long getDifferenceDays(Date d1, Date d2) {
        return ChronoUnit.DAYS.between(d1.toInstant(), d2.toInstant());
    }

}
  • 项类
import java.util.Date;

public class Item {
    Date start;
    Date end;

    public Item(Date start, Date end) {
        this.start = start;
        this.end = end;
    }

    public Date getStart() {
        return start;
    }

    public void setStart(Date start) {
        this.start = start;
    }

    public Date getEnd() {
        return end;
    }

    public void setEnd(Date end) {
        this.end = end;
    }

    @Override
    public String toString() {
        return "Item{" +
                "start=" + start +
                ", end=" + end +
                '}';
    }
}

共有1个答案

段干安和
2023-03-14

由于您可以使用Java.time,即现代Java日期和时间API,所以我建议您坚持使用它,不要使用旧的类simpledateformatdate。那么您也不需要Apachedateutilschronounit枚举来自java.time。

    DateTimeFormatter dateFormatter
            = DateTimeFormatter.ofPattern("d MMM u", Locale.ENGLISH);
    
    String startDateString = "30 Jan 2016";
    LocalDate originalStartDate
            = LocalDate.parse(startDateString, dateFormatter);
    for (int i = 0; i < 12; i++) {
        LocalDate startDate = originalStartDate.plusMonths(i);
        LocalDate nextStartDate = originalStartDate.plusMonths(i + 1);
        LocalDate endDate = nextStartDate.minusDays(1);
        long differenceDays = ChronoUnit.DAYS.between(startDate, nextStartDate);
        
        System.out.format("%s - %s : %d%n", startDate, endDate, differenceDays);
    }

输出为:

2016-01-30 - 2016-02-28 : 30
2016-02-29 - 2016-03-29 : 30
2016-03-30 - 2016-04-29 : 31
2016-04-30 - 2016-05-29 : 30
2016-05-30 - 2016-06-29 : 31
2016-06-30 - 2016-07-29 : 30
2016-07-30 - 2016-08-29 : 31
2016-08-30 - 2016-09-29 : 31
2016-09-30 - 2016-10-29 : 30
2016-10-30 - 2016-11-29 : 31
2016-11-30 - 2016-12-29 : 30
2016-12-30 - 2017-01-29 : 31

在你观察到的意想不到的结果背后有几个原因。

    null
 类似资料:
  • 所以我更新了代码,添加了行所做的是将主线程置于Hibernate状态一段时间,因此jvm可以获得一些时间来创建一个新线程。我正在得到我的预期输出

  • 如果使用Excel的< code>YEARFRAC(date1,date2,1)函数,则Excel将按照第二个参数使用基数。如果日期1和日期2在同一年,这没有关系,但如果日期1是闰年(例如2020年)而日期2是非闰年(例如2021年),这就有关系了 我认为更准确的计算应该考虑到< code>date1的基数可能不同于< code>date2的基数。 例如,< code>YEARFRAC(15/12

  • 我在 Android 中面临日期解析的真正问题。我通过 JSON 接收一个日期,日期为 dd/MM/yyyy HH:mm z 格式,我所需要的只是获取“本地化”的小时和分钟并将其显示在我的应用程序中。使用我的代码,每台设备上一切正常,但我的客户报告说,他们在使用索尼XPERIA设备时无法看到应用程序中的时间。他们还告诉我,他们有一个无法显示时间的XPeria设备,然后他们扎根它,一切都开始正常工作

  • 我发现了Java并发的奇怪行为。请参阅下面的下一段代码: 在我看来,这段代码应该挂起并永远等待,但是在控制台中的next out没有任何问题地完成了代码: 我试图找到一些关于如果线程死了通知锁的信息,但缺乏。我也没有在Java规范中找到任何信息。 但是如果我试图锁定其他对象(而不是thread对象),就会像我预期的那样工作得很好。

  • 如果有人理解java编译器为什么这么做,请解释一下。

  • 下面的代码是一个小示例,可以轻松重现问题。所以我有 String 类型的变量,它设置了默认值。我有3种方法: getter 塞特 将字符串转换为布尔值的方便方法 自省不会将getter作为readMethod返回,将setter作为WriteMethod返回。相反,它将isTest()方法作为readMethod返回。setter为空。 从文档中我了解到,如果类型是boolean,那么" is "