java - 计算每年3月到11月的一次JDate

标签 java date

我编写了一个方法,将日期字符串转换为“JDate”int(自 1900 年 1 月 1 日以来的天数,其中 1900-01-01 算作第 1 天)。然而,我注意到它并不总是返回预期值;有时它返回的值比预期值少一。我做了一些实验,发现每年从三月的第二个星期一到十一月的第一个星期天,预期值都会减少一个。我想弄清楚这是为什么?

这是我的代码:

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

您可以尝试将时区设置为 UTC。

(几年前我曾研究过此类多时区的 DST 问题,但我的内存不太清晰,我必须再次挖掘一些东西。)

更新:

我尝试对您的代码进行快速测试,为所有内容设置通用时区,现在它应该给出您期望的结果:

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"));
    ...
}

关于java - 计算每年3月到11月的一次JDate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30355008/

相关文章:

Java 迭代类的集合并使用它们的函数

java - Rhino 中的 XMLHttpRequest?

python - 如何将日期转换为 0001-01-01 中的天数?

java - 从日历对象显示“MM/DD/YYYY”(重复)

sql - 在 SQL Server 2008 中创建日期

java - 如何在预期可运行实例的地方接受方法引用运算符?

java - 是否可以仅使用按位运算符将无符号整数的 4 个小字节序字节分配给 Java 原语?

javascript - moment.js : format a date keeping the locale's day, 年月顺序

javascript - Angular 2日期管

java - 将 jQuery div 导出为图片