Java 和 Python 之间的一年中的周计算差异

发布于 2024-11-02 17:06:14 字数 583 浏览 1 评论 0 原文

我的实现有两部分,一部分用 Python,另一部分用 Java。现在的问题是我意识到他们对一年中周数的计算不匹配。例如:

Java 代码:

private static int getWeekOfYear(int y, int m, int d) {
    Calendar cal = Calendar.getInstance();
    cal.setMinimalDaysInFirstWeek(4);
    cal.set(y, m, d);
    return cal.get(Calendar.WEEK_OF_YEAR);
}

System.out.println(getWeekOfYear(2010, 7, 1));

Java 结果:31

Python 代码:

print datetime(2010, 7, 1, 0, 0).isocalendar()[1]

Python 结果:26

现在我怎样才能使它们相同呢?顺便说一句,我希望 Java 能够完全遵循 python 的计算。

I have two parts of my implementation, one in Python and one in Java. Now the problem is I realized their calculations of week number of the year don't match. For example:

Java code:

private static int getWeekOfYear(int y, int m, int d) {
    Calendar cal = Calendar.getInstance();
    cal.setMinimalDaysInFirstWeek(4);
    cal.set(y, m, d);
    return cal.get(Calendar.WEEK_OF_YEAR);
}

System.out.println(getWeekOfYear(2010, 7, 1));

Java result: 31

Python code:

print datetime(2010, 7, 1, 0, 0).isocalendar()[1]

Python result: 26

Now how can I get these to be the same? I'd like Java to follow exactly python's calculation by the way.

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

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

发布评论

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

评论(5

执笏见 2024-11-09 17:06:14

Java 中的月份是从 0 开始的,您需要这样:

cal.set(y, m - 1, d); 

编辑:

正如 jarnbjo 所指出的,Calendar 应配置为生成 ISO 8601 周数 如下

cal.setMinimalDaysInFirstWeek(4);    
cal.setFirstDayOfWeek(Calendar.MONDAY);

Months in Java are 0-based, you need this:

cal.set(y, m - 1, d); 

EDIT:

As noted by jarnbjo, Calendar should be configured to produce ISO 8601 week numbers as follows:

cal.setMinimalDaysInFirstWeek(4);    
cal.setFirstDayOfWeek(Calendar.MONDAY);
甲如呢乙后呢 2024-11-09 17:06:14

Java 中奇数月份编号的问题并不是完整的解决方案。 Java 使用本地化规则来计算周数(不同国家对于哪个工作日是第一天以及哪一周是一年中的第一天有不同的规则)。 Python 的 isocalendar 函数使用根据 ISO 8601 的周编号规则,出于这些目的,该规则定义一周从星期一开始,并且 1 月 4 日始终位于第 1 周。

The issue with the odd month numbering in Java is not the entire solution. Java uses localized rules to calculate the week number (different countries have different rules regarding which weekday is the first and which week is the first of the year). Python's isocalendar function uses the week numbering rules according to ISO 8601, which for these purposes defines that a week starts on Monday and that January 4th is always in week number 1.

梦屿孤独相伴 2024-11-09 17:06:14

太长了;博士

LocalDate.of( 2010 , Month.JULY , 1 )
.get ( 
    IsoFields.WEEK_OF_WEEK_BASED_YEAR 
)

26

详细信息

正如其他人所指出的,您的月份参数不正确,因为在该 Calendar 类中进行了从零开始的疯狂计数。

另请注意,“星期”的 Calendar 类定义因 Locale 而异,而不是使用 ISO 8601 标准周定义

java.time

另一个问题:您正在使用与最早版本的 Java 捆绑在一起的非常麻烦的旧日期时间类。它们现在已成为遗产,被 java.time 类取代。

对于仅包含日期的值,没有时间和时区,请使用 LocalDate。使用方便的 月份< /a> 枚举以提高可读性。

LocalDate ld = LocalDate.of( 2010 , Month.JULY , 1 ) ;

或者使用月份编号,1 月至 12 月的编号为 1-12。

LocalDate ld = LocalDate.of( 2010 , 7 , 1 ) ;

计算标准ISO 8601 周数。使用 LocalDate::get 方法来访问相关值。传递枚举元素 IsoFields .WEEK_OF_WEEK_BASED_YEAR 表示您想要的值。

int w = ld.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR ) ;

YearWeek

提示:如果您在一年中的这一周做了很多工作,您可能会发现 YearWeek 类在 ThreeTen-Extra 项目。

YearWeek yw = YearWeek.from( ld ) ;

关于 java.time

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

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

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

您可以直接与数据库交换java.time对象。使用符合 JDBC 驱动程序 /jeps/170" rel="nofollow noreferrer">JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* 类。

从哪里获取 java.time 类?

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

tl;dr

LocalDate.of( 2010 , Month.JULY , 1 )
.get ( 
    IsoFields.WEEK_OF_WEEK_BASED_YEAR 
)

26

Details

As other noted, your month argument was incorrect because of the crazy counting from zero done in that Calendar class.

Also noted was that Calendar class definition of "week" varies by Locale rather than using the ISO 8601 standard week definition used in your Python code.

java.time

Another issue: You are using terribly troublesome old date-time classes bundled with the earliest version of Java. They are now legacy, supplanted by the java.time classes.

For a date-only value, without time-of-day and without time zone, use LocalDate. Use the handy Month enum for readability.

LocalDate ld = LocalDate.of( 2010 , Month.JULY , 1 ) ;

Or use month number, with sane numbering 1-12 for January-December.

LocalDate ld = LocalDate.of( 2010 , 7 , 1 ) ;

Calculate the standard ISO 8601 week number. Use the LocalDate::get method to access a relevant value. Pass the enum element IsoFields.WEEK_OF_WEEK_BASED_YEAR to indicate your desired value.

int w = ld.get( IsoFields.WEEK_OF_WEEK_BASED_YEAR ) ;

YearWeek

Tip: If you are doing much work with this week-of-year, you may find helpful the YearWeek class found in the ThreeTen-Extra project.

YearWeek yw = YearWeek.from( ld ) ;

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, & SimpleDateFormat.

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

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

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

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.

々眼睛长脚气 2024-11-09 17:06:14

检查 javadoc 中的 set 方法。您将看到以下内容:

参数:

year - 用于设置 YEAR 的值
日历字段。

月份 - 用于设置的值
月份日历字段。月值是
0 为基础。例如,0 代表一月。

日期 - 用于设置的值
DAY_OF_MONTH 日历字段。

所以你的代码应该变成如下:

private static int getWeekOfYear(int y, int m, int d) {     
    Calendar cal = Calendar.getInstance();     
    cal.setMinimalDaysInFirstWeek(4);     
    cal.set(y, m - 1, d);     // Note the change here
    return cal.get(Calendar.WEEK_OF_YEAR); 
} 

Check the javadoc for the set method. You'll see the following:

Parameters:

year - the value used to set the YEAR
calendar field.

month - the value used to set the
MONTH calendar field. Month value is
0-based. e.g., 0 for January.

date - the value used to set the
DAY_OF_MONTH calendar field.

So your code should become the following:

private static int getWeekOfYear(int y, int m, int d) {     
    Calendar cal = Calendar.getInstance();     
    cal.setMinimalDaysInFirstWeek(4);     
    cal.set(y, m - 1, d);     // Note the change here
    return cal.get(Calendar.WEEK_OF_YEAR); 
} 
我做我的改变 2024-11-09 17:06:14

在 Java 中 7 不是七月,而是八月。

In Java 7 is not July, it's August.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文