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

发布于 2025-01-01 09:24:40 字数 523 浏览 1 评论 0原文

我正在使用 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 < em>或 Java 周数?

TIA

I'm working on a reporting system using Java 6 and SQL Server 2008. For some queries I want to look at the data by week number. I'm using Java to fill in gaps in the the data to make a continuous time line and I have found that

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

and

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

return a different week number to

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

Is there an approach to resolving this difference or will I have to choose to use SQL Server or Java week numbers?

TIA

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

七度光 2025-01-08 09:24:40

Java 在计算周数时更为复杂,而 SQL-Server DATEPART(WEEK... 则更为简单。我发现以下记录 此处

"设置或获取 WEEK_OF_MONTH 或 WEEK_OF_YEAR 字段时,日历必须确定第一周一个月或一年的第一周被定义为从 getFirstDayOfWeek() 开始并至少包含 getMinimalDaysInFirstWeek() 的最早的 7 天时间段“

我认为这默认为 ISO 标准,即一年中的第一周,其中星期四(周一至周日,一年中至少有 4 天)。

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

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

这获取 ISO 标准定义的周数,即第一周一年中的星期四(周一至周日,一年中至少有 4 天)。

正如所述,由于 SQL Server 的计算更加简单,因此无法对其进行配置,这意味着您需要在 Java 中配置周数。只需确保您在 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

Java is more sophisticated when it comes to calculating week numbers, whereas SQL-Server DATEPART(WEEK... is more simplistic. I found the following documented here

"When setting or getting the WEEK_OF_MONTH or WEEK_OF_YEAR fields, Calendar must determine the first week of the month or year as a reference point. The first week of a month or year is defined as the earliest seven day period beginning on getFirstDayOfWeek() and containing at least getMinimalDaysInFirstWeek() "

I think this defaults to the ISO standards which is the first week of the year with a thursday in (Monday-Sunday weeks where at least 4 days are the year). Consider using:

In SQL Server the DATEPART(WEEK, ..) function is much more simplistic, it simply calculates the number of week boundaries (as defined by DATEFIRST) between the first of january, and the input date, so the 1st January will always be week 1. You may wish to consider using:

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

This gets the week number as defined by the ISO standards, which is the first week of the year with a thursday in (Monday-Sunday weeks where at least 4 days are the year).

Since, as stated SQL Server is more simplistic in it's calculations, this can't be configured, which means that you will need to configure your week numbers within Java. Simply ensure you set up your calendar in Java with the correct values for getFirstDayOfWeek() and getMinimalDaysInFirstWeek():

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

Then you can esnsure consistent week numbers.

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

------
52
稚然 2025-01-08 09:24:40

根据各自的文档, java.util .calendarjodaDATEPART 均返回 1 到 53 之间的整数表示星期。该值基于一周第一天的定义和默认日历(例如公历、中国)。我会检查您的默认值或看看每个人认为一周的第一天是什么。

According to their respective docs, java.util.calendar, joda, and DATEPART all return an integer between 1 and 53 indicating the week. This value is based on what is defined as the first day of the week and the default calendar (e.g. Gregorian, Chinese). I would check your defaults or see what each thinks the first day of the week is.

尤怨 2025-01-08 09:24:40

我认为这可能与 2011 年有关,并且根据 SQLServer 的说法,它有 53 周。查看 一月/新年 SQL 问题!,这解决方案可能有助于更好地处理 SQLServer 内容:

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

I think it might have something to do with 2011 and the idea that it has 53 weeks according to SQLServer. Looking at Jan / New Year SQL problems!, this solution might help to handle the SQLServer stuff better:

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

汐鸠 2025-01-08 09:24:40

tl;dr

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 标准定义了日期时间值的格式和相关问题。它具体定义了一周和一年中的一周的含义:

  • 每周从星期一开始 -星期日,编号为 1-7,其中星期一 = 1。
  • 第 1 周包含一年中的第一个星期四,每年有 52 或 53 周。

Joda-Time

Joda-Time 库使用 ISO 8601 周和周的标准定义-年。

但是,请注意 Joda-Time 项目现已位于 维护模式,团队建议迁移到 java.time。

java.time

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

IsoFields< /a> class 定义基于周的年份。我们可以要求:

首先我们获取当前的日期时间。

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

有关更多信息,请参阅类似的问题:如何根据 ISO8601 周数计算日期Java

WeekFields

在 java.time 中,您还可以调用 WeekFields 类,如WeekFields.ISO.weekBasedYear ()。应该与 Java 8 或更高版本中的 IsoFields 具有相同的效果(修复了一些错误 在 Java 8 的早期版本中)。


关于 java.time

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

Joda-Time 项目,现已在 维护模式,建议迁移到 java.time。

要了解更多信息,请参阅 Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范为 JSR 310

从哪里获取 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是 java.time 未来可能添加的内容的试验场。您可能会在这里找到一些有用的类,例如 间隔YearWeekYearQuarter更多

tl;dr

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

Many definitions of a week

There are many definitions of a week.

For some people the first day of a week is a Sunday, others Mondays, and still others some other day.

For some people the first week of the year contains January 1st, while some other folks count the first week as the one containing that start-of-week day mentioned above, while others count week one as containing a specific day-of-week.

So you should never assume the meaning of a "week" or "week number" without studying the documentation.

Avoid legacy date-time classes

In general, you should avoid the old legacy date-time classes bundled with the earliest versions of Java as they are poorly-designed, confusing, and troublesome.

Here specifically, the java.util.Calendar class has a definition of week that varies by locale. So do not use this if you want reliable constant results.

ISO 8601

The ISO 8601 standard defines formats and related issues for date-time values. It specifically defines the meaning of a week and week-of-year:

  • Week runs from Monday-Sunday, numbered 1-7 where Monday = 1.
  • Week # 1 contains the first Thursday of the year, yielding 52 or 53 weeks per year.

Joda-Time

The Joda-Time library uses the ISO 8601 standard definition of week and week-of-year.

However, be aware that the Joda-Time project is now in maintenance mode, with the team advising migration to java.time.

java.time

The java.time classes use the ISO 8601 definition of a week: Week # 1 has first Thursday, with week running Monday-Sunday.

The IsoFields class defines a week-based year. We can ask for the:

First we get the current date-time.

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

Interrogate that date-time object, asking about the standard week-based year.

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

Dump to console.

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

now: 2016-01-17T20:55:27.263-05:00[America/Montreal] is week: 2 of weekYear: 2016

For more info, see this similar Question: How to calculate Date from ISO8601 week number in Java.

WeekFields

In java.time you can also call upon the WeekFields class, such as WeekFields.ISO.weekBasedYear(). Should have the same effect as IsoFields in later versions of Java 8 or later (some bugs were fixed in earlier versions of Java 8).


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to java.time.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

The ThreeTen-Extra project 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.

看透却不说透 2025-01-08 09:24:40
   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
   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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文