             hour: firstHour, minute: firstMinute, second: firstSecond)
     }
 
-    internal func nextDay(_ date: Date) -> Date? {
+    func nextDay(_ date: Date) -> Date? {
         guard let nextDay = dayOfMonthPattern(month: date.month, year: date.year).next(date.day) else {
             return nextMonth(date)
         }

    internal let hash      : Int64
}

extension DatePattern {
    internal func secondPattern() -> NumberSet {
        return (try? second.toSecondPattern(hash)) ?? .none
    }
    internal func minutePattern() -> NumberSet {
        return (try? minute.toMinutePattern(hash)) ?? .none
    }
    internal func hourPattern() -> NumberSet {
        return (try? hour.toHourPattern(hash)) ?? .none
    }
    internal func dayOfMonthPattern(month: Int, year: Int) -> NumberSet {
        precondition(1...12 ~= month)
        let dayValue  = (try? dayOfMonth.toDayOfMonthPattern(month: month, year: year, hash: hash)) ?? .none
        let weekValue = (try? dayOfWeek.toDayOfWeekPattern(month: month, year: year, hash: hash)) ?? .none
        return .and(dayValue, weekValue)
    }
    internal func monthPattern() -> NumberSet {
        return (try? self.month.toMonthPattern()) ?? .none
    }
    internal func yearPattern() -> NumberSet {
        return (try? self.year.toYearPattern()) ?? .none
    }
}

extension DatePattern {
    func next(_ date: Date) -> Date? {
        if !yearPattern().contains(date.year) {
            return nextYear(date)

        fatalError("unreachable")
    }

    func nextYear(_ date: Date) -> Date? {
        guard let nextYear = yearPattern().next(date.year) else {
            return nil
        }
