繁体   English   中英

将 DAY_OF_MONTH 或 DAY_OF_YEAR 添加到 Calendar 对象有什么区别?

[英]What's the difference between adding DAY_OF_MONTH or DAY_OF_YEAR to a Calendar object?

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

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);

要么

cal.add(Calendar.DAY_OF_YEAR, 1);

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

添加它确实没有区别,但这

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

印刷

28
363

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

在这里,您可以添加或减去日历字段列表:

  • MILLISECOND是 0 到 999 之间的毫秒数

  • SECOND是 0 到 59 之间的秒数

  • MINUTE是 0 到 59 之间的分钟数

  • HOUR是 0 到 11 之间的小时数

  • HOUR_OF_DAY是 0 到 23 之间的小时数

  • DAY_OF_WEEK是与 1 和 7 之间的周相关的天

  • DAY_OF_MONTH是与 1 到 31 之间的月份相关的日期

  • DAY_OF_YEAR是与 1 到 365 之间的年份相关的日期

  • WEEK_OF_MONTH是从 1 开始的与月份相关的周

  • WEEK_OF_YEAR是从 1 开始的与年份相关的周

  • MONTH是与 0 到 11 之间的年份相关的月份

  • YEAR是从 1 开始的年数

小时、天和周有多个字段,但您选择哪一个并不重要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 years

1使用Calendar.add没有关系,其他操作结果可能不同。

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

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

来自GregorianCalendar#add代码片段

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

get 和 set 的字段编号表示当前年份中的天数

DAY_OF_MONTH

get 和 set 的字段编号,指示月份中的某一天 这是 DATE 的同义词

如果一天大于 31,您将看到差异。

在这两种情况下,您基本上都将日期提前了一个。 所以这两种方法没有区别。

但是坚持使用单一方法将使您的代码库保持一致,维护人员会感到宾至如归,并且运行时可能也会通过编译来优化方法调用。

实际上,根据您选择的字段类型,可能会有差异:

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

使用模型。

为了激发 add() 和 roll() 的行为,考虑一个带有月、日和年递增和递减按钮的用户界面组件,以及一个底层的 GregorianCalendar。 如果界面显示 1999 年 1 月 31 日,用户按下月份递增按钮,它应该显示什么? 如果底层实现使用 set(),它可能会显示 1999 年 3 月 3 日。更好的结果是 1999 年 2 月 28 日。此外,如果用户再次按下月份增量按钮,它应该显示 1999 年 3 月 31 日,而不是 3 月 28 日, 1999。通过保存原始日期并使用 add() 或 roll(),根据是否应该影响较大的字段,用户界面可以像大多数用户直观地期望的那样运行。

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

时间

Calendar类令人困惑、笨拙且设计不佳。 其众多问题之一是这些传递单位标志方法。 幸运的是,您现在可以忘记这个类的所有内容。

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

LocalDate

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

时区对于确定日期至关重要。 对于任何给定时刻,日期因地区而异。 例如,在法国巴黎午夜过后几分钟是新的一天,而在魁北克蒙特利尔仍然是“昨天”。

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

continent/region的格式指定正确的时区名称,例如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对象而不仅仅是整数,以使您的代码更具自文档性、确保有效值并提供类型安全

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

部分

有了LocalDate ,您就可以查询其部分。

要获取月份中的日期,即从 2018 年 1 月 23 23开始的“日期”,例如23

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

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

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 使用合理的编号 数字20182018年。 1-12 月的月份编号为 1-12。 根据ISO 8601标准,星期一至星期日的星期几编号为 1-7。


关于java.time

java.time框架内置于 Java 8 及更高版本中。 这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar ,和SimpleDateFormat

现在处于维护模式Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle 教程 并在 Stack Overflow 上搜索许多示例和解释。 规范是JSR 310

从哪里获得 java.time 类?

ThreeTen-Extra项目用额外的类扩展了 java.time。 该项目是未来可能添加到 java.time 的试验场。 您可以在这里找到一些有用的类,比如IntervalYearWeekYearQuarter ,和更多

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

使用 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

   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();
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM