为什么SQL Server周数与Java周数不同?

时间:2012-02-01 15:12:46

标签: java sql sql-server-2008 date week-number

我正在使用Java 6和SQL Server 2008编写报表系统。对于某些查询,我想按周编号查看数据。我正在使用Java来填补数据中的空白以形成连续的时间线,我发现了

java.util.Calendar cal = new java.util.GregorianCalendar();
cal.set(2012, 0, 1);
cal.get(Calendar.WEEK_OF_YEAR);

org.joda.time.DateTime date = new org.joda.time.DateTime(2012, 01, 01, 0, 0);
date.getWeekOfWeekyear();

将不同的周数返回

DATEPART(WEEK, '2012-01-01')

有解决这种差异的方法还是我必须选择使用SQL Server Java周数?

TIA

5 个答案:

答案 0 :(得分:6)

Java在计算周数方面更为复杂,而SQL-Server DATEPART(WEEK ......则更为简单。我发现以下内容记录了here

"设置或获取WEEK_OF_MONTH或WEEK_OF_YEAR字段时,日历必须将月份或年份的第一周确定为参考点。一个月或一年的第一周被定义为从getFirstDayOfWeek()开始并且至少包含getMinimalDaysInFirstWeek()"

的最早七天时段。

我认为这默认为ISO标准,这是一周中的第一周(周一至周日周,其中至少4天是一年)。考虑使用:

在SQL Server中,DATEPART(WEEK, ..)函数更简单,它只是计算1月1日和输入日期之间的星期边界数(由DATEFIRST定义),因此第1个1月将始终为第1周。您可能希望考虑使用:

SELECT DATEPART(ISO_WEEK, '01/01/2012')

这将获得ISO标准定义的周数,这是一周中的第一周(周一至周日,每年至少4天)。

由于SQL Server在其计算中更加简单,因此无法配置,这意味着您需要在Java中配置周数。只需确保使用正确的getFirstDayOfWeek()getMinimalDaysInFirstWeek()值设置您的日历:

public static Calendar getISOCalendar() {
    Calendar calendar = Calendar.getInstance();
    calendar.setMinimalDaysInFirstWeek(4);
    calendar.setFirstDayOfWeek(Calendar.MONDAY);
    return calendar;
}

然后你可以确保一致的周数。

public static void main(String args[]) {
    Calendar calendar = getISOCalendar();
    calendar.set(2012,0,1);
    System.out.println(calendar.get(Calendar.WEEK_OF_YEAR));
}

------
52

答案 1 :(得分:1)

根据各自的文档,java.util.calendarjodaDATEPART都返回1到53之间的整数,表示一周。此值基于定义为一周的第一天和默认日历(例如格里高利,中文)。我会检查你的默认值,或者看看每个人在一周的第一天的想法是什么。

答案 2 :(得分:0)

我认为它可能与2011年有关,并认为根据SQLServer它有53周的想法。看看Jan / New Year SQL problems!,这个解决方案可能有助于更好地处理SQLServer:

DATEPART(WEEK, DATEADD(WEEK, -1, '2012-01-01'))

答案 3 :(得分:0)

TL;博士

int iso8601WeekNumber = 
    ZonedDateTime.now( ZoneId.of ( "America/Montreal" ) )
        .get( IsoFields.WEEK_OF_WEEK_BASED_YEAR )

一周的许多定义

一周有很多定义。

对于某些人来说,一周的第一天是星期日,其他星期一,还有一天是其他人。

对于某些人来说,一年中的第一周包含1月1日,而其他一些人将第一周计算为包含上述开始日期的那一周,而其他人将第一周视为包含特定日期的一周-周。

所以,如果不学习文档,你应该永远不要假设“周”或“周数”的含义。

避免遗留日期时间类

通常,您应该避免使用与最早版本的Java捆绑在一起的旧旧日期时间类,因为它们设计不当,令人困惑且麻烦。

具体来说,java.util.Calendar类按区域设置有周定义。因此,如果您需要可靠的恒定结果,请不要使用它。

ISO 8601

ISO 8601标准定义了日期时间值的格式和相关问题。它specifically defines一周和一周的意思:

  • 周从周一到周日运行,编号为1-7,周一= 1。
  • 第1周包含一年中的第一个星期四,每年产生52或53周。

约达时间

Joda-Time库使用星期和星期的ISO 8601标准定义。

但是,请注意Joda-Time项目现在位于maintenance mode,团队建议迁移到java.time。

java.time

java.time类使用一周的ISO 8601定义:第1周有第一个星期四,第一周是星期一到星期日。

IsoFields类定义了基于周的年份。我们可以要求:

首先我们得到当前的日期时间。

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );

询问该日期时间对象,询问标准的基于周的年份。

int week = now.get ( IsoFields.WEEK_OF_WEEK_BASED_YEAR );
int weekYear = now.get ( IsoFields.WEEK_BASED_YEAR );

转储到控制台。

System.out.println ( "now: " + now + " is week: " + week + " of weekYear: " + weekYear );
  

现在:2016-01-17T20:55:27.263-05:00 [美国/蒙特利尔]是星期:2周,年:2016

有关详细信息,请参阅此类似问题:How to calculate Date from ISO8601 week number in Java

WeekFields

在java.time中,您还可以调用WeekFields类,例如WeekFields.ISO.weekBasedYear()。在Java 8或更高版本的更高版本(早期版本的Java 8中的某些bugs were fixed)中应该与IsoFields具有相同的效果。

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date.Calendar和& java.text.SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 4 :(得分:-1)

   System.out.println("get date range from week number and year in java");
   System.out.println(); // print a blank line

   // get the input from the user
   Scanner sc = new Scanner(System.in);

   System.out.print("Enter the week : ");
   int weekNumber  = sc.nextInt(); 
   System.out.print("Enter the Year: ");
   int year = sc.nextInt() ;



   Calendar cal = Calendar.getInstance();
   //cal.setTime(new Date());

   cal.set(Calendar.YEAR, year);
   cal.set(Calendar.WEEK_OF_YEAR, weekNumber);

   SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

   cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
   System.out.println(formatter.format(cal.getTime())); // start date

   cal.add(Calendar.DAY_OF_WEEK, 6);
   System.out.println(formatter.format(cal.getTime())); // end date