达到小时数后将日期重置为下一个小时
reset date to next hour after top of hour is reached
我希望我的 swift 代码倒计时到最近的整点。所以如果时间是 146,用户代码应该倒数 14 分钟。现在我下面的代码倒计时到特定的日期和时间。我只希望它在应用程序 运行.
时倒计时到最近的小时
import UIKit
class ViewController: UIViewController {
@IBOutlet var timerLabel: UILabel!
var timer: Timer!
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(UpdateTime), userInfo: nil, repeats: true)
}
@objc func UpdateTime() {
let userCalendar = Calendar.current
// Set Current Date
let date = Date()
let components = userCalendar.dateComponents([.hour, .minute, .month, .year, .day], from: date)
let currentDate = userCalendar.date(from: components)!
// Set Event Date
var eventDateComponents = DateComponents()
eventDateComponents.year = 2021
eventDateComponents.month = 01
eventDateComponents.day = 01
eventDateComponents.hour = 01
eventDateComponents.minute = 00
eventDateComponents.timeZone = TimeZone(abbreviation: "GMT")
let eventDate = userCalendar.date(from: eventDateComponents)!
let timeLeft = userCalendar.dateComponents([.day, .hour, .minute, ], from: currentDate, to: eventDate)
timerLabel.text = "\(timeLeft.day!)d \(timeLeft.hour!)h \(timeLeft.minute!)m "
endEvent(currentdate: currentDate, eventdate: eventDate)
}
func endEvent(currentdate: Date, eventdate: Date) {
if currentdate >= eventdate {
timerLabel.text = "Happy New Year!"
// Stop Timer
timer.invalidate()
}
}
}
edit/update:
我的 swift 代码中的目标是达到整点。在尝试执行@Leo 的回答后,它会打印“Top of Hour”,但问题是它只执行一次。只要该应用程序处于打开状态,我就希望它每小时打印一次“Top of Hour”。所以我需要重置结束日期,这是我在
尝试做的
let date = Date()
end = date.nextHour
这不会让代码编译。所以我必须将结束变量重置为下一个小时。
无需每秒更新用户界面 10 次。事实上,它会比需要更快地耗尽设备的电池,而它应该只 运行 每分钟一次。您可以将计时器 timeInterval 更改为 1 秒,并安排它在下一个偶数秒触发。要获得下一个偶数小时和下一个偶数分钟,您可以使用 Calendar 方法
func nextDate(after date: Date, matching components: DateComponents, matchingPolicy: Calendar.MatchingPolicy, repeatedTimePolicy: Calendar.RepeatedTimePolicy = .first, direction: Calendar.SearchDirection = .forward) -> Date?
只需创建两个扩展日期的计算属性并为分钟或纳秒分量传递零:
extension Date {
var nextHour: Date {
Calendar.current.nextDate(after: self, matching: DateComponents(minute: 0), matchingPolicy: .strict)!
}
var nextSecond: Date {
Calendar.current.nextDate(after: self, matching: DateComponents(nanosecond: 0), matchingPolicy: .strict)!
}
var minute: Int {
Calendar.current.component(.minute, from: self)
}
}
现在向您的视图控制器添加一个 属性 以保留对结束日期的引用。请注意,无需将计时器声明为可选:
var end: Date?
var timer = Timer()
并创建 DateComponentsFormatter 以创建剩余时间的本地化描述:
extension Formatter {
static let minutesRemaining: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.formattingContext = .standalone
formatter.unitsStyle = .short
formatter.allowedUnits = [.minute, .second]
formatter.includesTimeRemainingPhrase = true
return formatter
}()
}
现在您只需设置结束日期并安排您的计时器在下一个偶数分钟触发:
override func viewDidLoad() {
super.viewDidLoad()
// get the current date
let date = Date()
// set the end date
end = date.nextHour
// schedule the timer to fire at the next even second and set its interval to 1 second
timer = .init(fireAt: date.nextSecond, interval: 1, target: self, selector: #selector(updateUI), userInfo: nil, repeats: true)
RunLoop.main.add(timer, forMode: .common)
updateUI()
}
@objc func updateUI() {
if Date().minute == 0 || Date() > end {
end = Date().nextHour
timerLabel.text = "beginning of hour"
print("beginning of hour")
} else {
// update the remaining time (for a perfect sync we need to subtract a second from the current time)
let text = Formatter.minutesRemaining.string(from: Date().addingTimeInterval(-1), to: end) ?? ""
timerLabel.text = text
print(text)
}
}
我希望我的 swift 代码倒计时到最近的整点。所以如果时间是 146,用户代码应该倒数 14 分钟。现在我下面的代码倒计时到特定的日期和时间。我只希望它在应用程序 运行.
时倒计时到最近的小时import UIKit
class ViewController: UIViewController {
@IBOutlet var timerLabel: UILabel!
var timer: Timer!
override func viewDidLoad() {
super.viewDidLoad()
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(UpdateTime), userInfo: nil, repeats: true)
}
@objc func UpdateTime() {
let userCalendar = Calendar.current
// Set Current Date
let date = Date()
let components = userCalendar.dateComponents([.hour, .minute, .month, .year, .day], from: date)
let currentDate = userCalendar.date(from: components)!
// Set Event Date
var eventDateComponents = DateComponents()
eventDateComponents.year = 2021
eventDateComponents.month = 01
eventDateComponents.day = 01
eventDateComponents.hour = 01
eventDateComponents.minute = 00
eventDateComponents.timeZone = TimeZone(abbreviation: "GMT")
let eventDate = userCalendar.date(from: eventDateComponents)!
let timeLeft = userCalendar.dateComponents([.day, .hour, .minute, ], from: currentDate, to: eventDate)
timerLabel.text = "\(timeLeft.day!)d \(timeLeft.hour!)h \(timeLeft.minute!)m "
endEvent(currentdate: currentDate, eventdate: eventDate)
}
func endEvent(currentdate: Date, eventdate: Date) {
if currentdate >= eventdate {
timerLabel.text = "Happy New Year!"
// Stop Timer
timer.invalidate()
}
}
}
edit/update:
我的 swift 代码中的目标是达到整点。在尝试执行@Leo 的回答后,它会打印“Top of Hour”,但问题是它只执行一次。只要该应用程序处于打开状态,我就希望它每小时打印一次“Top of Hour”。所以我需要重置结束日期,这是我在
尝试做的let date = Date() end = date.nextHour
这不会让代码编译。所以我必须将结束变量重置为下一个小时。
无需每秒更新用户界面 10 次。事实上,它会比需要更快地耗尽设备的电池,而它应该只 运行 每分钟一次。您可以将计时器 timeInterval 更改为 1 秒,并安排它在下一个偶数秒触发。要获得下一个偶数小时和下一个偶数分钟,您可以使用 Calendar 方法
func nextDate(after date: Date, matching components: DateComponents, matchingPolicy: Calendar.MatchingPolicy, repeatedTimePolicy: Calendar.RepeatedTimePolicy = .first, direction: Calendar.SearchDirection = .forward) -> Date?
只需创建两个扩展日期的计算属性并为分钟或纳秒分量传递零:
extension Date {
var nextHour: Date {
Calendar.current.nextDate(after: self, matching: DateComponents(minute: 0), matchingPolicy: .strict)!
}
var nextSecond: Date {
Calendar.current.nextDate(after: self, matching: DateComponents(nanosecond: 0), matchingPolicy: .strict)!
}
var minute: Int {
Calendar.current.component(.minute, from: self)
}
}
现在向您的视图控制器添加一个 属性 以保留对结束日期的引用。请注意,无需将计时器声明为可选:
var end: Date?
var timer = Timer()
并创建 DateComponentsFormatter 以创建剩余时间的本地化描述:
extension Formatter {
static let minutesRemaining: DateComponentsFormatter = {
let formatter = DateComponentsFormatter()
formatter.formattingContext = .standalone
formatter.unitsStyle = .short
formatter.allowedUnits = [.minute, .second]
formatter.includesTimeRemainingPhrase = true
return formatter
}()
}
现在您只需设置结束日期并安排您的计时器在下一个偶数分钟触发:
override func viewDidLoad() {
super.viewDidLoad()
// get the current date
let date = Date()
// set the end date
end = date.nextHour
// schedule the timer to fire at the next even second and set its interval to 1 second
timer = .init(fireAt: date.nextSecond, interval: 1, target: self, selector: #selector(updateUI), userInfo: nil, repeats: true)
RunLoop.main.add(timer, forMode: .common)
updateUI()
}
@objc func updateUI() {
if Date().minute == 0 || Date() > end {
end = Date().nextHour
timerLabel.text = "beginning of hour"
print("beginning of hour")
} else {
// update the remaining time (for a perfect sync we need to subtract a second from the current time)
let text = Formatter.minutesRemaining.string(from: Date().addingTimeInterval(-1), to: end) ?? ""
timerLabel.text = text
print(text)
}
}