首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >了解java.util.Calendar WEEK_OF_YEAR

了解java.util.Calendar WEEK_OF_YEAR
EN

Stack Overflow用户
提问于 2012-06-05 15:41:12
回答 2查看 28.1K关注 0票数 10

我试图理解java.util.Calendar.get(java.util.Calendar.WEEK_OF_YEAR)是如何工作的,但我似乎遗漏了一些要点。

代码语言:javascript
复制
String time = "1998-12-31"; // year month day
java.util.Calendar date = java.util.Calendar.getInstance();
date.setTime((new java.text.SimpleDateFormat("yyyy-MM-dd")).parse(time));
System.err.println("Week of year = " + date.get(java.util.Calendar.WEEK_OF_YEAR));
// Week of year = 1 Why ???

为什么date.get(java.util.Calendar.WEEK_OF_YEAR)在一年中的最后一周返回1?

此外,"1998-01-01"WEEK_OF_YEAR是1,"1998-12-23"的是52。

有人对这种行为有什么解释吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-06-05 16:02:54

来自java.util.Calendar javadoc

第一周

Calendar使用两个参数定义了特定于地区的一周七天:一周的第一天和第一周的最小天数(从1到7)。这些数字是在构建Calendar时从区域设置资源数据中获取的。也可以通过设置它们的值的方法显式地指定它们。

在设置或获取WEEK_OF_MONTH或WEEK_OF_YEAR字段时,日历必须将月份或年份的第一周确定为参考点。一个月或一年的第一周被定义为从getFirstDayOfWeek()开始的最早的七天时间段,并且至少包含该月或年的getMinimalDaysInFirstWeek()天。编号为...的周,-1,0在第一周之前;编号为2,3,...跟着它走。注意,get()返回的规范化编号可能不同。例如,特定的Calendar子类可以将一年的第一周的前一周指定为前一年的第n周。

所以它是特定于语言环境的。在您的示例中,如果一周中包含新年的日期,则将其计为新年的第一周。

您可以使用Calendar#setMinimalDaysInFirstWeek(int)更改此行为。

票数 12
EN

Stack Overflow用户

发布于 2014-02-07 19:57:25

tl;dr

代码语言:javascript
复制
java.time.LocalDate.parse( "1998-12-31" )
    .get( IsoFields.WEEK_OF_WEEK_BASED_YEAR )

53

或者,添加库,然后添加…

代码语言:javascript
复制
org.threeten.extra.YearWeek.from(     // Convert from a `LocalDate` object to a `YearWeek` object representing the entire week of that date’s week-based year.
    LocalDate.parse( "1998-12-31" )   // Parse string into a `LocalDate` objects. 
).getWeek()                           // Extract an integer number of that week of week-based-year, either 1-52 or 1-53 depending on the year.

53

详细信息

我正在尝试理解java.util.Calendar.get(java.util.Calendar.WEEK_OF_YEAR)是如何工作的

不要!那个类简直是一团糟,最好还是忘了吧。

answer by npe是正确的。在Calendar中,周的定义因区域设置而异。这是一个用心良苦的功能,但令人困惑。

标准周定义

有很多方法来定义“一周”和“一年的第一周”。

然而,还有一个one major standard definitionISO 8601 standard。该标准定义了包括first week of the year在内的weeks of the year

今年第一个星期四的一周

标准的一周从星期一开始,以星期日结束。

以周为基础的标准年的第1周具有日历年的第一个星期四。

java.time

java.time类取代了麻烦的遗留date-time类。这些现代类通过IsoFields类支持ISO8601 week,该类包含实现TemporalField的三个常量

调用LocalDate::get访问TemporalField

代码语言:javascript
复制
LocalDate ld = LocalDate.parse( "1998-12-31" ) ;
int weekOfWeekBasedYear = ld.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR ) ;
int yearOfWeekBasedYear = ld.get( IsoFields.WEEK_BASED_YEAR ) ;

ld.toString():1998-12-31

weekOfWeekBasedYear: 53

yearOfWeekBasedYear: 1998

请注意,新历年1999的第一天也在同一周内,即1998年基于周的第53周。

代码语言:javascript
复制
LocalDate firstOf1999 = ld.plusDays( 1 );
int weekOfWeekBasedYear_FirstOf1999 = firstOf1999.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR ) ;
int yearOfWeekBasedYear_FirstOf1999 = firstOf1999.get( IsoFields.WEEK_BASED_YEAR ) ;

