我正在测试我们的日期管理框架的一部分,该框架应该重置一些日历字段(使用实际的最小值)。
但是,当更改一周的第一天时,日历总是返回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.Date
、Calendar
和&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 8、Java SE 9和Java SE 10,爪哇SE 11及更高版本-标准Java API的一部分,具有捆绑实现。
- Java 9带来了一些小功能和修复
- Java SE 6和Java SE 7
- java.time的大部分功能都是后移植到Java6&7英寸ThreeTen背包
- 安卓
- 稍后版本的Android(26+)捆绑java.time类的实现
- 对于早期的Android(<26),一个名为neneneba API desugaring的过程带来了java.time功能的子集,该功能最初不是内置于Android中的。
- 如果降级不能满足您的需求,ThreeTenABP项目会将ThreeTen Backport(如上所述)适配到Android。请参阅如何使用ThreeTenABP…