java比较日期不超过一年,一年中的Java日期库不一致

As per https://en.wikipedia.org/wiki/ISO_8601#Week_dates, Weekdays start on Monday. But, from Java, if you try to extract week number in two different ways, two different outputs come if the date is a Sunday.

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Calendar;

public class TestDate {

public static void main(String[] args) throws ParseException {

final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");

final SimpleDateFormat weekFormatter = new SimpleDateFormat("ww");

String date = "2018-10-21";

System.out.println(weekFormatter.format(formatter.parse(date)));

Calendar calendar = Calendar.getInstance();

calendar.setFirstDayOfWeek(Calendar.MONDAY);

calendar.setTime(formatter.parse(date));

System.out.println(calendar.get(Calendar.WEEK_OF_YEAR));

}

}

Output:

43

42

Is this an inconsistency?

This is just a test program I wrote to reproduce the issue, I noticed the problem in Hive, like the following:

0: jdbc:hive2://zk0-something> select from_unixtime(t, 'ww'), weekofyear(from_unixtime(t, 'yyyy-MM-dd')) from (select 1540122033 as t) a;

+------+------+--+

| _c0 | _c1 |

+------+------+--+

| 43 | 42 |

+------+------+--+

1 row selected (0.388 seconds)

0: jdbc:hive2://zk0-something>

解决方案

java.time

String date = "2018-10-21";

LocalDate ld = LocalDate.parse(date);

int weekOfYear = ld.get(WeekFields.ISO.weekOfYear());

System.out.println(weekOfYear);

Output:

42

Since you are interested in the ISO 8601 rules for week numbers, use WeekFields.ISO for getting week related data from a LocalDate. You may also use a formatter if you like:

DateTimeFormatter weekFormatter = DateTimeFormatter.ofPattern("ww", Locale.FRANCE);

System.out.println(ld.format(weekFormatter));

Output is the same:

42

The locale passed to DateTimeFormatter.ofPattern determines the week scheme. If I pass Locale.US instead, I get 43.

I recommend you use java.time, the modern Java date and time API, and stay away from the old date-time classes like SimpleDateFormat and Calendar. The old ones were poorly designed and the modern ones are much nicer to work with.

What went wrong in your code?

Both the outdated SimpleDateFormat class and the modern DateTimeFormatter take their week numbering scheme from their locale. If no locale is specified for the formatter, it uses the default locale of the JVM. So if the JVM has American locale, for example, the formatter will print 43 in your first example because in the US Sunday October 21 this year was in week 43. If the locale is French, it will print 42 because that day was in week 42 in France. France follows the ISO 8601 standard, the USA does not.

In your example, setting the Calendar’s first day of week to Monday causes the week number to be 42 as you had expected. This will not always be the case, however. Week numbers are defined not only by the first day of the week but also by the definition of week 1. From your link:

The first ISO week of a year may have up to three days that are

actually in the Gregorian calendar year that is ending; if they are

Monday, Tuesday and Wednesday. Similarly, the last ISO week of a year

may have up to three days that are actually in the Gregorian calendar

year that is starting; if they are Friday, Saturday, and Sunday. The

Thursday of each ISO week is always in the Gregorian calendar year

denoted by the ISO week-numbering year.

The American definition of which week is week 1 is different: In the US January 1 is always in week 1. Therefore if your Calendar is created with American locale, setting its first day of week to Monday is not enough to make is follow ISO 8601 rules. Coincidentally, for 2018 the week numbers agree, though.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值