简体   繁体   English

SimpleDateFormat 周年

[英]SimpleDateFormat week year

java8 GregorianCalendar DOC java8 GregorianCalendar DOC

A week year is in sync with a WEEK_OF_YEAR cycle.一周年与 WEEK_OF_YEAR 周期同步。 All weeks between the first and last weeks (inclusive) have the same week year value.第一周和最后一周(含)之间的所有周都具有相同的周年值。 Therefore, the first and last days of a week year may have different calendar year values.因此,一周年的第一天和最后一天可能具有不同的日历年值。

For example, January 1, 1998 is a Thursday.例如,1998 年 1 月 1 日是星期四。 If getFirstDayOfWeek() is MONDAY and getMinimalDaysInFirstWeek() is 4 (ISO 8601 standard compatible setting), then week 1 of 1998 starts on December 29, 1997, and ends on January 4, 1998. The week year is 1998 for the last three days of calendar year 1997. If, however, getFirstDayOfWeek() is SUNDAY, then week 1 of 1998 starts on January 4, 1998, and ends on January 10, 1998;如果 getFirstDayOfWeek() 为 MONDAY 且 getMinimalDaysInFirstWeek() 为 4(ISO 8601 标准兼容设置),则 1998 年的第 1 周从 1997 年 12 月 29 日开始,到 1998 年 1 月 4 日结束。最后三天的年份为 1998 年1997 日历年。但是,如果 getFirstDayOfWeek() 是 SUNDAY,则 1998 的第 1 周从 1998 年 1 月 4 日开始,到 1998 年 1 月 10 日结束; the first three days of 1998 then are part of week 53 of 1997 and their week year is 1997. 1998 年的前三天是 1997 年第 53 周的一部分,它们的周年是 1997 年。

As the DOC said, if I set FirstDayOfWeek to SUNDAY and MinimalDaysInFirstWeek to 4, so week year of 1998-01-01 should be 1997, but junit result is 1998.正如 DOC 所说,如果我将 FirstDayOfWeek 设置为 SUNDAY 并将 MinimalDaysInFirstWeek 设置为 4,那么 1998-01-01 的周年应该是 1997,但 junit 结果是 1998。

Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.YEAR, 1998);
    calendar.set(Calendar.MONTH, 0);
    calendar.set(Calendar.DAY_OF_MONTH, 1);
    calendar.setMinimalDaysInFirstWeek(4);
    calendar.setFirstDayOfWeek(Calendar.SUNDAY);

    System.out.println(calendar.getTimeZone());
    System.out.println(calendar.getMinimalDaysInFirstWeek());
    System.out.println(calendar.getFirstDayOfWeek());

    SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd");
    System.out.println(sdf.format(calendar.getTime()));

junit result is: sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=29,lastRule=null] junit 结果是: sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=29,lastRule=null]

4 4

1 1

1998-01-01 1998-01-01

TL;DR: The formatter uses its own week numbering TL;DR:格式化程序使用自己的周编号

The date formatter is using its own week numbering scheme, not that of the date (in your case that of the Calendar object).日期格式化程序使用它自己的周编号方案,而不是日期的编号方案(在您的情况下为Calendar对象的编号方案)。 I am demonstrating using java.time the modern Java date and time API.我正在使用 java.time 演示现代 Java 日期和时间 API。 Specifically I am using a LocalDate .具体来说,我使用的是LocalDate A LocalDate is always a date in the ISO calendar system. LocalDate始终是 ISO 日历系统中的日期。

    LocalDate date = LocalDate.of(1998, Month.JANUARY, 1);
    DateTimeFormatter baseFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd");

    DateTimeFormatter chinaFormatter = baseFormatter.withLocale(Locale.CHINA);
    System.out.println("China:   " + date.format(chinaFormatter));

    DateTimeFormatter franceFormatter = baseFormatter.withLocale(Locale.FRANCE);
    System.out.println("France:  " + date.format(franceFormatter));

    DateTimeFormatter irelandFormatter = baseFormatter.withLocale(Locale.forLanguageTag("en-IE"));
    System.out.println("Ireland: " + date.format(irelandFormatter));

