1

我正在尝试解决jsr310中的“last Friday the 13th”表达式,但如果您可以在 Joda Time 或其他一些库中解决,那也可以。我做到了这一点:

val builder = new DateTimeBuilder()
  .addFieldValue(ChronoField.DAY_OF_MONTH, 13)
  .addFieldValue(ChronoField.DAY_OF_WEEK, DayOfWeek.FRIDAY.getValue)

这似乎指定了“13 号星期五”好吧。但是我如何从这个到“13 号上周五”呢?

4

2 回答 2

1

这里是每月迭代解决方案(记住两个这样的日期之间不能超过 14 个月),这可能比每日迭代解决方案更好。我在纯 Java 的 JSR-310 的基础上编写它 - 未经测试,因此无法保证(而且我不知道编写 Scala,所以你必须根据你的需要调整它):

public static final TemporalAdjuster LAST_FRIDAY_13 = (Temporal temporal) -> {
  LocalDate test = LocalDate.from(temporal);

  // move to last 13th of month before temporal
  if (test.getDayOfMonth() <= 13) {
    test = test.minus(1, ChronoUnit.MONTHS);
  }

  test = test.withDayOfMonth(13);

  // iterate monthly backwards until it is a friday
  while (test.getDayOfWeek() != DayOfWeek.FRIDAY) {
    test = test.minus(1, ChronoUnit.MONTHS);
  }

  return test;
}

请注意,调节器存储为静态常量(规范负责人 Stephen Colebourne 也推荐使用此值)。然后你可以这样去使用这个调节器:

System.out.println(LocalDate.of(2012, 12, 12).with(LAST_FRIDAY_13));
// Output: 2012-07-13

顺便说一句,您也在其他库中要求提供解决方案。好吧,如果您可以等待几周(3-4),那么我将使用我的新时间库提供一个非常相似的解决方案,它只需要 Java 6+。您当然也可以将显示的代码翻译成 JodaTime(应该或多或少直接)。

于 2014-01-06T17:43:02.587 回答
0

我能想出的唯一解决方案是向后走,手动检查这一天是否满足约束条件。这是一个通用的类,用于通过时间向后走以找到DateTime满足某些约束的类:

class PreviousAdjuster(constraints: (DateTimeField, Int)*) extends WithAdjuster {
  val unit = constraints.map(_._1.getBaseUnit).minBy(_.getDuration)
  def doWithAdjustment(dateTime: DateTime): DateTime = {
    var curr = dateTime
    while (constraints.exists{case (field, value) => curr.get(field) != value}) {
      curr = curr.minus(1, unit)
    }
    curr
  }
}

with然后我可以在 a 的方法中使用该调节器DateTime

val lastFridayThe13th = LocalDate.of(2012, 12, 12).`with`(new PreviousAdjuster(
    ChronoField.DAY_OF_MONTH -> 13,
    ChronoField.DAY_OF_WEEK -> DayOfWeek.FRIDAY.getValue))

println(lastFridayThe13th) // prints 2012-07-13    

感觉应该有一种更有效的方法来做到这一点,因为限制意味着我们不必每天都走过,但我不知道如何实现......

于 2012-12-14T10:26:16.690 回答