Java日历-一周中的第一天与实际最小值



我正在测试我们的日期管理框架的一部分,该框架应该重置一些日历字段(使用实际的最小值)。

但是,当更改一周的第一天时,日历总是返回SUNDAY(1)作为一周中某一天的实际最小值。是虫子吗?

MVCE:

import java.util.*;
public class Main {
  public static void main(String[] args) {
    System.out.printf("Java specification: %s%n", System.getProperty("java.vm.specification.version"));
    System.out.printf("Java version: %s%n", System.getProperty("java.specification.version"));
    System.out.printf("VM version: %s%n", System.getProperty("java.vm.version"));
    Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
    int[] days = { 1, 5, 7 };
    for (int day : days) {
      cal.setTimeInMillis(0L);
      cal.setFirstDayOfWeek(day);
      System.out.printf("expected: %d, actual: %d%n", day, cal.getActualMinimum(Calendar.DAY_OF_WEEK));
    }
  }
}

您应该使用的cal.getFirstDayOfWeek()instandcal.getActualMinimum(日历.DAY_OF_WEEK)

因为cal.getActualMinimum(Calendar.DAY_OF_WAEK)将始终返回sunday查看java源代码中getActualMinium(Calendar.DAY_OF_WEEK)的实现

  public int getActualMinimum(int field) {
        if (field == DAY_OF_MONTH) {
            GregorianCalendar gc = getNormalizedCalendar();
            int year = gc.cdate.getNormalizedYear();
            if (year == gregorianCutoverYear || year == gregorianCutoverYearJulian) {
                long month1 = getFixedDateMonth1(gc.cdate, gc.calsys.getFixedDate(gc.cdate));
                BaseCalendar.Date d = getCalendarDate(month1);
                return d.getDayOfMonth();
            }
        }
        return getMinimum(field);
    }

而getMinimum是:-

   public int getMinimum(int field) {
        return MIN_VALUES[field];
    }

MIN_VALUES数组定义为:-

 static final int MIN_VALUES[] = {
        BCE,            // ERA
        1,              // YEAR
        JANUARY,        // MONTH
        1,              // WEEK_OF_YEAR
        0,              // WEEK_OF_MONTH
        1,              // DAY_OF_MONTH
        1,              // DAY_OF_YEAR
        SUNDAY,         // DAY_OF_WEEK
        1,              // DAY_OF_WEEK_IN_MONTH
        AM,             // AM_PM
        0,              // HOUR
        0,              // HOUR_OF_DAY
        0,              // MINUTE
        0,              // SECOND
        0,              // MILLISECOND
        -13*ONE_HOUR,   // ZONE_OFFSET (UNIX compatibility)
        0               // DST_OFFSET
    };

K M PATEL的回答是正确的。

问题和答案都使用了过时的类。与最早版本的Java捆绑在一起的旧日期时间类已被Java.time类所取代。

标准定义

DayOfWeek枚举根据ISO 8601标准定义一周,星期一为1,星期日为7。

您可以向DayOfWeek对象询问此1-7编号。

int dayOfWeekNumber = DayOfWeek.WEDNESDAY.getValue();

但是不要在代码中传递这个数字。相反,绕过DayOfWeek对象以享受类型安全性和有保证的有效值的好处。

本地化定义

有关"星期几"、"月周"one_answers"年周"字段的本地化定义,请使用WeekFields类。

WeekFields weekFields_US = WeekFields.of ( Locale.US );
DayOfWeek firstDayOfWeek = weekFields_US.getFirstDayOfWeek ();

转储到控制台。

System.out.println ( "weekFields_US: " + weekFields_US + " | firstDayOfWeek: " + firstDayOfWeek );

weekFields_US:weekFields[SUNDAY,1]|周的第一天:SUNDAY

定义自己的周变化

我建议坚持指定Locale对象来定义一周。但如果你坚持,你可以定义自己一周的变化。调用WeekFields.of并指定(a)一周中的第一天,以及(b)定义一年中第一周或一个月中第一周的最小天数。

首先,为了进行比较,使用IsoFields类中包含的标准ISO 8601定义来获得星期几编号。

// Using standard IsoFields.
LocalDate localDate = LocalDate.of ( 2016 , 2 , 3 ); // Feb 3 2016 = Wednesday
DayOfWeek dow = DayOfWeek.from ( localDate );
int ordinalNumberDayOfWeek = dow.getValue ();

转储到控制台。

System.out.println ( "localDate: " + localDate + " | dow: " + dow + " | ordinalNumberDayOfWeek: " + ordinalNumberDayOfWeek );

本地日期:2016年2月3日|星期三|序号一周中的日期:3

现在切换到定义我们自己的WeekFields对象,并再次询问星期几的编号。上面我们看到了3,因为2016年2月3日是星期三,所以星期一-星期二-星期三是三。下面我们看到的是4,因为星期日、星期一、星期二、星期三。

// Define our own WeekFields to use in place of IsoFields.
WeekFields weekFields_SUNDAY_1 = WeekFields.of ( DayOfWeek.SUNDAY , 1 );
int ordinalNumberDayOfWeek_SundayBasedWeek = localDate.get ( weekFields_SUNDAY_1.dayOfWeek () );

转储到控制台。

System.out.println ( "ordinalNumberDayOfWeek_SundayBasedWeek: " + ordinalNumberDayOfWeek_SundayBasedWeek );

一周中的普通数字星期k_SundayBasedWeek:4

(示例基于JodaStephen的回答)


请参阅类似的问题,java为给定的日期获取一年中的一周。


关于java.time

java.time框架构建在Java8及更高版本中。这些类取代了诸如java.util.DateCalendar和&SimpleDateFormat

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

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

您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,也不需要java.sql.*类。休眠5&JPA 2.2支持java.time.

从哪里获得java.time类?

  • Java SE 8Java SE 9Java SE 10爪哇SE 11及更高版本-标准Java API的一部分,具有捆绑实现。
    • Java 9带来了一些小功能和修复
  • Java SE 6Java SE 7
    • java.time的大部分功能都是后移植到Java6&7英寸ThreeTen背包
  • 安卓
    • 稍后版本的Android(26+)捆绑java.time类的实现
    • 对于早期的Android(<26),一个名为neneneba API desugaring的过程带来了java.time功能的子集,该功能最初不是内置于Android中的。
      • 如果降级不能满足您的需求,ThreeTenABP项目会将ThreeTen Backport(如上所述)适配到Android。请参阅如何使用ThreeTenABP…

相关内容

最新更新