Output from this snippet is:这个片段的输出是:

 China: 1998-01-01 France: 1998-01-01 Ireland: 1997-01-01
  • If your default locale is China, your formatter was using China weeks.如果您的默认语言环境是中国,则您的格式化程序使用的是中国周。 They begin on Sunday, and week 1 is the week that contains January 1 (like in the US, as another example).它们从星期日开始,第 1 周是包含 1 月 1 日的那一周(就像在美国,作为另一个例子)。 So January 1 of 1998 must belong to week year 1998.所以 1998 年 1 月 1 日必须属于 1998 年周。
  • France uses ISO numbering: The week begins on Monday, and as you said, in this case week 1 of 1998 begins on December 29, 1997. So we get 1998 again.法国使用 ISO 编号:一周从星期一开始,正如您所说,在这种情况下,1998 年的第 1 周从 1997 年 12 月 29 日开始。所以我们再次得到 1998。
  • Ireland is one of the few countries using the mixed scheme that you were trying to obtain in your question: Minimal days in first week is 4 (as in ISO), and Sunday is the first day of the week (as in China and the US).爱尔兰是少数几个使用您试图在问题中获得的混合方案的国家之一:第一周的最少天数是 4(如 ISO),星期日是一周的第一天(如中国和美国) )。 So using a formatter with Ireland as locale country gives you the result you were trying to get, 1997.因此,使用带有爱尔兰作为语言环境国家/地区的格式化程序可以为您提供您想要获得的结果,1997 年。

A different way of obtaining a week year of 1997 from your date is to put your own WeekFields object together.从您的日期获取 1997 年的另一种方法是将您自己的WeekFields对象放在一起。 Then you don't need to worry about locale.那么您无需担心语言环境。

    WeekFields myWeekFields = WeekFields.of(DayOfWeek.SUNDAY, 4);
    int weekYear = date.get(myWeekFields.weekBasedYear());
    System.out.println("Week year: " + weekYear);

Week year: 1997周年份:1997

java.time?? java.time??

The date and time classes that you were using, Calendar and SimpleDateFormat , are poorly designed and long outdated.您使用的日期和时间类CalendarSimpleDateFormat设计不佳且已过时。

It seems from your document link that you are using Java 8, and if so, there's absolutely no reason why you should struggle with the old classes.从您的文档链接看来,您正在使用 Java 8,如果是这样,那么您绝对没有理由应该与旧类斗争。 Use java.time as I do above.像上面一样使用 java.time。 A backport for Java 6 and 7 exists too. Java 6 和 7 的反向移植也存在。

How come the code in the question didn't work?为什么问题中的代码不起作用?

You were taking the time out of your Calendar using calendar.getTime() .您正在使用calendar.getTime()Calendar中抽出时间。 This returns a Date (another poorly designed and long outdated class).这将返回一个Date (另一个设计不良且过时的类)。 A Date is a point in time, nothing more. Date是一个时间点,仅此而已。 It hasn't got any notion of week number or week year.它没有任何周数或周年的概念。 You passed this Date to your SimpleDateFormat , which had no way of detecting that the Date had originally come from a Calendar object with a certain setting of days in first week and first day of week.您将此Date传递给SimpleDateFormat ,它无法检测到Date最初来自Calendar对象,并且在第一周和一周的第一天具有特定的天数设置。 Instead the SimpleDateFormat uses its own definition of weeks.相反, SimpleDateFormat使用它自己的SimpleDateFormat It always does that.它总是这样做。 Since you had not explicitly set a locale or calendar for the SimpleDateFormat , it used the default locale of your JVM.由于您没有为SimpleDateFormat显式设置语言环境或日历,因此它使用了 JVM 的默认语言环境。 This produced a week year of 1998, as it would in the vast majority of locales.这产生了 1998 年的一周年,就像在绝大多数语言环境中一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM