1、问题:
在某些情况下,会需要将日期按周来进行排序或统计,mysql就要用到week()或yearWeek()函数,就会发现,比如2016年的某一天,在mysql里面是属于第30周,但在JAVA中使用Calendar类计算出来,却是第31周,单纯的将mysql查询出来的周进行+1操作,会解决2016的问题,但到了2017年,就会出现问题了。
百度了下,很多人都碰到这个问题,后来在stackoverflow上找到了解决思路:使用JDK8提供的java.time类库可以完美解决。
2、原因:
在JAVA中,“周”由以下两个因素决定:
- 周的开始日期(星期一为一周的第一天,或星期日为每周的第一天)
- 第一周的最小天数(1~4天)
在mysql中,“周”由以下两个因素决定:
- 周的开始日期(星期一为一周的第一天,或星期日为每周的第一天),与JAVA相同
- 第一周最少包含4天,或第一周包含一周的第一天(如果星期一为一周的第一天,则必须包含星期一,才算第一周)
week函数由参数mode的值来控制星期由哪天开始
模式 | 星期的第一天 | 范围 | 星期 1 是第一天 |
0 | Sunday | 0-53 | 一年中多一个星期天 |
1 | Monday | 0-53 | 一年多3天 |
2 | Sunday | 1-53 | 一年中多一个星期天 |
3 | Monday | 1-53 | 一年多3天 |
4 | Sunday | 0-53 | 一年多3天 |
5 | Monday | 0-53 | 一年中多一个星期一 |
6 | Sunday | 1-53 | 一年多3天 |
7 | Monday | 1-53 | 一年中多一个星期一 |
3:解决方法:
示例代码:
SELECT DATE_FORMAT('2017-01-01', '%x') AS year, WEEK('2017-01-01', 3) AS week;
结果:
---------------------------------------------------
year week
2016 52
---------------------------------------------------
以星期一为一周的开始,则2017-01-01属于2016年的第52周,获取2016年第52周的星期一的时间为:
String dateStr = "2016-W52-1";
LocalDate localDate2 = LocalDate.parse(dateStr, DateTimeFormatter.ISO_WEEK_DATE);
int day = localDate2.getDayOfMonth();
int month = localDate2.getMonthValue();
int year = localDate2.getYear();
LOGGER.info("1:year-month-day:{}-{}-{}", year, month, day);
星期日的时间为:
dateStr = "2016-W52-7";
localDate2 = LocalDate.parse(dateStr, DateTimeFormatter.ISO_WEEK_DATE);
day = localDate2.getDayOfMonth();
month = localDate2.getMonthValue();
year = localDate2.getYear();
LOGGER.info("2:year-month-day:{}-{}-{}", year, month, day);
[2017-01-22 14:59:45] [main] [INFO] [c.v.f.m.u.DateUtilsTest] - 1:year-month-day:2016-12-26
[2017-01-22 14:59:45] [main] [INFO] [c.v.f.m.u.DateUtilsTest] - 2:year-month-day:2017-1-1
简单说明:
String dateStr = "2016-W52-1";
LocalDate localDate2 = LocalDate.parse(dateStr, DateTimeFormatter.ISO_WEEK_DATE);
W52表示52周,最后面的1代表星期1,同理,改为1~7可以获取周一到周日的具体日期
获取某天属于一年中的第几周:
String dateStr = "2017-01-01";
LocalDate localDate = LocalDate.parse(dateStr);
int week = localDate.get ( IsoFields.WEEK_OF_WEEK_BASED_YEAR );
int weekYear = localDate.get ( IsoFields.WEEK_BASED_YEAR );
LOGGER.info("week:{}", week);
LOGGER.info("weekYear:{}", weekYear);
打印结果:
[2017-01-22 14:59:45] [main] [INFO] [c.v.f.m.u.DateUtilsTest] - week:52
[2017-01-22 14:59:45] [main] [INFO] [c.v.f.m.u.DateUtilsTest] - weekYear:2016
参考资料:
http://stackoverflow.com/questions/24566831/week-of-year-calculation-differences-among-java-and-multi-sql-rdbms