【问题标题】:Calendar returns bad start of week on some Android devices日历在某些 Android 设备上返回糟糕的一周开始
【发布时间】:2018-11-07 08:54:03
【问题描述】:

我想获取本周第一天的日期。所以我是这样实现的:

fun getFirstDayInCurrentWeek(): Date {
    val calendar = Calendar.getInstance()
    calendar.clear(MILLISECOND)
    calendar.clear(SECOND)
    calendar.clear(MINUTE)
    calendar.set(HOUR_OF_DAY, 0)
    calendar.set(DAY_OF_WEEK, 1)
    return calendar.time
}

它适用于大多数设备,但有时它会返回下周第一天的日期。我不知道为什么。

课程来自java.util.*

编辑:只需在今天(28.05.2018)记录此函数的结果,您将看到 27.05.2018 或 03.06.2018。这些设备具有相同的区域设置和相同的时区。

【问题讨论】:

  • 请提供一些样本数据,以便针对您的结果进行测试。
  • 只需记录此函数的结果,您将看到今天(28.05.2018)的 27.05.2018 或 03.05.2018。
  • 您是否使用具有相同时区/语言环境的设备进行测试?这可能解释了差异
  • 在美国的语言环境中,一周的第一天是SUN。就像“午夜”出于某种原因 12:00 PM 而不是像 00:00 这样的东西。
  • @EpicPandaForce 好的,但结果有 7 天的差异,而不仅仅是一天。

标签: android date kotlin dayofweek java.util.calendar


【解决方案1】:

如果我理解正确,您想考虑星期天是一周的第一天(如在美国)。

    WeekFields wf = WeekFields.SUNDAY_START;
    LocalDate today = LocalDate.now(ZoneId.of("Europe/Warsaw"));
    LocalDate firstDayOfThisWeek = today.with(wf.dayOfWeek(), 1);
    System.out.println(firstDayOfThisWeek);

我正在编写 Java 代码并相信您可以转换为 Kotlin。今天(5 月 29 日,星期二)运行此打印

2018-05-27

如果您希望将星期一作为一周的第一天(如波兰和国际标准所述),只需使用 WeekFields.ISO 而不是 WeekFields.SUNDAY_START。如果您希望它依赖于语言环境,请使用例如WeekFields.of(Locale.forLanguageTag("pl-PL"))

另一个可能更清晰的选择是:

    LocalDate firstDayOfThisWeek = today
            .with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY));

在这两种情况下,我都使用现代 Java 日期和时间 API java.time。我认为这是一个很好的例子,它提供了更清晰的代码,与 Calendar 这样的旧日期和时间类相比,这通常是这种情况。

你的代码出了什么问题?

据我了解文档,您的代码应该给出本周的星期日。 Calendar 使用 1 表示星期日。您可能使用calendar.set(DAY_OF_WEEK, SUNDAY) 来获得完全相同的结果。当我今天运行它时,当使用星期日作为一周的第一天时,我得到 5 月 27 日,当使用星期一作为第一天时,我得到 6 月 3 日(这意味着星期日是一周的最后一天)。但是,文档不是很清楚,Calendar 类可能会令人困惑。无论如何,当你在不同的设备上尝试时,可能也会发生这种情况:它们对周有不同的定义。如果您可以单独配置周定义,即使它们具有相同的语言环境,这也是可能的。

问题:我可以在 Android 上使用 java.time 吗?

是的,java.time 在较旧和较新的 Android 设备上都能正常工作。它只需要至少 Java 6

  • 在 Java 8 及更高版本以及更新的 Android 设备上(据我所知,从 API 级别 26 开始),现代 API 是内置的。
  • 在 Java 6 和 7 中,获取 ThreeTen Backport,即新类的后向端口(对于 JSR 310,ThreeTen;请参阅底部的链接)。
  • 在(较旧的)Android 上使用 ThreeTen Backport 的 Android 版本。它被称为 ThreeTenABP。并确保从 org.threeten.bp 导入日期和时间类以及子包。

链接

【讨论】:

  • 这是一个很好的答案,感谢它。所以你的意思是Calendar 在使用美国标准时在本周的第一天工作得很好,但在 ISO 标准下表现得很奇怪并返回下周的第一天,对吗?而且我认为我必须使用 Java 8 中的 DateTime。
  • 谢谢。这不完全是我的意思。在您的代码中,您要求输入星期日,因此无论星期日是否是一周的第一天,它都会给您星期日。
  • 你的意思是calendar.set(DAY_OF_WEEK, 1) 这总是星期天?但其实没关系,问题是它返回了 7 天的差异,而不是 1 天。
  • 是的,一周中的一天 1 始终表示星期日。因此,它可以给出两个不同结果的唯一方法是给出两个不同的星期天,它们必须相隔 7 天(至少)。
【解决方案2】:

不同国家/地区的第一天是不同的。如果您希望它对所有用户都相同,您可以将 Locale 传递给 Calendar

Calendar currentCalendar = Calendar.getInstance(new Locale("en","UK"));

同样来自this的回答,可以使用setFirstDayOfWeek()方法设置一周的第一天。该方法只能影响 WEEK_OF_MONTH 或 WEEK_OF_YEAR 的返回值。对于 DAY_OF_WEEK,它什么也不做。

你可以实现类似的东西:

Calendar cal = Calendar.getInstance();
cal.setFirstDayOfWeek(Calendar.MONDAY);
int rec = cal.get(Calendar.WEEK_OF_MONTH);
System.out.println(rec);

阅读更多关于 API HERE

【讨论】:

  • 这不能回答我的问题。结果的差异是 7 天,而不是 1 天。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多