firstOf1999.toString():1999-01-01

weekOfWeekBasedYear_FirstOf1999: 53

yearOfWeekBasedYear_FirstOf1999: 1998

ISO 8601字符串格式

ISO 8601标准定义了一种文本格式以及基于周的年份值的含义:yyyy-Www。对于特定日期,添加编号为1-7的星期1-周日:yyyy-Www-d

构造这样的字符串。

代码语言:javascript
复制
String outputWeek = ld.format( DateTimeFormatter.ISO_WEEK_DATE ) ;  // yyyy-Www 

1998-W53

代码语言:javascript
复制
String outputDate = outputWeek + "-" + ld.getDayOfWeek().getValue() ;  // yyyy-Www-d

1998-W53-4

YearWeek

如果您将库添加到您的项目中,这项工作就会容易得多。然后使用YearWeek类。

代码语言:javascript
复制
YearWeek yw = YearWeek.from( ld ) ;  // Determine ISO 8601 week of a `LocalDate`. 

生成标准字符串。

代码语言:javascript
复制
String output = yw.toString() ;

1998-W53

并进行解析。

代码语言:javascript
复制
YearWeek yearWeek = YearWeek.parse( "1998-W53" ) ;  

yearWeek.toString():1998-W53

确定日期。为星期一到星期日的星期几传递一个java.time.DayOfWeek枚举对象。

代码语言:javascript
复制
LocalDate localDate = yw.atDay( DayOfWeek.MONDAY ) ;

localDate.toString():1998-12-28

我强烈建议将此库添加到您的项目中。然后,您可以传递智能对象,而不是愚蠢的int。这样做可以使您的代码更具自文档性,提供type-safety,并确保有效的值。

关于java.time

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

现在在maintenance mode中的项目建议迁移到java.time类。

要了解更多信息,请参阅。和搜索堆栈溢出,以获得许多示例和解释。规范为JSR 310

使用与JDBC 4.2或更高版本兼容的JDBC driver,您可以直接与数据库交换java.time对象。不需要字符串或java.sql.*类。

从哪里获取java.time类?

  • ,,以及后来内置的
    • 。与implementation.
    • Java 9捆绑在一起的标准Java API的
    • 部分添加了一些次要功能和fixes.

  • 和.

中的

  • 许多java.time功能已向后移植到Java6和7

  • classes.
  • For
    • 更高版本的安卓捆绑实现早期的安卓,项目适应了ThreeTen-Backport (如上所述)。请参阅.

项目使用额外的类扩展了java.time。这个项目是未来可能添加到java.time中的试验场。您可能会在这里找到一些有用的类,如IntervalYearWeekYearQuartermore

Joda-Time

更新: Joda-Time项目现在在maintenance mode中,团队建议迁移到java.time类。这一部分完好无损地保留了历史。

优秀的Joda-Time框架默认使用ISO 8601。它的类包括这周的信息。Joda-Time是与Java捆绑在一起的出了名的麻烦的java.util.Date & java.util.Calendar类的流行替代品。

示例代码

下面是一些示例代码,用于获取当前日期-时间的一年中第一周的第一天的第一个时刻。

注意调用withTimeAtStartOfDay来获取一天中的第一个时刻。

代码语言:javascript
复制
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );

DateTime now = new DateTime( timeZone );
DateTime firstWeekStart = now.withWeekOfWeekyear(1).withDayOfWeek(1).withTimeAtStartOfDay();
DateTime firstWeekStop = firstWeekStart.plusWeeks( 1 );
Interval firstWeek = new Interval( firstWeekStart, firstWeekStop );

转储到控制台…

代码语言:javascript
复制
System.out.println( "now: " + now );
System.out.println( "firstWeekStart: " + firstWeekStart );
System.out.println( "firstWeekStop: " + firstWeekStop );
System.out.println( "firstWeek: " + firstWeek );

运行…时

代码语言:javascript
复制
now: 2014-02-07T12:49:33.623+01:00
firstWeekStart: 2013-12-30T00:00:00.000+01:00
firstWeekStop: 2014-01-06T00:00:00.000+01:00
firstWeek: 2013-12-30T00:00:00.000+01:00/2014-01-06T00:00:00.000+01:00
票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10893443

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档