【问题标题】:What's the difference between adding DAY_OF_MONTH or DAY_OF_YEAR to a Calendar object?将 DAY_OF_MONTH 或 DAY_OF_YEAR 添加到 Calendar 对象有什么区别?
【发布时间】:2012-12-28 05:51:36
【问题描述】:

我想将某个日期增加 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”常量,但是我使用上述两种将天加1的方法得到了相同的结果。在这种情况下,我会得到两个不同的结果吗?

【问题讨论】:

  • 查看更活跃的帖子并获得投票赞成的答案:stackoverflow.com/questions/428918/…
  • 如参数提示的那样 cal.add(Calendar.DAY_OF_MONTH, 2); 表示将 DAY_OF_MONTH 的单位添加到日历中的日期...

标签: java datetime


【解决方案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

【讨论】:

    【解决方案2】:

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

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

    • 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 到 366 之间的年份相关的日期

    • 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,其他操作结果可能不同。

    【讨论】:

      【解决方案3】:
      DAY_OF_YEAR
      

      get 和 set 的字段编号,表示当年的日期

      DAY_OF_MONTH
      

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          【解决方案5】:

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

          来自GregorianCalendar#add的代码sn-p

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

          【讨论】:

            【解决方案6】:

            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 类令人困惑、笨拙且设计不佳。在它的许多问题中,这些传递单元标志的方法。幸运的是,你现在可以忘记这门课了。

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

            LocalDate

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

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

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

            以continent/region 的格式指定proper time zone name,例如America/Montreal、Africa/Casablanca 或Pacific/Auckland。切勿使用 3-4 个字母的缩写,例如 EST 或 IST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。

            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 使用 sane 编号,这与旧类不同。数字 2018 是 2018 年。1 月至 12 月的月份编号为 1-12。根据ISO 8601 标准,周一至周日将一周中的天数编号为 1-7。


            关于java.time

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

            Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

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

            从哪里获得 java.time 类?

            ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。

            【讨论】:

              【解决方案7】:

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

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

              【讨论】:

                【解决方案8】:

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

                * 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 日,而不是 1999 年 3 月 28 日。通过保存原始日期并使用 add() 或 roll(),取决于是否应该影响更大的字段, 用户界面的行为与大多数用户的直觉预期一致。

                【讨论】:

                  【解决方案9】:

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

                  【讨论】:

                    【解决方案10】:

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

                    【讨论】:

                      【解决方案11】:
                         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();
                          }
                      

                      }

                      【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2012-01-04
                      • 2021-01-16
                      • 2011-09-23
                      • 2013-06-26
                      • 2011-07-31
                      • 1970-01-01
                      相关资源
                      最近更新 更多