GregorianCalendar setFirstDayOfWeek不影响前牛轧糖上的WEEK_OF_YEAR

时间:2017-01-26 21:47:52

标签: android dayofweek gregorian-calendar week-number

下面的代码给出了Nougat和pre-Nougat的不同结果。看看,如果你想要自己尝试一下。如果有人能解释我为什么并给出解决方案,我将不胜感激。

我想要所有Android版本的正确WEEK_OF_YEAR值,取决于一周的第一天。我有一个时间表应用程序,我正在使用gregorianCalendar很多,所以我不想切换到另一个类/ lib。

    //default first day of the week is Monday for replication. I live in the Netherlands, it's weird.
    Locale l = new Locale("nl", "NL");

    GregorianCalendar test = new GregorianCalendar(l);
    test.set(Calendar.YEAR, 2017);
    test.set(Calendar.MONTH, 0);
    test.set(Calendar.DAY_OF_MONTH, 29);//this is a Sunday

    int week = test.get(Calendar.WEEK_OF_YEAR);//should be 4
    test.setFirstDayOfWeek(1);//Set it to Sunday
    int week2 = test.get(Calendar.WEEK_OF_YEAR);//should be 5 but is 4 below nougat???

2 个答案:

答案 0 :(得分:3)

如果您查看release notes for Nougat,就可以看到对语言环境的支持得到了增强。

特别是,

  

在Android 7.0之前,Android无法始终成功匹配应用和系统区域设置。

我也在自己的设备上注意到这一点。我的手机设置了英语(澳大利亚)语言环境。在Nougat之前,

DateTimeFormat.forPattern("dd MMMM").print(new LocalDate(2017,1,29));

会打印29 Jan(没有句号/期间),但在Nougat之后会打印29 Jan.(有句号)。

虽然我很难给出确切的细节,但似乎这就是你的情况。 Post-Nougat后,手机能够更好地匹配应用和系统区域设置,包括您的区域设置的一周的第一天。在任何情况下,单步执行调试器以查找根本原因都不会起作用,因为调用是在libcore内处理的,而不是源代码中公开的Java类。

如果Android设备错误地报告了一年中的第一天/一年中的第一周,除了解决问题之外,您几乎无法做到:

if (android.os.Build.VERSION.SDK_INT < 24) {
    //pre-Nougat logic
}
else {
    //Nougat/post-Nougat logic
}

您也可以尝试使用enhanced replacement for GregorianCalendar(在SDK 24中添加)来解决您的问题。

如果您使用Joda-time等类或使用新的JSR-310类(通过ThreeTen backport),您可以获得所需内容而无需解决GregorianCalendar。通常,这些类更容易使用,并且更容易出错。由于此类问题,许多开发人员已放弃java.util.Calendarjava.util.Date。有关详细信息,请参阅答案to this canonical question

如果您使用Joda,可以使用LocalDate.fromCalendarFields(test)GregorianCalendar对象转换为LocalDate。这些课程使用ISO标准,其中一周的第一天始终是星期一。然后,您可以在它们之上编写所需的逻辑。那么GregorianCalendar的问题就是&#34;隔离&#34;仅仅检索给定区域设置的一年中的第一周。如果您的应用程序包含对服务器的调用,则可以通过API调用在一周的第一天进行服务。

<强>更新

注意时区行为已在Android O中更新:

其他区域设置和与国际化相关的更改如下:

  

时区名称解析已更改。以前,Android设备使用在引导时采样的系统时钟值来缓存用于解析日期时间的时区名称。因此,如果系统时钟在启动时或其他罕见情况下出错,则解析可能会受到负面影响。   现在,在常见情况下,解析逻辑在解析时区名称时使用ICU和当前系统时钟值。此更改提供了更正确的结果,当您的应用使用类似SimpleDateFormat的类时,这可能与早期的Android版本不同。 Android O将ICU版本更新为版本58。

答案 1 :(得分:-1)

据我所知,问题出在你设定月份的行上。

//在月份参数中,您传递0作为可能产生问题的值,因为即使数组从0开始,此Calendar.MONTH接受的输入也介于1到12之间。因此请尝试更改它。

或者您也可以将其更改为将其设置为1月作为月份使用

test.set(Calendar.MONTH, Calendar.JANUARY);

//此处此行也尝试更改为

test.setFirstDayOfWeek(Calendar.SUNDAY);//Set it to Sunday

这可以解决您的问题。