将DAY_OF_MONTH或DAY_OF_YEAR添加到Calendar对象之间的区别是什么?

时间:2012-12-28 05:51:36

标签: java datetime

我想将某个日期增加1天。我创建了一个Calendar对象,如:

Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2012);
cal.set(Calendar.MONTH, 0);
cal.set(Calendar.DAY_OF_MONTH, 31);

然后,为了增加1天,我可以做两件事:

cal.add(Calendar.DAY_OF_MONTH, 1);

OR

cal.add(Calendar.DAY_OF_YEAR, 1);

还有其他“DAY”常数,但我使用上述两种增加1的方法得到相同的结果。在这种情况下,我会得到两个不同的结果吗?

11 个答案:

答案 0 :(得分:43)

添加它确实没什么区别,但是这个

Calendar c = Calendar.getInstance();
System.out.println(c.get(Calendar.DAY_OF_MONTH));
System.out.println(c.get(Calendar.DAY_OF_YEAR));

打印

28
363

答案 1 :(得分:11)

  

Calendar.add根据日历的规则,在指定的日历字段中添加或减去指定的时间。

这里有一个可以添加或减去的fields of Calendar列表:

小时,天和周有多个字段,但选择哪一个 1 并不重要。例如,对DAY_OF_WEEK使用-8将起作用。

calendar.add(Calendar.DAY_OF_MONTH, -2); // subtract 2 days
calendar.add(Calendar.DAY_OF_WEEK, -2);  // subtract 2 days
calendar.add(Calendar.DAY_OF_YEAR, -2);  // subtract 2 days

calendar.add(Calendar.YEAR, -2);         // subtract 2 year

1 使用Calendar.add无关紧要,其他操作结果可能不同。

答案 2 :(得分:8)

Calendar.DATE用于您的目的。在您的情况下,这三个常量是同义词。

答案 3 :(得分:7)

调用add时没有任何区别。然而,吸气剂返回不同的结果:D

来自GregorianCalendar#add

代码段

case DAY_OF_MONTH: // synonym of DATE
 case DAY_OF_YEAR:
 case DAY_OF_WEEK:
    break;

答案 4 :(得分:5)

DAY_OF_YEAR

获取和设置的字段编号,表示当前年份中的日期编号

DAY_OF_MONTH

获取和设置的字段编号,表示当月的日期。这是DATE的同义词

如果日期大于31,您将看到不同。

答案 5 :(得分:2)

在这两种情况下,你基本上将日期提前一。因此两种方法都没有区别。

但坚持使用单一方法可以在代码库中实现一致性,维护人员会感到宾至如归,并且运行时可能也会通过编译来优化方法调用。

答案 6 :(得分:1)

实际上,根据您选择的字段类型,可能会有所不同:

  

*   http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Calendar.html

     

使用模式。

     

要激发add()和roll()的行为,请考虑a   用户界面组件,带有递增和递减按钮   月,日和年,以及潜在的GregorianCalendar。如果   界面读取1999年1月31日,用户按下月份   增量按钮,它应该读什么?如果底层   实现使用set(),它可能会读到1999年3月3日。更好   结果将是1999年2月28日。此外,如果用户按下   再次按月增加按钮,它应该是1999年3月31日,而不是   1999年3月28日。通过保存原始日期并使用add()或   roll(),取决于是否应该影响更大的字段   用户界面的行为可以像大多数用户一样直观地预期。

答案 7 :(得分:1)

TL;博士

LocalDate.of( 2012 , Month.JANUARY , 31 )
    .plusDays( 1 )
  

2012-02-01

...或...

LocalDate.of( 2012 , 1 , 31 )  // Sane numbering: 1-12 for January-December, and `2012` means year 2012.
    .plusDays( 1 )
  

2012-02-01

java.time

Calendar课程令人困惑,尴尬,设计不佳。其中许多问题包括这些pass-the-units-flag方法。幸运的是,你现在可以忘记这堂课了。

Java 8及更高版本中内置的 java.time 类现在取代了旧的日期时间类。

LocalDate

LocalDate类表示没有时间且没有时区的仅限日期的值。

