DateBuilder

DateBuilder 允许您以可视化和声明式的方式轻松创建 DateDateComponents 实例。使用 DateBuilder,您可以轻松定义日期,从简单的“明天晚上 9 点”到复杂的“未来 24 个月内每个月的第一个星期五,时间在下午 3 点到 7 点之间的随机时间”

维护者: @dreymonde

目前,DateBuilder 仍处于 beta 阶段。某些 API 可能会在发布版本之间发生更改。

DateBuilderNiceNotifications 的一个独立部分,这是一个从内容到权限都大大简化了本地通知的框架。

用法

import DateBuilder

Today()
    .at(hour: 20, minute: 15)
    .dateComponents() // year: 2021, month: 1, day: 31, hour: 20, minute: 15

NextWeek()
    .weekday(.saturday)
    .at(hour: 18, minute: 50)
    .dateComponents() // DateComponents

EveryWeek(forWeeks: 10, starting: .thisWeek)
    .weekendStartDay
    .at(hour: 9, minute: 00)
    .dates() // [Date]
    
ExactlyAt(account.createdAt)
    .addingDays(15)
    .date() // Date
    
WeekOf(account.createdAt)
    .addingWeeks(1)
    .lastDay
    .at(hour: 10, minute: 00)
    .dateComponents() // DateComponents

EveryMonth(forMonths: 12, starting: .thisMonth)
    .lastDay
    .at(hour: 23, minute: 50)
    .dateComponents() // [DateComponents]

NextYear().addingYears(2)
    .firstMonth.addingMonths(3) // April (in Gregorian)
    .first(.thursday)
    .dateComponents() // year: 2024, month: 4, day: 4

ExactDay(year: 2020, month: 10, day: 5)
    .at(hour: 10, minute: 15)
    .date() // Date

ExactYear(year: 2020)
    .lastMonth
    .lastDay
    .dateComponents()

指南

DateBuilder 的结构

每个 DateBuilder 表达式都以特定的日期结束(如果您使用像 EveryDay/EveryMonth/etc. 这样的函数,则为一组日期)。首先,您将表达式指定到日期,然后通过调用 at(hour:minute:) 函数定义一天中的时间。 例如:

NextWeek()
    .firstDay
    .at(hour: 10, minute: 15)

一旦有了 at 表达式,您的日期就完全确定了。 您可以通过调用 .date().dateComponents() 来获取现成的 DateDateComponents 实例。

稍微复杂一点的例子是:

let dateComponents = NextYear()
    .firstMonth.addingMonths(3)
    .first(.thursday)
    .at(hour: 21, minute: 00)
    .dateComponents()

因此,我们从年份的尺度开始,然后将其缩小到月份的尺度,最后我们得到特定的日期,在本例中是明年 4 月的第一个星期四。 之后,我们使用 at 函数来完成查询。

可用函数

日期

// top-level
Today()
Tomorrow()
DayOf(account.createdAt)
ExactDay(year: 2021, month: 1, day: 26)
AddingDays(15, to: .today)
AddingDays(15, to: .dayOf(account.createdAt))
EveryDay(forDays: 100, starting: .tomorrow)
EveryDay(forDays: 100, starting: .dayOf(account.createdAt))

// instance
Today()
--->.addingDays(10)

星期

注意:一周的开始和结束由当前设置的 Calendar 及其 Locale 决定。 要了解如何自定义用于 DateBuilder 查询的日历对象,请参阅下面的“自定义日历/区域设置/时区”部分

// top-level
ThisWeek()
NextWeek()
WeekOf(account.createdAt)
WeekOf(Today()) // use any `DateBuilder.Day` instance here
AddingWeeks(5, to: .thisWeek)
EveryWeek(forWeeks: 10, starting: .nextWeek)

// instance
ThisWeek()
--->.addingWeeks(10) // Week
--->.firstDay // Day
--->.lastDay // Day
--->.allDays // [Day]
--->.weekday(.thursday) // Day
--->.weekendStartDay // Day
--->.weekendEndDay // Day

月份

// top-level
ThisMonth()
NextMonth()
MonthOf(account.createdAt)
MonthOf(Today()) // use any `DateBuilder.Day` instance here
ExactMonth(year: 2021, month: 03)
AddingMonths(3, to: .thisMonth)
EveryMonth(forMonths: 5, starting: .monthOf(account.createdAt))

