【问题标题】:Start of week for locale using Joda-Time使用 Joda-Time 的语言环境的一周开始
【发布时间】:2010-12-20 14:08:54
【问题描述】:

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

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

Wikipedia "Seven-day week"#Week_number

【问题讨论】:

  • 请再读一遍我的问题。我相信我实际上已经足够努力地强调这一点,以至于对于你们两个提出的问题根本不可能误解它。令人惊讶的是,我错了。再说一遍:某些地区(即美国)使用星期日作为一周的第一天。其他人使用 ISO 标准星期一作为一周的第一天。我如何为此查询 Joda Time?使用 Java,这非常简单:java.sun.com/javase/6/docs/api/java/util/… 所以:Calendar.getInstance(Locale.US).getFirstDayOfWeek()。和乔达在一起?
  • 为什么不直接使用 Calendar.getInstance(Locale.US).getFirstDayOfWeek()?
  • 因为如果我想使用 Joda Time,我想“一直使用”它,而不是混合使用两个完全不同的库。
  • 是的,该声明意味着您可以轻松地在它们之间来回切换。 AFAICT 并不意味着您应该混合它们。对我来说,我似乎可以用 Joda Time 做任何事情,纯粹的,除了找到一周的第一天!
  • Calendar.getFirstDayOfWeek() 将返回与 Joda 的 DateTimeConstants 不同的数字。例如,Calendar.SUNDAY==1(美国默认),而 DateTimeConstants.SUNDAY==7 (ISO)。

标签: java calendar jodatime weekday


【解决方案1】:

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

DateTime dt = new DateTime().withYear(2009).plusDays(111);
dt.toGregorianCalendar().getFirstDayOfWeek();

【讨论】:

  • 不,这不是我的问题。我的问题是:给定 Locale.US (以及其他),一周的第一天是哪一天?我想让 Joda Time 告诉我——不是 java 标准。图书馆。 Joda Time 的年表似乎都表明星期一是一周的第一天(这就是 ISO8601 标准所说的)。这不可能吗? Joda Time 不知道美国人更喜欢将“星期日”作为一周的第一天来查看他们的日历,而(大多数)我们欧洲人对此感到非常沮丧,并希望“星期一”成为一周的开始吗?我觉得这令人难以置信,因为 Joda Time 似乎已经完成了。
  • 为什么不只使用 Java 标准库?也许他们没有实现它,因为它已经存在了。我真的不明白你的意思。
  • 你知道乔达时间吗?他们不需要实现任何东西,因为在 java std 中一切皆有可能。库。因此,我的问题仍然存在:如果 Joda Time 真的不可能,那么 Joda Time 是不完整的,缺乏的。我觉得这很难相信,但它可能是真的。
  • 无论如何,整个讨论对我来说似乎毫无意义。在我看来,应该使用 Joda Time,因为最初的实现是一个很棒的 PITA。但是,对于未提供的部分,您可以轻松退回。我认为没有必要复制每个方面,只是为了完整。如果 firstDayOfWeek 方法确实是唯一且唯一缺少的方法,我明白你的意思。但我不明白,为什么你对那个如此沮丧和热情......
【解决方案2】:

看起来你运气不好,看起来所有提供的 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)。

【讨论】:

  • 我不太明白。我们挪威人和他们美国人确实同意 2009 年 11 月 26 日是星期四——只是当我们显示整整一周时——连续 7 天——我们欧洲人从某个星期一开始,到下一个星期日结束(即“周末”是周六和周日,对吧?),而美国人从某个周日开始,到下一个周六结束。这与挪威人在 2009 年 11 月 26 日、瑞典人在 2009 年 11 月 26 日写的完全相同(他们在那儿是合乎逻辑的!)和美国人在 2009 年 11 月 26 日写的(?!)。这只是显示问题,不是计算问题。
  • 所有年表都将 2009-11-26 显示为星期四,这应该显示为 ISOChronology 中 5​​3 周的第 48 周。现在,如果我们要问 firstDayOfWeek(48) 是什么,答案将取决于语言环境:US = Sun 2009-11-22 NO = Mon 2009-11-23
  • 这个问题似乎类似于不同的编程语言,它们对数组中的第一个位置使用不同的值,例如java 是基于 0 的数组 [0],而 pascal 和 cobol 是基于 1 的数组 [1]。因此,如果在大小为 7 的数组中给定一个 > 1 的随机元素,那么确定如何返回第一个位置的方式将取决于您的编程语言:java: fdow(day[3]) = day [3-3] cobol/pascal: fdow(day[3]) = day[3-2]
  • 我希望类比不要太晦涩,同样地,不同地区的一周的第一天会有所不同,因为有些回到星期一,有些回到太阳,所以计算会有所不同,具体取决于语言环境。
  • 你在哪里有 firstDayOfWeek(48)?我不太明白这一点。您不需要争论 - 所有 1-53 都是一样的,总是吗?但不管怎样,我越是研究这个,越觉得 Joda Time 根本不处理这个问题?鉴于它被誉为 Java 日历的替代品,这不是特别奇怪吗? ..而不是倾向于美国人民?
