Swift 可移动日期

Swift 可移动日期,swift,range,sequence,date-range,Swift,Range,Sequence,Date Range,我正在寻找一种很酷的方法,以不同的增量跨越日期范围(秒,又称时间间隔,或日期组件又称小时,分钟) 问题的第二部分是,我也想要一些类似的东西: var components = DateComponents() components.hour = 8 components.minute = 0 let date = Calendar.current.date(from: components) let dateByComponentArr : [Date] = Array(stride(from:

我正在寻找一种很酷的方法,以不同的增量跨越
日期
范围(秒,又称
时间间隔
,或
日期组件
又称
小时
分钟

问题的第二部分是,我也想要一些类似的东西:

var components = DateComponents()
components.hour = 8
components.minute = 0
let date = Calendar.current.date(from: components)
let dateByComponentArr : [Date] = Array(stride(from: now, to: dayAfterNow, by: components))

日期
已经声明了一个冲突的
距离(to:)
实现。您定义的实现具有相同的名称,但类型不同。另一个重载可能会起作用,但不幸的是,
Date
已经声明了一个名为
Stride
的类型别名,它将该别名设置为
TimeInterval
(只是
Double
的别名)

我认为遵从
Date
streadable
是个坏主意。以
Double
为例,它故意不符合
stripable
:没有明确的通用最佳步幅定义。它是否应该上升到
0.1
<代码>0.01<代码>3.14?这不明显<代码>跨步(from:to:by:)的存在正是因为这个原因,你需要清楚地知道你的跨步量


让errDateArr:[Date]=Array(now…dayAfterNow)
肯定会得高分

对于问题的第二部分,我创建了一个简单的序列,考虑了夏令时设置和其他内容。在某些特定情况下,它可能会有所帮助

let dayAfterNow = Date().addingTimeInterval(86400)
var components = DateComponents()
components.hour = 8
components.minute = 0

func dateIterator(start: Date = Date(), by components: DateComponents, wrappingComponents: Bool = false) -> AnyIterator<Date> {
    var state = start
    return AnyIterator {
        
        let nextDate = Calendar.current.date(byAdding: components, to: state, wrappingComponents: wrappingComponents)
        state = nextDate ?? state
        return state
    }    
}


let dateCompSequence = AnySequence(dateIterator(by: components))
let dateArray = Array(dateCompSequence.prefix(10))
dateArray.map{print($0.description)}
print("starting for loop...")

for d in dateCompSequence.prefix(10) {
    print(d.description)
}
let dayAfterNow=Date()。添加时间间隔(86400)
var components=DateComponents()
组件。小时=8
组件。分钟=0
func dateIterator(start:Date=Date(),by components:DateComponents,wrappingComponents:Bool=false)->AnyIterator{
var状态=开始
返回任意迭代器{
让nextDate=Calendar.current.date(通过添加:组件、收件人:状态、包装组件:包装组件)
状态=下一个日期??状态
返回状态
}    
}
让dateCompSequence=AnySequence(dateIterator(by:components))
让dateArray=Array(dateCompSequence.prefix(10))
dateArray.map{print($0.description)}
打印(“开始循环…”)
对于dateCompSequence.前缀中的d(10){
打印(d.说明)
}

值得注意的是,
Calendar.current.enumerateDates()
可能总是有助于完成类似的任务。但有一个序列有时更可取。在早期版本的Swift中,NSCalendar似乎提供了一种可移动类型(这正是我想要的),但现在标准库中没有类似的类型。

正如@Alexander已经提到的,您不应该尝试将日期与可移动类型一致,但您可以实现自己的方法来生成接下来的n天、小时或分钟:

extension Date {
    func year(using calendar: Calendar = .current) -> Int { calendar.component(.year, from: self) }
    func month(using calendar: Calendar = .current) -> Int { calendar.component(.month, from: self) }
    func day(using calendar: Calendar = .current) -> Int { calendar.component(.day, from: self) }
    func hour(using calendar: Calendar = .current) -> Int { calendar.component(.hour, from: self) }
    func minute(using calendar: Calendar = .current) -> Int { calendar.component(.minute, from: self) }
    func nextDays(n: Int, nth: Int = 1, using calendar: Calendar = .current) -> [Date] {
        let year  = self.year(using: calendar)
        let month = self.month(using: calendar)
        let day   = self.day(using: calendar)
        var days: [Date] = []
        for x in 0..<n where x.isMultiple(of: nth) {
            days.append(DateComponents(calendar: calendar, year: year, month: month, day: day + x, hour: 12).date!)

        }
        return days
    }
    func nextHours(n: Int, nth: Int = 1, using calendar: Calendar = .current) -> [Date] {
        let year  = self.year(using: calendar)
        let month = self.month(using: calendar)
        let day   = self.day(using: calendar)
        let hour   = self.hour(using: calendar)
        var hours: [Date] = []
        for x in 0..<n where x.isMultiple(of: nth) {
            hours.append(DateComponents(calendar: calendar, year: year, month: month, day: day, hour: hour + x).date!)

        }
        return hours
    }
    func nextMinutes(n: Int, nth: Int = 1, using calendar: Calendar = .current) -> [Date] {
        let year  = self.year(using: calendar)
        let month = self.month(using: calendar)
        let day   = self.day(using: calendar)
        let hour   = self.hour(using: calendar)
        let minute   = self.minute(using: calendar)
        var minutes: [Date] = []
        for x in 0..<n where x.isMultiple(of: nth) {
            minutes.append(DateComponents(calendar: calendar, year: year, month: month, day: day, hour: hour, minute: minute + x).date!)

        }
        return minutes
    }
}

PlayGound测试:

let days = Date().nextDays(n: 10)
for day in days {
    print(Date.formatter.string(from: day))
}

let hours = Date().nextHours(n: 10)
for hour in hours {
    print(Date.formatter.string(from: hour))
}

let minutes = Date().nextMinutes(n: 10)
for minute in minutes {
    print(Date.formatter.string(from: minute))
}

相关:还有:。是的,
日历
枚举日期()
非常有用,@Martin。但在某些情况下,我们只需要一个iterable序列本身,也许是惰性序列。我想知道为什么
NSCalendar
中的
DateRange
被丢弃。在
Stride
类型不是
Int
的边界之间生成默认序列(没有明确的步骤)确实是个坏主意。然而,
Double
确实符合
stridible
的要求,否则就不可能用它创建
stride
序列。啊,我对Stridable的目的有一个错误的理解。
的能力不仅仅取决于是否符合
可移动的
,还要求
跨步
是一个
签名的整数
你为什么要通过0分钟?您没有设置要添加的组件。这很容易出错。如果您通过等于1的日组件并立即开始,它将返回7/14/20、3:32 PM 7/15/20、3:32 PM 7/16/20、3:32 PM 7/17/20、3:32 PM 7/18/20、3:32 PM 7/19/20、3:32 PM 7/21/20、3:32 PM 7/22/20、3:32 PM 7/23/20、3:32 pmi如果开始日期为“6/30/20、11:45 AM”,并且通过日组件=1,则将导致6/11/20,11:45 AM 6/12/20,11:45 AM 6/13/20,11:45 AM 6/14/20,11:45 AM 6/15/20,11:45 AM 6/16/20,11:45 AM 6/17/20,11:45 AM 6/18/20,11:45 AM 6/19/20,11:45 AM 6/20/20,11:45 AMI我不确定,但看起来您正在尝试实现类似的目标,但仍然存在一些问题。试试看
let start=DateComponents(日历:。当前,年份:2020,月:6,日:30,小时:23,分钟:45)。日期
print(Date.formatter.string(from:d))
}
中为d编写代码,并检查在2月之后返回的日期看起来非常方便。尤其是第n部分。
extension Date {
    static let formatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateStyle = .short
        formatter.timeStyle = .short
        return formatter
    }()
}
let days = Date().nextDays(n: 10)
for day in days {
    print(Date.formatter.string(from: day))
}

let hours = Date().nextHours(n: 10)
for hour in hours {
    print(Date.formatter.string(from: hour))
}

let minutes = Date().nextMinutes(n: 10)
for minute in minutes {
    print(Date.formatter.string(from: minute))
}