使用 Joda-Time 的区域设置的一周开始

IT小君   2021-10-18T04:41:27

您如何使用Joda-Time根据给定的Locale确定一周中的哪一天被视为“开始”

要点:大多数国家/地区使用国际标准星期一作为一周的第一天 (!)。其他一些人使用星期日(特别是美国)。其他人显然是星期六。有些显然是星期三?!

维基百科“一周七天”#Week_number

评论(7)
IT小君

Joda-Time 在周一至周日使用 ISO 标准。

它无法获取一周的第一天,也无法根据标准星期一以外的任何一天返回星期几索引。最后,周数总是按照 ISO 规则计算的。

2021-10-18T04:41:27   回复
IT小君

您没有理由不能至少使用 JDK 来为给定的 Locale 找到“一周的习惯开始”。唯一棘手的部分是转换工作日的常量,两者都是 1 到 7,但 java.util.Calendar 移位了 1,Calendar.MONDAY = 2 vs. DateTimeConstants.MONDAY = 1。

无论如何,请使用此功能:

/**
 * Gets the first day of the week, in the default locale.
 *
 * @return a value in the range of {@link DateTimeConstants#MONDAY} to
 *         {@link DateTimeConstants#SUNDAY}.
 */
private static final int getFirstDayOfWeek() {
  return ((Calendar.getInstance().getFirstDayOfWeek() + 5) % 7) + 1;
}

将 Locale 添加到 Calendar.getInstance() 以获取除默认值之外的某些 Locale 的结果。

2021-10-18T04:41:28   回复
IT小君

以下是人们如何绕过 Joda 时间来获得美国一周的第一天:

DateTime getFirstDayOfWeek(DateTime other) {
  if(other.dayOfWeek.get == 7)
    return other;
  else
    return other.minusWeeks(1).withDayOfWeek(7);
}

或者在斯卡拉

def getFirstDayOfWeek(other: DateTime) = other.dayOfWeek.get match {
    case 7 => other
    case _ => other.minusWeeks(1).withDayOfWeek(7)
}
2021-10-18T04:41:28   回复
IT小君

好像你不走运,看起来所有提供的 Chronologies 都继承了 baseChronology 的实现,它只支持 ISO 定义,即星期一 = 1 ...星期日 = 7。

您必须定义自己的 LocaleChronology,可能以 StrictChronology 或 LenientChronology 为模型,添加工厂方法:

public static LocaleChronology getInstance(Chronology base, Locale locale)

并覆盖实施

public final DateTimeField dayOfWeek()

重新实现依赖于 sun.util.resources.LocaleData..getCalendarData(desiredLocale) 的 java.util.Calendar.setWeekCountData(Locale desiredLocale)。

2021-10-18T04:41:28   回复
IT小君

这就是我想出的。startOfWeek将永远是一个星期天的开始和endOfweek将永远是一个周六的一端(启动星期一)。

DateTime startOfWeek;
DateTime endOfWeek;
// make sure Sunday is the first day of the week, not Monday
if (dateTime.getDayOfWeek() == 7) {
    startOfWeek = dateTime.plusDays(1).weekOfWeekyear().roundFloorCopy().minusDays(1);
    endOfWeek = dateTime.plusDays(1).weekOfWeekyear().roundCeilingCopy().minusDays(1);
} else {
    startOfWeek = dateTime.weekOfWeekyear().roundFloorCopy().minusDays(1);
    endOfWeek = dateTime.weekOfWeekyear().roundCeilingCopy().minusDays(1);
}
2021-10-18T04:41:28   回复
IT小君

所以你的问题是,如何从 Joda DateTime 对象中获取 DayOfWeek?那这个呢:

DateTime dt = new DateTime().withYear(2009).plusDays(111);
dt.toGregorianCalendar().getFirstDayOfWeek();
2021-10-18T04:41:28   回复
IT小君

我用下面的存根Scala获得第一天和最后一天的一周,从Joda DateTime

val today: DateTime = new DateTime()
val dayOfWeek: DateTime.Property = today.dayOfWeek()

val firstDayOfWeek: DateTime = dayOfWeek.withMinimumValue().minusDays(1)
val lastDayOfWeek: DateTime = dayOfWeek.withMaximumValue().minusDays(1)

注意minusDays(1)仅用于使周跨度从星期日到星期六(而不是默认的星期一到星期日Joda)。对于美国(和其他类似的)语言环境,您可以忽略此部分

2021-10-18T04:41:28   回复