【解决方案3】:

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

它没有能力获取星期的第一天,也没有能力返回基于标准星期一以外的任何一天的星期索引。最后,周数总是按照 ISO 规则计算的。

【讨论】:

  • 那我要问了——难道这不应该被视为 Joda Time 的明显缺陷吗?说真的,对于“打印日历”(即那些你挂在厨房里的那些,那些你在航班时间表网络应用程序中挑选的那些),当日历显示星期天作为一周的第一天时,我发现它非常烦人 - 我确实如此因为它而陷入麻烦。所以我认为,当美国人看到周从星期一开始的日历时,这对美国人来说一定是完全一样的:一切都变得“提前一天”,可以这么说——当查看一周的第三个“盒子”时,一个美国人假设是星期二。
  • @stolsvik 为什么应该是缺陷?这仅确定什么数字对应于一周中的哪一天。例如:1=星期一。
  • 因为,@CristianVrabie,如果您必须找到给定日期的一周的第一天,那么使用图书馆会更加困难。对于周一的语言环境,您可以调用LocalDate.now().withDayOfWeek(DateTimeConstants.MONDAY),但如果您实际上需要周日,这将不起作用。你必须检查它是否已经是星期天,如果不是,去星期天和一周前。糟透了。但是,请注意 Java 的日历也很糟糕;更糟糕的是,它让您相信它有效而无效,请参阅stackoverflow.com/a/7499264/505775
【解决方案4】:

没有理由至少不能使用 JDK 来为给定的语言环境找到“一周的习惯开始”。唯一棘手的部分是转换工作日的常量,两者都是 1 到 7,但 java.util.Calendar 移动了 1,Calendar.MONDAY = 2 与 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 而非默认值的结果。

【讨论】:

  • 这是我在对 11 月 29 日问题的评论中写的。 2009.
  • 非常好的答案,为 OP 提供了他所说的他正在寻找的东西。一个建议:明确指定包名称,“java.util.Calendar”,因此最纯粹的人不需要在他的代码顶部使用不受欢迎的 using 语句来违反他的敏感性。 :-)
【解决方案5】:

以下是如何利用 Joda 时间获得美国一周的第一天:

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

或者在 Scala 中

def getFirstDayOfWeek(other: DateTime) = other.dayOfWeek.get match {
    case 7 => other
    case _ => other.minusWeeks(1).withDayOfWeek(7)
}

【讨论】:

    【解决方案6】:

    我在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 已知的默认周一到周日)。对于美国(和其他类似)locales,您可以忽略这部分

    【讨论】:

      【解决方案7】:

      这就是我想出的。 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);
      }
      

      【讨论】:

        【解决方案8】:

        这是动态获取星期几的开始和结束的 Scala 代码。

        注意:- 确保开始和结束是有序的,例如当开始日是 Sunday 然后 Monday 是一周的结束日

        def shiftWeeksBy(startDayOfWeek: Int, currentWeekDay: Int) : Int = (startDayOfWeek, currentWeekDay) match {
          case (s, c) if s <= c  | s == 1 => 0 //start day of week is Monday -OR- start day of week <= current week day
          case _ => 1
        }
        
        def getStartAndEndDays(initialTime: DateTime, startDayOfWeek: Int, endDayOfWeek: Int): (Option[DateTime], Option[DateTime]) = {
           val currentDateWeekDay = initialTime.dayOfWeek.get
           (Some(initialTime.minusWeeks(shiftWeeksBy(startDayOfWeek, currentDateWeekDay)).withDayOfWeek(startDayOfWeek).withTimeAtStartOfDay()),
               Some(initialTime.plusWeeks(shiftWeeksBy(currentDateWeekDay, endDayOfWeek)).withDayOfWeek(endDayOfWeek)))
        }
        

        输出:- 对于5th Jan 2021,一周的开始日期为Thursday,一周的结束日期为Wednesday,则一周以2020-12-31 开始,以2021-01-06 结束。 p>

        scala> getStartAndEndDays(new DateTime("2021-01-05T00:00:00.000"), 4, 3)
        res5: (Option[org.joda.time.DateTime], Option[org.joda.time.DateTime]) = (Some(2020-12-31T00:00:00.000+05:30),Some(2021-01-06T00:00:00.000+05:30))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-21
          • 2021-11-03
          • 2014-02-11
          • 1970-01-01
          • 2011-01-12
          相关资源
          最近更新 更多