【问题标题】:Calendar set YEAR issue日历设置 YEAR 问题
【发布时间】:2011-11-24 22:53:42
【问题描述】:

我尝试了以下代码:

Calendar c1 = Calendar.getInstance();
c1.set(Calendar.YEAR, 0);
c1.set(Calendar.DAY_OF_YEAR, 1);
Date d1 = c1.getTime();

Calendar c2 = Calendar.getInstance();
c2.setTime(d1);
c2.set(Calendar.YEAR, 2001);
c2.set(Calendar.DAY_OF_YEAR, 1);
System.out.println(c2.getTime().toString());

Calendar c3 = Calendar.getInstance();
c3.set(Calendar.YEAR, 2000);
c3.set(Calendar.DAY_OF_YEAR, 1);
Date d2 = c3.getTime();

Calendar c4 = Calendar.getInstance();
c4.setTime(d2);
c4.set(Calendar.YEAR, 2001);
c4.set(Calendar.DAY_OF_YEAR, 1);
System.out.println(c4.getTime().toString());

结果是:

Wed Jan 01 23:47:00 CET 2001
Mon Jan 01 23:47:00 CET 2001

怎么了?我不应该以这种方式使用日历来设置 YEAR 吗?

【问题讨论】:

    标签: java date calendar


    【解决方案1】:

    年份与时代有关。通过将年份设置为小于或等于 0,日历会通过切换时代(从 AD 到 BC 或从 BC 到 AD)来自动更正这一点。这种行为在其他领域更为人所知。例如。如果您将月份设置为负数,则年份会相应减少。

    这些更正不是单独进行的,而是一次性进行的,通常是在您致电getTime() 读出结果日期时。

    Calendar c1 = Calendar.getInstance(); // August  16th, 2012 AD
    c1.set(Calendar.YEAR, 0);             // August  16th,    0 AD
    c1.set(Calendar.DAY_OF_YEAR, 1);      // January  1st,    0 AD
    Date d1 = c1.getTime();               // January  1st,    1 BC (corrected)
    
    Calendar c2 = Calendar.getInstance();
    c2.setTime(d1);
    c2.set(Calendar.YEAR, 2001);          // January  1st, 2001 BC
    c2.set(Calendar.DAY_OF_YEAR, 1);
    System.out.println(c2.getTime());     // prints "Wed Jan 01 05:35:00 CET 2001"
                                          // because 01/01/2001 BC was a Wednesday
    

    因此,您不必将年份设置为 2001,而是将其设置为 -2000(因为根本不存在年份 0)。或者您可以明确设置时代:

    c2.set(Calendar.ERA, GregorianCalendar.AD);
    

    解决此“错误”的另一种方法是在设置完整日期之前读出时间:

    Calendar c1 = Calendar.getInstance(); // August  16th, 2012 AD
    c1.set(Calendar.YEAR, 0);             // August  16th,    0 AD
    c1.set(Calendar.DAY_OF_YEAR, 1);      // January  1st,    0 AD
    c1.set(Calendar.YEAR, 2001);          // January  1st, 2001 AD
    System.out.println(c1.getTime());     // prints the expected date
    

    要输出日期的时代,您可以在SimpleDateFormat 的模式中使用“G”:

    new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy G").format(c2.getTime())
    // "Wed Jan 01 05:35:00 CET 2001 BC"
    

    【讨论】:

      【解决方案2】:

      在这两种情况下,在打印输出之前,您将年份设置为 2001 年。在这两种情况下,输出都反映了该年份。你期待不同的输出吗?

      【讨论】:

      • 周三与周一。此外,如果我将 MILLISEC 和 SEC 设置为 0,并比较两个日期,它们的结果将不相等。最初我的目的是规范化 DateTime 对象的日期部分,以便仅比较时间部分。
      • 哈哈!什么……?是的,那个是我找的。在我看来,您发现了一个错误。
      • 异常行为似乎与将 c1 年份设置为 0 (或负年份,事实证明)有关。当我尝试积极的年份时,我只看到了正确的星期一结果。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-09
      • 1970-01-01
      相关资源
      最近更新 更多