错误的月份最后一天

Wrong last day of month

我的服务中哪里有获取月份最后一天的函数?

 DateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
        Date date = format.parse(stringDate);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        calendar.add(Calendar.MONTH, 1);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.add(Calendar.DATE, -1);

        Date lastDayOfMonth = calendar.getTime();

        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        return sdf.format(lastDayOfMonth);

因此,此方法在其他地方也适用,但在美国,最后一天始终为 29(最后一天 - 1)

stringDate 是 "yyyy-MM-dd"

格式的日期

Java日期很差API。相反,我建议您使用 Joda Time

在 Joda 中它看起来像这样:

LocalDate endOfMonth = date.dayOfMonth().withMaximumValue();

我认为这个问题是由于 Day Light saving time 在美国造成的。

您可以通过将日历的时区设置为不同的时区来更改此设置。

相关问题:Adding days with java.util.Calendar gives strange results

如果你没有 Java 8,这与 JodaTime 非常紧凑。

import org.joda.time.DateTime;

public class SoLastDay {
    public DateTime lastDay(final String yyyy_MM_dd) {
        DateTime givenDate = new DateTime(yyyy_MM_dd);
        return givenDate.dayOfMonth().withMaximumValue();
    }
}

还有一个小测试...

@Test
public void testLastDay() throws Exception {
    SoLastDay soLastDay = new SoLastDay();

    String date1 = "2015-01-27";
    System.out.printf("Date %s becomes %s.\n", date1, soLastDay.lastDay(date1).toString("yyyy-MM-dd"));

    String date2 = "2015-02-02";
    System.out.printf("Date %s becomes %s.\n", date2, soLastDay.lastDay(date2).toString("yyyy-MM-dd"));

}

以及测试结果:

Date 2015-01-27 becomes 2015-01-31.
Date 2015-02-02 becomes 2015-02-28.

如果您 有 Java 8,您可以使用这样的代码:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;

public class SoLastDayJava8 {
    static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    public LocalDate lastDay(final String yyyy_MM_dd) {
        LocalDate givenDate = LocalDate.parse(yyyy_MM_dd, formatter);
        return givenDate.with(TemporalAdjusters.lastDayOfMonth());
    }
}

测试代码略有改动。

public class SoLastDayJava8Test {

    @Test
    public void testLastDay() throws Exception {
        SoLastDayJava8 soLastDay = new SoLastDayJava8();

        String date1 = "2015-01-27";
        System.out.printf("Date %s becomes %s.\n", date1, soLastDay.lastDay(date1));

        String date2 = "2015-02-02";
        System.out.printf("Date %s becomes %s.\n", date2, soLastDay.lastDay(date2));

    }
}

但是结果是一样的

Date 2015-01-27 becomes 2015-01-31.

Date 2015-02-02 becomes 2015-02-28.

你在搞乱 TimeZones

当您执行 Date date = format.parse(stringDate); 时,您正在使用 DateFormat 对象的 TimeZone 创建一个 Date 对象。理论上,如果 TimeZone 对于所有 DateFormatCalendar 对象都是相同的,你应该没问题。检查它们是否与 getTimeZone() 方法一致。

如果第一个 DateFormatTimeZone 是错误的(例如,是你的 TimeZoneUTCGMT),你会得到一个UTC-008 第二个 TimeZone(和 Calendar)的转换导致您从午夜开始后缺少一天。

从您的代码判断 stringDate 本身在其他地方被错误地转换了...