我编写了一种将日期String转换为“ JDate” int(自1900年1月1日以来的天数,其中1900-01-01算作第1天)的方法。但是,我注意到它并不总是返回期望值。有时返回的值比预期值小一。我进行了一些实验,发现每年的期望值比3月的第二个星期一到11月的第一个星期日要小。我试图弄清楚,为什么呢?

这是我的代码:

public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
public static final SimpleDateFormat DATE_FORMAT_WITH_WEEK = new SimpleDateFormat("yyyy-MM-dd EEE");

/**
 * Conversion method
 */
public static int getJDateFromyyyyMMdd(String yyyyMMdd) throws ParseException {
    long millisForDate = DATE_FORMAT.parse(yyyyMMdd).getTime();
    long millisFor1900 = DATE_FORMAT.parse("1900-01-01").getTime();
    long millisSince1900 = millisForDate - millisFor1900;
    return (int)TimeUnit.DAYS.convert(millisSince1900, TimeUnit.MILLISECONDS) + 1;
}

/**
 * Method to test conversion method
 */
public static void testJDateConversion(Calendar calendar, int expectedValue) throws ParseException {
    String yyyyMMdd = DATE_FORMAT.format(calendar.getTime());
    String yyyyMMddEEE = DATE_FORMAT_WITH_WEEK.format(calendar.getTime());
    int actualValue = getJDateFromyyyyMMdd(yyyyMMdd);
    if(actualValue != expectedValue) {
        System.out.printf("%s\t\tExpected %d, Actual %d\n", yyyyMMddEEE, expectedValue, actualValue);
    }
}

/**
 * Execute
 */
public static void main(String[] args) throws ParseException {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(DATE_FORMAT.parse("1900-01-01"));
    Calendar futureDate = Calendar.getInstance();
    futureDate.setTime(DATE_FORMAT.parse("2020-12-31"));
    for(int expectedJDate = 1; calendar.before(futureDate); expectedJDate++) {
        testJDateConversion(calendar, expectedJDate);
        calendar.add(Calendar.DATE, 1);
    }
}


以下是一些打印出来的内容:

2013-11-02 Sat      Expected 41579, Actual 41578
2013-11-03 Sun      Expected 41580, Actual 41579
2014-03-10 Mon      Expected 41707, Actual 41706
2014-03-11 Tue      Expected 41708, Actual 41707

...

2014-11-01 Sat      Expected 41943, Actual 41942
2014-11-02 Sun      Expected 41944, Actual 41943
2015-03-09 Mon      Expected 42071, Actual 42070
2015-03-10 Tue      Expected 42072, Actual 42071

...

2015-10-31 Sat      Expected 42307, Actual 42306
2015-11-01 Sun      Expected 42308, Actual 42307
2016-03-14 Mon      Expected 42442, Actual 42441
2016-03-15 Tue      Expected 42443, Actual 42442


关于什么原因导致这种异常行为的任何想法?

最佳答案

我很确定您的问题是由DST(夏令时)引起的。夏季时间在三月至十月/十一月之间,并且因地区而异。

例如,在我的情况下,此代码:

    System.out.println(DATE_FORMAT.parse("2015-03-01"));
    DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
    System.out.println(DATE_FORMAT.parse("2015-03-01"));


产生以下输出:

Sun Mar 01 00:00:00 CET 2015
Sun Mar 01 01:00:00 CET 2015


您可以尝试将TimeZone设置为UTC。

(几年前,我曾在多个时区处理过此类DST问题,但记忆并不新鲜,我不得不再次挖掘一些东西。)

更新:

我为所有代码设置了一个通用的TimeZone,从而对您的代码进行了快速测试,现在它应该可以提供您期望的结果:

public static void main(String[] args) throws ParseException {
    TimeZone utc = TimeZone.getTimeZone("UTC");
    DATE_FORMAT.setTimeZone(utc);
    DATE_FORMAT_WITH_WEEK.setTimeZone(utc);
    Calendar calendar = Calendar.getInstance(utc);
    calendar.setTime(DATE_FORMAT.parse("1900-01-01"));
    Calendar futureDate = Calendar.getInstance(utc);
    futureDate.setTime(DATE_FORMAT.parse("2020-12-31"));
    ...
}

10-07 18:06