2012-12-13 49 views
1

我試圖解決表達「上週五13日」jsr310,但如果你可以在喬達時間或其他圖書館做到這一點,那很好太。我得到了這個:「上週五13日」在jsr310或joda-time

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

這似乎指定「星期五第13」好吧。但是我怎樣才能從此到「上週五13日」呢?

回答

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方法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  

感覺就像應該有一個更有效的方法來做到這一點,因爲約束意味着我們不必每天都在步行,但我不知道如何實現...

1

在這裏每月iter (記住兩個這樣的日期之間不能超過14個月),這可能比每日迭代解決方案更好。我把它寫在JSR-310的基地,在純Java - 沒有測試,因此無法保證(我不知道寫斯卡拉所以你要它適應您的需求):

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),那麼我將提供一個非常類似的解決方案,使用我的new time library,這隻需要Java 6+。你也可以把顯示的代碼翻譯成JodaTime(應該或多或少地直接)。

+0

這對於13號星期五的特定問題肯定更有效。儘管如此,它並沒有很好地概括任何其他領域。例如,如果我切換到「DAY_OF_YEAR」而不是「DAY_OF_MONTH」,或者如果我添加了另一個約束,就像它也必須在2月份一樣,您的代碼不能直接使用。 – Steve

+0

是的,具體說明DAY_OF_MONTH和DAY_OF_WEEK的組合預計將配置調節器。對於其他條件,無論如何還需要另一種算法 - 由於我們日曆的不規則性而導致最終後果。有無限的可能性。沒有圖書館可以提供全部,但是你可以自由地爲你的具體問題編寫自己的調節器。 –

+0

請注意,對於我給這個問題的答案,您不需要爲每個問題編寫一個新的調整器 - 它將處理任何類型的單位和任何數量的約束。但要使其像每個問題的自定義編碼解決方案一樣高效,可能相當困難。 – Steve

相關問題