Swift - 给定一个固定的字符串数组(时间),找到下一个最接近的时间
Swift - Given a fixed array of Strings (times), find the next closest time
我正在使用 UIKit 开发一个简单的 iOS 应用程序,它可以显示下一班公交车的发车时间。
我有一个字符串数组,代表出发时间。我已将这些字符串转换为 DateComponents
对象并尝试使用 .nextDate
方法访问下一个最接近的时间。不幸的是,在搜索并尝试了各种选项之后,我似乎无法弄清楚。我尝试了一个具有固定值的日期组件对象。这有效,但没用。我需要从数组中获取值(除非有另一个我不知道的选项)。
到目前为止我的代码看起来是什么:
let currentTime = Date()
let calendar = Calendar.current
var busTimes = ["15:02", "15:27", "15:52", "16:12", "16:37", "17:02", "17:27", "17:52", "18:12", "18:32", "18:52", "19:17"]
@IBAction func calculateRoute(_ sender: Any) {
let myDate = busTimes[0].getMyDate()
let nextBusTime = calendar.nextDate(after: currentTime, matching: myDate, matchingPolicy: .nextTime, repeatedTimePolicy: .first, direction: .forward )!
print(nextBusTime) //prints only the first value ofc
}
extension String {
func getMyDate() -> DateComponents {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
dateFormatter.timeZone = TimeZone.current
let date = dateFormatter.date(from: self)
let dateComp = Calendar.current.dateComponents([.hour, .minute], from: date!)
return dateComp
}
}
我希望 return 下一个最接近的值。假设当前时间是 15:15,那么输出应该是下一个最接近的时间,即 15:27.
提前致谢!
首先让我们定义一个允许我们表达时间的类型。
struct Time {
let hour: Int
let minute: Int
static let zero = Time(hour: 0, minute: 0)
}
让我们也实现一个初始化器,这样我们就可以方便地传入字符串化的时间值
extension Time {
init(_ string: String) {
let ints = string
.components(separatedBy: ":")
.compactMap(Int.init)
hour = ints.first ?? 0
minute = ints.last ?? 0
}
}
let timeFromString = Time("2:30")
让我们也符合 Comparable
以便我们可以比较 Time
个值并对 Time
个值Array
进行排序
extension Time: Comparable {
static func < (lhs: Time, rhs: Time) -> Bool {
return lhs.hour * 60 + lhs.minute < rhs.hour * 60 + rhs.minute
}
}
print(Time("02:00") < Time("03:44"))
print([Time("03:44"), Time("02:00"), Time("1:30")].sorted())
true
[01:30, 02:00, 03:44]
这只是为了好玩。我们可以用 String
文字
初始化 Time
值
extension Time: ExpressibleByStringLiteral {
init(stringLiteral: String) {
self.init(stringLiteral)
}
}
let timeFromStringLiteraL: Time = "3:30"
这将使我们能够将 Time
值转换为友好的 String
值,主要用于调试。
extension Time: CustomStringConvertible {
var description: String {
return String(format: "%02d:%02d", hour, minute)
}
}
print(Time("4:30"))
04:30
现在让我们扩展 Calendar
以便我们可以将 Date
值转换为 Time
值
extension Calendar {
func time(from date: Date) -> Time? {
let timeComponents = dateComponents([.hour, .minute], from: date)
guard let hour = timeComponents.hour,
let minute = timeComponents.minute else { return nil }
return Time(hour: hour, minute: minute)
}
}
let timeFromDate = Calendar.current.time(from: Date())
现在让我们创建一个类型来为我们管理 Time
值。请注意当您传入时间值时它是如何排序的。这会设置 next(after:)
方法,因此它可以轻松找到指定时间后的下一个时间。
struct Schedule {
let times: [Time]
init(times: [Time]) {
self.times = times.sorted()
}
func next(after time: Time) -> Time? {
times.first(where: { [=16=] > time })
}
}
综合起来
let times: [Time] = ["01:22", "15:02", "15:27", "15:52", "16:12", "16:37", "20:00", "17:02", "17:27", "17:52", "18:12", "18:32", "18:52", "19:46", "18:37", "19:17", "19:32", "19:33"]
let schedule = Schedule(times: times)
let now = Calendar.current.time(from: Date())!
let next = schedule.next(after: now)
print("Next time: \(next ?? .zero)")
或:
["01:22", "15:02", "15:27", "20:22", "20:23"]
.map { Time([=18=]) }
.filter { [=18=] > now }
.sorted()
.prefix(1)
.forEach { print([=18=]) }
我正在使用 UIKit 开发一个简单的 iOS 应用程序,它可以显示下一班公交车的发车时间。
我有一个字符串数组,代表出发时间。我已将这些字符串转换为 DateComponents
对象并尝试使用 .nextDate
方法访问下一个最接近的时间。不幸的是,在搜索并尝试了各种选项之后,我似乎无法弄清楚。我尝试了一个具有固定值的日期组件对象。这有效,但没用。我需要从数组中获取值(除非有另一个我不知道的选项)。
到目前为止我的代码看起来是什么:
let currentTime = Date()
let calendar = Calendar.current
var busTimes = ["15:02", "15:27", "15:52", "16:12", "16:37", "17:02", "17:27", "17:52", "18:12", "18:32", "18:52", "19:17"]
@IBAction func calculateRoute(_ sender: Any) {
let myDate = busTimes[0].getMyDate()
let nextBusTime = calendar.nextDate(after: currentTime, matching: myDate, matchingPolicy: .nextTime, repeatedTimePolicy: .first, direction: .forward )!
print(nextBusTime) //prints only the first value ofc
}
extension String {
func getMyDate() -> DateComponents {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
dateFormatter.timeZone = TimeZone.current
let date = dateFormatter.date(from: self)
let dateComp = Calendar.current.dateComponents([.hour, .minute], from: date!)
return dateComp
}
}
我希望 return 下一个最接近的值。假设当前时间是 15:15,那么输出应该是下一个最接近的时间,即 15:27.
提前致谢!
首先让我们定义一个允许我们表达时间的类型。
struct Time {
let hour: Int
let minute: Int
static let zero = Time(hour: 0, minute: 0)
}
让我们也实现一个初始化器,这样我们就可以方便地传入字符串化的时间值
extension Time {
init(_ string: String) {
let ints = string
.components(separatedBy: ":")
.compactMap(Int.init)
hour = ints.first ?? 0
minute = ints.last ?? 0
}
}
let timeFromString = Time("2:30")
让我们也符合 Comparable
以便我们可以比较 Time
个值并对 Time
个值Array
进行排序
extension Time: Comparable {
static func < (lhs: Time, rhs: Time) -> Bool {
return lhs.hour * 60 + lhs.minute < rhs.hour * 60 + rhs.minute
}
}
print(Time("02:00") < Time("03:44"))
print([Time("03:44"), Time("02:00"), Time("1:30")].sorted())
true
[01:30, 02:00, 03:44]
这只是为了好玩。我们可以用 String
文字
Time
值
extension Time: ExpressibleByStringLiteral {
init(stringLiteral: String) {
self.init(stringLiteral)
}
}
let timeFromStringLiteraL: Time = "3:30"
这将使我们能够将 Time
值转换为友好的 String
值,主要用于调试。
extension Time: CustomStringConvertible {
var description: String {
return String(format: "%02d:%02d", hour, minute)
}
}
print(Time("4:30"))
04:30
现在让我们扩展 Calendar
以便我们可以将 Date
值转换为 Time
值
extension Calendar {
func time(from date: Date) -> Time? {
let timeComponents = dateComponents([.hour, .minute], from: date)
guard let hour = timeComponents.hour,
let minute = timeComponents.minute else { return nil }
return Time(hour: hour, minute: minute)
}
}
let timeFromDate = Calendar.current.time(from: Date())
现在让我们创建一个类型来为我们管理 Time
值。请注意当您传入时间值时它是如何排序的。这会设置 next(after:)
方法,因此它可以轻松找到指定时间后的下一个时间。
struct Schedule {
let times: [Time]
init(times: [Time]) {
self.times = times.sorted()
}
func next(after time: Time) -> Time? {
times.first(where: { [=16=] > time })
}
}
综合起来
let times: [Time] = ["01:22", "15:02", "15:27", "15:52", "16:12", "16:37", "20:00", "17:02", "17:27", "17:52", "18:12", "18:32", "18:52", "19:46", "18:37", "19:17", "19:32", "19:33"]
let schedule = Schedule(times: times)
let now = Calendar.current.time(from: Date())!
let next = schedule.next(after: now)
print("Next time: \(next ?? .zero)")
或:
["01:22", "15:02", "15:27", "20:22", "20:23"]
.map { Time([=18=]) }
.filter { [=18=] > now }
.sorted()
.prefix(1)
.forEach { print([=18=]) }