我编写了一种将日期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"));
...
}