tl;博士
- 您似乎将每月第一天与每周第一天混为一谈。
-
2 是一个硬编码常量,代表星期一。
- 显然,您当前的默认语言环境认为星期一是一周的第一天。
- 请改用 java.time。
一周的第一天:
LocalDate.now( ZoneId.of( "America/Montreal" ) )
.with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) )
每月的第一天:
LocalDate.now( ZoneId.of( "Pacific/Auckland" ) )
.with( ChronoField.DAY_OF_MONTH , 1L )
详情
getFirstDayOfWeek() 获取每个月的第一天
您似乎将周初与月初混淆了。
当然,每月的第一天总是1。
一周的第一天是一周中的某一天,例如周日或周一等。Calendar 类中一周第一天的定义因Locale 而异。例如,在北美大部分地区,第一天通常是星期日。在欧洲大部分地区,一周的第一天是星期一。
如果您未能指定 Locale,Calendar 类将隐式应用 JVM 的当前默认语言环境。显然,在您的默认语言环境中,一周的第一天是星期一。我推断这是因为您报告了号码2。如果你探索int 常量Calendar.MONDAY,你会发现it is indeed a primitive int of value 2。
避免使用旧的日期时间类
Calendar 类有许多糟糕的设计决策。我认为这种对星期几的不同定义就是其中之一。避免使用这些麻烦的旧日期时间类(例如 Calendar 和 Date)的众多原因之一。这些类现在是遗留的,被 java.time 类所取代。
使用 java.time
LocalDate 类表示没有时间和时区的仅日期值。
时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因区域而异。例如,Paris France 中午夜过后几分钟是新的一天,而 Montréal Québec 中仍然是“昨天”。
以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 );
要获得一周的第一天,(a) 决定一周的第一天是哪一天,(b) 使用在 TemporalAdjusters 中定义的 TemporalAdjuster 实现来获取特定 @987654332 的日期@枚举对象。
DayOfWeek firstDow = DayOfWeek.MONDAY ;
LocalDate ld = today.with( TemporalAdjusters.previousOrSame( firstDow ) ) ;
要获取一个月中某一天的LocalDate,请调用with 方法并从ChronoField.DAY_OF_MONTH 传递一个枚举对象。
LocalDate firstOfMonth = today.with( ChronoField.DAY_OF_MONTH , 1L ) ;
关于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 类?