如何在Swift上使用跨步功能从StartDate到EndDate每天进行迭代?

时间:2019-03-31 20:00:09

标签: ios swift date

我正在尝试创建一个接收以下内容的函数:

-开始日期(DATE)。

-结束日期(DATE)。

能够逐日迭代以yyyy-MM-dd格式打印日期

但是我遇到以下错误:

"Cannot invoke 'stride' with an argument list of type '(from: Date, to: Date, by: Int)'"

我尝试了什么?

我的约会符合通用协议

extension Date: Strideable {
    public func distance(to other: Date) -> TimeInterval {
        return other.timeIntervalSinceReferenceDate - self.timeIntervalSinceReferenceDate
    }

    public func advanced(by n: TimeInterval) -> Date {
        return self + n
    }
}

所以我可以使用跨步功能

stride(from: <#T##Strideable#>, to: <#T##Strideable#>, by: <#T##Comparable & SignedNumeric#>)

在我的ViewDidLoad上尝试运行它

override func viewDidLoad() {
        super.viewDidLoad()
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy/MM/dd"
        let startDate = formatter.date(from: "2014/01/01")
        let endDate = formatter.date(from: "2019/03/31")
        let dayDurationInSeconds = 60*60*24

        for date in stride(from: startDate!, to: endDate!, by: dayDurationInSeconds) {
            print(date)
        }
}

我希望在控制台上看到什么?

2014-01-01
2014-01-02
2014-01-03
.........
2019-03-30
2019-03-31

1 个答案:

答案 0 :(得分:2)

您的代码无法编译,因为您正在跨整数,但已将Stride定义为TimeInterval。如果您修复dayDurationInSeconds的类型,它将满足您的大部分期望:

let dayDurationInSeconds: TimeInterval = 60*60*24

但这会给您完全不正确的结果,因为并非每天都有86,400秒。 DST会根据位置的不同,每年两次更改日长。

执行日期数学运算的正确方法是使用Calendar。如果您没有使用Calendar,那么您将无法使用几秒钟内未明确显示的任何内容。

您可能想要的更像这样,它枚举了有关日期之间的所有午夜(UTC)。请记住,Foundation中的Date不是“日期”。这是一个精确的时间点。如果您确实想使用“日期”,那么您想要的是DateComponents

let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd"
let startDate = formatter.date(from: "2014/01/01")!
let endDate = formatter.date(from: "2019/03/31")!

var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = TimeZone(identifier: "UTC")!

calendar.enumerateDates(startingAfter: startDate,
                        matching: DateComponents(hour: 0, minute: 0, second:0),
                        matchingPolicy: .nextTime) { (date, _, stop) in
                            guard let date = date, date < endDate else {
                                stop = true
                                return
                            }

                            print(date)
}