// instance
ThisMonth()
--->.addingMonths(5) // Month
--->.firstDay // Day
--->.lastDay // Day
--->.allDays // [Day]
--->.first(.saturday) // Day
--->.weekday(.third, .friday) // Day

年份

// top-level
ThisYear()
NextYear()
YearOf(account.createdAt)
YearOf(Tomorrow()) // use any `DateBuilder.Day` instance here
YearOf(NextMonth()) // use any `DateBuilder.Month` instance here
ExactYear(year: 2022)
AddingYears(1, to: ThisYear())
EveryYear(forYears: 100, starting: .thisYear)

// instance
ThisYear()
--->.addingYears(1) // Year
--->.firstMonth // Month
--->.lastMonth // Month
--->.allMonths // [Month]

解析日期

Today()
--->.at(hour: 10, minute: 15)
--->.at(hour: 19, minute: 30, second: 30)
--->.at(TimeOfDay(hour: 10, minute: 30, second: 0)) // equivalent to:
--->.at(.time(hour: 10, minute: 30))
--->.at(.randomTime(from: .time(hour: 10, minute: 15), to: .time(hour: 15, minute: 30)))
Today()
    .at(hour: 9, minute: 15)
    .date() // Date
    
// or

Today()
    .at(hour: 9, minute: 15)
    .dateComponents() // DateComponents

您还可以通过在 DateBuilder.Day 的实例上调用 dateComponents() 来获取 DateComponents 实例(但不是 Date),而无需使用 at

NextMonth()
    .firstDay
    .dateComponents() // year: 2021, month: 2, day: 1

使用 ExactlyAt 函数

ExactlyAt 从现有的 Date 实例创建一个已解析的日期。 然后,您可以使用它来执行简单的日期计算(函数 addingMinutes/addingHours 等),并轻松获取 DateDateComponents 实例。

ExactlyAt(account.createdAt)
--->.addingSeconds(30)
--->.addingMinutes(1)
--->.addingHours(5)
--->.addingDays(20)
--->.addingMonths(3)
--->.addingWeeks(14)
--->.addingYears(1)

// usge:
ExactlyAt(account.createdAt)
    .addingMinutes(15)
    .dateComponents() // DateComponents

使用 Every 函数

您可以像使用 Today()NextYear() 一样使用 EveryDayEveryWeekEveryMonthEveryYear 函数。 唯一的区别是,最后您将获得一个日期数组,而不是单个实例

let dates = EveryMonth(forMonths: 12, starting: .thisMonth)
    .firstDay.addingDays(9)
    .at(hour: 20, minute: 00)
    .dates() // [Date]
    
// or

let dates = EveryMonth(forMonths: 12, starting: .thisMonth)
    .lastDay.addingDays(-5)
    .at(hour: 20, minute: 00)
    .dateComponents() // [DateComponents]

如果您将 .at(.randomTime( ... )) 函数与 Every 函数一起使用,则每天的确切解析时间将不同。

自定义日历/区域设置/时区

默认情况下,DateBuilder 使用 Calendar.current 进行所有计算。 如果需要自定义它,您可以全局更改它

var customCalendar = DateBuilder.calendar
customCalendar.firstWeekday = 6
DateBuilder.calendar = customCalendar

或者暂时使用 DateBuilder.withCalendar 函数

DateBuilder.withCalendar(customCalendar) {
    ThisWeek().firstDay.dateComponents()
}

在评估表达式后,DateBuilder 将返回到其全局 Calendar 实例。

以类似的方式,您也可以使用 DateBuilder.withTimeZoneDateBuilder.withLocale 函数

DateBuilder.withTimeZone(TimeZone(identifier: "America/Cancun")) {
    Tomorrow().at(hour: 9, minute: 15).date()
}

let nextFriday = DateBuilder.withLocale(Locale(identifier: "he_IL")) {
    NextWeek()
        .weekendStartDay
        .at(hour: 7, minute: 00)
        .date() // next friday!
}

所有这些函数都支持返回闭包的结果(见上文)。

安装

Swift Package Manager

  1. 点击 File → Swift Packages → Add Package Dependency。
  2. 输入 http://github.com/nicephoton/DateBuilder.git

鸣谢

特别感谢

相关资料