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

时间:2011-04-19 13:28:19

标签: java python calendar

我的实现有两部分,一部分是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的计算。

5 个答案:

答案 0 :(得分:4)

Java中的月份是从0开始的,你需要这个:

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

修改

如jarnbjo所述,Calendar应配置为生成ISO 8601周数as follows

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

答案 1 :(得分:2)

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

答案 2 :(得分:0)

检查set方法的javadoc。你会看到以下内容:

  

参数:

     

year - 用于设置YEAR的值   日历领域。

     

month - 用于设置的值   月日历字段。月值是   0为主。例如,1月份为0。

     

date - 用于设置的值   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); 
} 

答案 3 :(得分:0)

在Java中,7不是7月,而是8月。

答案 4 :(得分:0)

tl; dr

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

26

详细信息

正如其他人指出的那样,由于在该Calendar类中从零开始的疯狂计数,您的month参数是错误的。

还应注意,Calendar的“周”类定义因Locale而异,而不是使用Python代码中使用的ISO 8601 standard week definition

java.time

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

对于没有日期和时区的仅日期值,请使用LocalDate。使用方便的Month枚举可提高可读性。

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

或者使用月份号,在1月到12月之间以理智的数字表示1-12。

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

计算标准ISO 8601 week number。使用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及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

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

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore