java 为什么 2010 年 12 月 31 日返回 1 作为一年中的一周?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4608470/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why dec 31 2010 returns 1 as week of year?
提问by OscarRyz
For instance:
例如:
Calendar c = Calendar.getInstance();
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
c.setTime( sdf.parse("31/12/2010"));
out.println( c.get( Calendar.WEEK_OF_YEAR ) );
Prints 1
打印 1
Same happens with Joda time.
Joda时间也是如此。
:)
:)
回答by Ralph
The definition of Week of Year is Locale
dependent.
一年中的一周的定义是Locale
相关的。
How it is defined in US is discused in the other posts. For example in Germany (DIN 1355-1/ ISO 8601): the first Week* of Year is the first week with 4 or more days in the new year.
在其他帖子中讨论了它在美国的定义。例如在德国 ( DIN 1355-1/ ISO 8601):一年中的第一周*是新年有 4 天或更多天的第一周。
*first day of week is Monday and last day of week is Sunday
*一周的第一天是星期一,一周的最后一天是星期日
And Java's Calendar
pays attention to the locale. For example:
而 Java 则Calendar
注重语言环境。例如:
public static void main(String[] args) throws ParseException {
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date lastDec2010 = sdf.parse("31/12/2010");
Calendar calUs = Calendar.getInstance(Locale.US);
calUs.setTime(lastDec2010);
Calendar calDe = Calendar.getInstance(Locale.GERMAN);
calDe.setTime(lastDec2010);
System.out.println( "us: " + calUs.get( Calendar.WEEK_OF_YEAR ) );
System.out.println( "de: " + calDe.get( Calendar.WEEK_OF_YEAR ) );
}
prints:
印刷:
us: 1
de: 52
ADDEDFor the US (and I can think of that it is the same for Mexico) the 1. Week of Year is the week where the 1. January belongs to. -- So if 1. Januar is a Saturday, then the Friday before (31. Dec) belongs the same week, and in this case this day belongs to the 1. Week of Year 2011.
添加对于美国(我可以认为它对墨西哥也是如此)1. 一年中的一周是 1. 一月所属的那一周。-- 因此,如果 1. Januar 是星期六,则之前的星期五(12 月 31 日)属于同一周,在这种情况下,这一天属于 2011 年的 1. 周。
回答by Adam
Values calculated for the WEEK_OF_YEAR field range from 1 to 53. Week 1 for a year is the earliest seven day period starting on getFirstDayOfWeek() that contains at least getMinimalDaysInFirstWeek() days from that year. It thus depends on the values of getMinimalDaysInFirstWeek(), getFirstDayOfWeek(), and the day of the week of January 1. Weeks between week 1 of one year and week 1 of the following year are numbered sequentially from 2 to 52 or 53 (as needed).
为 WEEK_OF_YEAR 字段计算的值范围从 1 到 53。一年的第 1 周是从 getFirstDayOfWeek() 开始的最早的 7 天时间段,其中至少包含该年的 getMinimalDaysInFirstWeek() 天数。因此,它取决于 getMinimalDaysInFirstWeek()、getFirstDayOfWeek() 的值和 1 月 1 日的星期几。一年的第 1 周和下一年的第 1 周之间的周从 2 到 52 或 53 依次编号(如需要)。
To determine if that week is the last week of 2010 or the first of 2011 Java uses getMinimalDaysInFirstWeek
javadoc. If that method returns 7 then the first week in which all the days in the week are of the same year is week one, if it returns 1 then the first week with any days of the next year is the first week of the next year.
为了确定那一周是 2010 年的最后一周还是 2011 年的第一周,Java 使用getMinimalDaysInFirstWeek
javadoc。如果该方法返回 7,那么一周中所有天数都属于同一年的第一周是第一周,如果它返回 1,那么下一年有任何天数的第一周是下一年的第一周。
In this case the first of January in 2011 is on a Saturday so it is considered the first week of 2011 as long as you would like a week with one day to be considered already the first week of the next year, if you don't then do:
在这种情况下,2011 年 1 月的第一天是星期六,所以它被认为是 2011 年的第一周,只要您希望有一天的一周已经被视为明年的第一周,如果您不这样做然后做:
Calendar c = Calendar.getInstance();
c.setMinimalDaysInFirstWeek(7);//anything more than 1 will work in this year
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
c.setTime( sdf.parse("31/12/2010"));
System.out.println( c.get( Calendar.WEEK_OF_YEAR ) );
returns:
返回:
52
回答by KevinDTimm
IIRC, The first week with a date of Jan 1 is week 1.
That's why week 1 is returned for 12/31/2010.
Try it for 12/31/2011 and you'll get 52.
Edit: Week is locale specific, sometimes defined as Sunday - Saturday, sometimes defined as Monday - Sunday
IIRC,日期为 1 月 1 日的第一周是第 1 周。
这就是返回 12/31/2010 的第 1周的原因。 2011 年
12 月 31 日试试,你会得到 52。
编辑:周是特定于语言环境的,有时定义为星期日 - 星期六,有时定义为星期一 - 星期日
回答by Basil Bourque
tl;dr
tl;博士
java.time.LocalDate.parse(
"31/12/2010" ,
DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( Locale.UK )
)
.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR )
52
52
Or, add a library, and then…
或者,添加一个库,然后……
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.
java.time.LocalDate.parse( "31/12/2010" , DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( Locale.UK )
).getWeek() // Extract an integer number of that week of week-based-year, either 1-52 or 1-53 depending on the year.
52
52
java.time
时间
As others noted, the definition of a week varies by Locale
in the old java.util.Calendar
class.
正如其他人指出的那样,一周的定义因Locale
旧java.util.Calendar
班级而异。
That troublesome class, and its partner java.util.Date
, have been supplanted by the java.timeframework built into Java 8 and later.
这个麻烦的类和它的伙伴java.util.Date
,已经被内置在 Java 8 和更高版本中的java.time框架所取代。
The IsoFields
class defines a week using the ISO 8601standard: Week always starts on a Monday, and week # 1 holds the first Thursday of the calendar-year.
在IsoFields
类定义了使用一个星期ISO 8601标准:周总是开始于一个星期一,每周1号持有的日历年度的第一个星期四。
Get the current moment.
获取当前时刻。
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
Ask about the standard week-based year.
询问标准的基于周的年份。
int week = now.get ( IsoFields.WEEK_OF_WEEK_BASED_YEAR );
int weekYear = now.get ( IsoFields.WEEK_BASED_YEAR );
Standard week definition
标准周定义
There are many ways to define “a week” and “first week of the year”.
有很多方法可以定义“一周”和“一年中的第一周”。
However, there is one major standard definition: the ISO 8601 standard. That standard defines weeks of the year, including the first week of the year.
但是,有一个主要的标准定义:ISO 8601 标准。该标准定义了一年中的几周,包括一年中的第一周。
the week with the year's first Thursday
一年中第一个星期四的那一周
A standard weeks begins with Monday and ends with Sunday.
标准周从星期一开始,到星期日结束。
Week # 1 of a week-based year has the first Thursday of the calendar year.
基于周的年的第 1 周是日历年的第一个星期四。
The java.timeclasses support the ISO 8601 week through the IsoFields
class, holding three constants that implement TemporalField
:
该java.time类支持ISO 8601周至第的IsoFields
类,认为实施三个常量TemporalField
:
Call LocalDate::get
to access the TemporalField
.
调用LocalDate::get
以访问TemporalField
.
LocalDate ld = LocalDate.parse( "2010-12-31" ) ;
int weekOfWeekBasedYear = ld.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR ) ;
int yearOfWeekBasedYear = ld.get( IsoFields.WEEK_BASED_YEAR ) ;
ld.toString(): 2010-12-31
weekOfWeekBasedYear: 52
yearOfWeekBasedYear: 2010
ld.toString(): 2010-12-31
weekOfWeekBasedYear: 52
yearOfWeekBasedYear: 2010
ISO 8601 string format
ISO 8601 字符串格式
The ISO 8601 standard defines a textual format as well as a meaning for week-based-year values: yyyy-Www
. For a specific date, add day-of-week numbered 1-7 for Monday-Sunday: yyyy-Www-d
.
ISO 8601 标准定义了文本格式以及基于周的年值的含义:yyyy-Www
. 对于特定日期,为星期一至星期日添加编号为 1-7 的星期几:yyyy-Www-d
。
Construct such a string.
构造这样一个字符串。
String outputWeek = String.format( "%04d" , yearOfWeekBasedYear ) + "-W" + String.format( "%02d" , weekOfWeekBasedYear ) ;
String outputDate = outputWeek + "-" + ld.getDayOfWeek().getValue() ;
2010-W52-5
2010-W52-5
YearWeek
YearWeek
This work is much easier if you add the ThreeTen-Extralibrary to your project. Then use the YearWeek
class.
如果将ThreeTen-Extra库添加到项目中,这项工作会容易得多。然后使用YearWeek
类。
YearWeek yw = YearWeek.from( ld ) ; // Determine ISO 8601 week of a `LocalDate`.
Generate the standard string.
生成标准字符串。
String output = yw.toString() ;
2010-W52
2010-W52
And parse.
并解析。
YearWeek yearWeek = YearWeek.parse( "2010-W52" ) ;
yearWeek.toString(): 2010-W52
yearWeek.toString(): 2010-W52
Determine a date. Pass a java.time.DayOfWeek
enum object for day-of-week Monday-Sunday.
确定日期。传递java.time.DayOfWeek
星期一至星期日的枚举对象。
LocalDate localDate = yw.atDay( DayOfWeek.MONDAY ) ;
localDate.toString(): 2010-12-27
localDate.toString(): 2010-12-27
I strongly recommending adding this library to your project. Then you can pass around smart objects rather than dumb ints. Doing so makes your code more self-documenting, provides type-safety, and ensures valid values.
我强烈建议将此库添加到您的项目中。然后你可以传递智能对象而不是愚蠢的整数。这样做会使您的代码更加自文档化,提供类型安全,并确保有效值。
About java.time
关于java.time
The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
该java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date
, Calendar
, & SimpleDateFormat
。
The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310。
Using a JDBC drivercompliant with JDBC 4.2or later, you may exchange java.timeobjects directly with your database. No need for strings nor java.sql.* classes.
使用符合JDBC 4.2或更高版本的JDBC 驱动程序,您可以直接与您的数据库交换java.time对象。不需要字符串或 java.sql.* 类。
Where to obtain the java.time classes?
从哪里获得 java.time 类?
- Java SE 8, Java SE 9, and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6and Java SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.time classes.
- For earlier Android, the ThreeTenABPproject adapts ThreeTen-Backport(mentioned above). See How to use ThreeTenABP….
- Java SE 8、Java SE 9及更高版本
- 内置。
- 具有捆绑实现的标准 Java API 的一部分。
- Java 9 添加了一些小功能和修复。
- Java SE 6和Java SE 7
- 多的java.time功能后移植到Java 6和7在ThreeTen-反向移植。
- 安卓
- 更高版本的 Android 捆绑实现 java.time 类。
- 对于早期的 Android,ThreeTenABP项目采用了ThreeTen-Backport(上面提到过)。请参阅如何使用ThreeTenABP ...。
The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
该ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如Interval
,YearWeek
,YearQuarter
,和更多。
For much more detail, see my Answeron the similar Question:
…and see my Answeron the similar Question:
回答by Basil Bourque
This is because the start of the week is local dependent.
这是因为一周的开始取决于本地。
In the US the Week 1 starts on the Sunday before Jan 1. In 2010 this is Dec 26. That's why Dec 31 is still week 1.
在美国,第 1 周从 1 月 1 日之前的星期日开始。在 2010 年,这是 12 月 26 日。这就是为什么 12 月 31 日仍然是第 1 周。
In Europe the week 1 starts on the Monday before Jan 1. In 2010 this is Dec 27. That's why also in Europe Dec 31 is still week 1.
在欧洲,第 1 周从 1 月 1 日之前的星期一开始。在 2010 年,这是 12 月 27 日。这就是为什么在欧洲,12 月 31 日仍然是第 1 周。
回答by Tanny
I feel this is a better approach.
我觉得这是一个更好的方法。
Calendar c = Calendar.getInstance();
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
c.setTime( sdf.parse("31/12/2010"));
int thisWeek = c.get(Calendar.WEEK_OF_YEAR);
if (c.get(Calendar.MONTH) == Calendar.DECEMBER && thisWeek == 1)
thisWeek = 53;
System.out.println(thisWeek);
The main assumption here is, for the month of December, the week cannot be 1, hence just returning 53.
这里的主要假设是,对于 12 月份,周不能为 1,因此只返回 53。
Please suggest, if I am wrong somewhere, and why this is not implemented in the Calendar of Java.
如果我在某处错了,请提出建议,以及为什么在 Java 日历中没有实现这一点。