【问题标题】:Java Calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY), will it roll backwards, forwards or unknown?Java Calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY),它会向后滚动,向前滚动还是未知?
【发布时间】:2017-03-27 16:03:05
【问题描述】:

假设以下代码在 2009 年 8 月 22 日(星期六)执行

   Calendar c = Calendar.getInstance();
   c.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);

c.get(Calendar.DAY_OF_MONTH) 将返回 23。我感兴趣的条件是返回 14(上周日,而不是下周日)。

当设置DAY_OF_WEEK 时,是否有任何与日历滚动DAY_OF_MONTH/YEAR 的方向相关的规则?如果有,它们是什么?

【问题讨论】:

  • 对于 2014 年以后提出这个问题的读者,我建议你不要使用Calendar。该课程设计不良且早已过时。对于公历,请使用 LocalDateWeekFields,两者都来自 java.time, the modern Java date and time API

标签: java calendar


【解决方案1】:

它应该始终保持相同的WEEK_OF_MONTH (http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html#WEEK_OF_MONTH)。来自文档:

当设置或获取 WEEK_OF_MONTH 或 WEEK_OF_YEAR 字段, 日历必须确定第一周 作为参考的月份或年份 观点。一个月的第一周或 年份被定义为最早的七个 日期间开始于 getFirstDayOfWeek() 并包含在 最少 getMinimalDaysInFirstWeek() 天 那个月或那个年。周数 ..., -1, 0 在第一周之前; 第 2 周、第 3 周、... 跟随它。 请注意,标准化编号 get() 返回的可能不同。 例如,特定的日历 子类可以指定前一周 一年的第 1 周作为第 n 周 上一年。

【讨论】:

  • 我们在这里谈论的是DAY_OF_WEEK,我看不出你的答案是如何相关的。
  • 问题是“当设置DAY_OF_WEEK 时,是否有任何与日历滚动DAY_OF_MONTH 的方向相关的规则。”答案是:“无论哪个方向,WEEK_OF_MONTH 都会保持不变。”
【解决方案2】:

以下公式返回 [0;6] 范围内一周中的“当前”天

(d + numberOfDaysInAWeek - firstDayOfWeek) % numberOfDaysInAWeek

如果您想要范围 [1;7],则添加 1

(d + numberOfDaysInAWeek - firstDayOfWeek) % numberOfDaysInAWeek + 1

dCalendar.get(Calendar.DAY_OF_WEEK) 返回的内容

要获得一周的第一天,请从当前日期减去公式的结果。下面的代码做到了:

final int currentDayOfWeek = (calendar.get(Calendar.DAY_OF_WEEK) + 7 - cal.getFirstDayOfWeek()) % 7;
cal.add(Calendar.DAY_OF_YEAR, -currentDayOfWeek);

【讨论】:

    【解决方案3】:

    使用 java.time

    现代方法是使用 java.time 类来代替麻烦的旧旧日期时间类。

    java.time 类更容易使用。特别是,它们消除了问题中提出的歧义。您可以明确要求较早星期日或较晚星期日。

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

    Month 枚举提供了十几个预定义对象,一年中的每个月一个。这些枚举对象使用起来更安全,但您可以改为使用纯数字来表示月份。与传统课程不同,这些月份的编号很合理,1 月至 12 月为 1-12。

    LocalDate localDate = LocalDate.of( 2009 , Month.AUGUST, 22 );
    

    TemporalAdjuster 接口提供日期时间值的操作。 TemporalAdjusters 类(注意复数 s)提供了几个方便的实现。

    previousnext 调整器不考虑日期本身。 previousOrSamenextOrSame 方法返回有问题的日期,如果它确实是所需的星期几。

    DayOfWeek 枚举提供了七个预定义对象,一个用于一周中的每一天。

    LocalDate previousSunday = localDate.with( TemporalAdjusters.previous ( DayOfWeek.SUNDAY ));
    LocalDate previousOrSameSunday = localDate.with( TemporalAdjusters.previousOrSame ( DayOfWeek.SUNDAY ));
    
    LocalDate nextSunday = localDate.with( TemporalAdjusters.next ( DayOfWeek.SUNDAY ));
    LocalDate nextOrSameSunday = localDate.with( TemporalAdjusters.nextOrSame ( DayOfWeek.SUNDAY ));
    

    转储到控制台。

    System.out.println ("localDate: " + localDate + " ( " + localDate.getDayOfWeek ().getDisplayName ( TextStyle.FULL, Locale.US )  + " )");
    System.out.println ("previousSunday: " + previousSunday );
    System.out.println ("nextSunday: " + nextSunday );
    

    本地日期:2009-08-22(星期六)

    上一个星期日:2009-08-16

    下周日:2009-08-23


    关于java.time

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

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

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

    从哪里获得 java.time 类?

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

    【讨论】:

    • 非常详细,正是我需要的。谢谢!
    【解决方案4】:

    实际上,这取决于。考虑以下 Java 代码。它实际上很简单,我希望它打印 2011-09-18 之前的星期一,即 2011-09-12:

    Calendar calendar = Calendar.getInstance(Locale.GERMANY);
    System.out.printf("First day of week: %d%n%n", calendar.getFirstDayOfWeek());
    
    calendar.set(2011, Calendar.SEPTEMBER, 18);
    System.out.printf("Starting day: %tF%n", calendar);
    calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
    System.out.printf("Last monday: %tF%n%n", calendar);
    
    calendar.set(2011, Calendar.SEPTEMBER, 18);
    System.out.printf("Starting day: %tF (week %d)%n",
            calendar, calendar.get(Calendar.WEEK_OF_YEAR));
    calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
    System.out.printf("Last monday: %tF (week %d)%n", calendar,
            calendar.get(Calendar.WEEK_OF_YEAR));
    

    但实际上结果有点不同:

    First day of week: 2
    
    Starting day: 2011-09-18
    Last monday: 2011-09-19
    
    Starting day: 2011-09-18 (week 37)
    Last monday: 2011-09-12 (week 37)
    

    换句话说,结果取决于我的日历是否知道我可能对这一周感兴趣。如果我查询WEEK_OF_YEAR,结果实际上会改变!

    【讨论】:

      【解决方案5】:

      来自Javadoc

      如果日历字段值有任何冲突,日历会优先考虑最近设置的日历字段。以下是日历字段的默认组合。将使用由最近设置的单个字段确定的最近组合。

      对于日期字段:

       YEAR + MONTH + DAY_OF_MONTH
       YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK
       YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
       YEAR + DAY_OF_YEAR
       YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
       
      

      我将其解释为,鉴于您正在设置星期几,它最终将与月份中的星期或一年中的星期相结合,以生成实际的日期和时间。

      【讨论】:

        【解决方案6】:

        您还应该检查一周的第一天是哪一天。 我还认为它总是星期天,但这取决于当地的环境,就我而言 星期一是一周的第一天。将星期日设置为一周的第一天解决了我的问题。

        【讨论】:

          【解决方案7】:

          取决于一周的第一天:

           /**
           * Gets what the first day of the week is; e.g., <code>SUNDAY</code> in the U.S.,
           * <code>MONDAY</code> in France.
           *
           * @return the first day of the week.
           * @see #setFirstDayOfWeek(int)
           * @see #getMinimalDaysInFirstWeek()
           */
          public int getFirstDayOfWeek()
          {
              return firstDayOfWeek;
          }
          

          【讨论】:

            【解决方案8】:

            你可以像这个方法一样使用。

            public Integer whichDayOfWeek(Calendar calendar) {
                        if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
                            return 1;
                        } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.TUESDAY) {
                            return 2;
                        } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.WEDNESDAY) {
                            return 3;
                        } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.THURSDAY) {
                            return 4;
                        } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) {
                            return 5;
                        } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
                            return 6;
                        } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
                            return 7;
                        } else {
                            return null;
                        }
                    }
            

            【讨论】:

            • 这根本没有解决发帖者的问题
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-06-30
            • 2017-09-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-02-02
            相关资源
            最近更新 更多