时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因地区而异。例如,在Paris France午夜后的几分钟是新的一天,而Montréal Québec中仍然是“昨天”。

如果未指定时区,则JVM会隐式应用其当前的默认时区。该默认值可能随时更改,因此您的结果可能会有所不同。最好明确指定您期望/预期的时区作为参数。

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTIST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;

如果要使用JVM的当前默认时区,请求它并作为参数传递。如果省略,则隐式应用JVM的当前默认值。最好是明确的,因为默认情况下可以在运行时期间由JVM中任何应用程序的任何线程中的任何代码随时更改

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

或指定日期。您可以将月份设置为一个数字,1月至12月的数字为1-12。

LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ;  // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.

或者,更好的是,使用预定义的Month枚举对象,一年中的每个月一个。提示:在整个代码库中使用这些Month对象,而不仅仅是整数,以使代码更具自我记录功能,确保有效值,并提供type-safety

LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;

零件

手持LocalDate,您可以询问其部分。

要获取日期,即2018年1月23日的23之类的“日期”:

int dayOfMonth = ld.getDayOfMonth() ; // 1-31, depending on length of month.

要获得一年中的第n天,从1-365,或在闰年,1-366:

int dayOfYear = ld.getDayOfYear() ;

数学

在java.time中添加或减去日期非常简单且直观。便捷方法和时间跨度对象使代码更加清晰。

LocalDate dayLater = ld.plusDays( 1 ) ;

所以明天就会:

LocalDate tomorrow = LocalDate.now( ZoneId.of( "Africa/Tunis" ) ).plusDays( 1 ) ;

或者,您可以表示未附加到时间轴的时间跨度。对于数月 - 天,请使用Period。对于小时 - 分钟 - 秒,请使用Duration

Period p = Period.ofDays( 1 ) ;
LocalDate dayLater = ld.plus( p ) ;

请注意,java.time使用理智编号,与旧版类不同。数字2018是2018年。1月至12月的月数为1-12。根据{{​​3}}标准,星期一至星期日的星期几为1-7。

关于 java.time

ISO 8601框架内置于Java 8及更高版本中。这些类取代了麻烦的旧java.time日期时间类,例如legacyjava.util.Date和& Calendar

现在位于SimpleDateFormatJoda-Time项目建议迁移到maintenance mode类。

要了解详情,请参阅java.time。并搜索Stack Overflow以获取许多示例和解释。规范是Oracle Tutorial

从哪里获取java.time类?

  • JSR 310Java SE 8以及之后
    • 内置。
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9增加了一些小功能和修复。
  • Java SE 9Java SE 6
    • 大部分java.time功能都被反向移植到Java 6& 7 {in Java SE 7
  • ThreeTen-Backport
    • 更新版本的Android捆绑java.time类的实现。
    • 对于早期的Android,Android项目会调整 ThreeTen-Backport (如上所述)。见ThreeTenABP

How to use ThreeTenABP…项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如ThreeTen-ExtraIntervalYearWeekYearQuarter

答案 8 :(得分:0)

除了日期之外,无论您使用DAY_OF_MONTH还是DAY_OF_YEAR,它都没有任何区别。但是,当你获得get getter并传递其中一个时,它是有道理的。

答案 9 :(得分:0)

使用DATE或DAY_OF_MONTH两者相同

区别在于:

DATE or DAY_OF_MONTH : Get and Set indicating the day of the month
DAY_OF_WEEK          : get and set indicating the week number within the current month
DAY_OF_YEAR          : get and set indicating the day number within the current ye

来源:https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html

答案 10 :(得分:0)

   public static String findDay(int month, int day, int year) {
// Creating a calendar
  Calendar calndr = Calendar.getInstance();
     calndr.set(Calendar.MONTH, month-1);
     calndr.set(Calendar.YEAR, year);        
     calndr.set(Calendar.DAY_OF_MONTH, day);
     String[] strDays = new String[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
                "Friday", "Saturday" };
      return strDays[calndr.get(Calendar.DAY_OF_WEEK)-1].toUpperCase();
    }

}