Tìm chênh lệch tính bằng giây giữa các NSDates dưới dạng số nguyên bằng Swift


96

Tôi đang viết một đoạn mã trong đó tôi muốn tính thời gian một nút được nhấn. Để làm điều đó, tôi đã ghi lại NSDate()thời điểm nút được nhấn và thử sử dụng timeIntervalSinceDatechức năng khi nút được nhả. Điều đó dường như hoạt động nhưng tôi không thể tìm thấy bất kỳ cách nào để in kết quả hoặc chuyển nó thành một số nguyên.

var timeAtPress = NSDate() 

@IBAction func pressed(sender: AnyObject) {
    println("pressed")
    timeAtPress = NSDate()
}

@IBAction func released(sender: AnyObject) {
    println("released")
    var elapsedTime = NSDate.timeIntervalSinceDate(timeAtPress)
    duration = ???
}

Tôi đã thấy một vài câu hỏi tương tự, nhưng tôi không biết C nên tôi đã rất khó hiểu câu trả lời được đưa ra. Nếu có cách nào hiệu quả hơn để tìm hiểu khoảng thời gian mà nút được nhấn, tôi sẵn sàng tiếp nhận các đề xuất. Cảm ơn trước.

Câu trả lời:


211

Nỗ lực tính toán của bạn elapsedTimekhông chính xác. Trong Swift 3, nó sẽ là:

let elapsed = Date().timeIntervalSince(timeAtPress)

Lưu ý ()sau khi Datetham khảo. Khởi Date()tạo đối tượng ngày tháng mới, rồi timeIntervalSincetrả về chênh lệch thời gian giữa đối tượng đó và timeAtPress. Điều đó sẽ trả về một giá trị dấu phẩy động (về mặt kỹ thuật, a TimeInterval).

Nếu bạn muốn Intgiá trị đó được cắt ngắn thành một giá trị, bạn chỉ có thể sử dụng:

let duration = Int(elapsed)

Và, BTW, định nghĩa của bạn về timeAtPressbiến không cần phải khởi tạo một Dateđối tượng. Tôi cho rằng bạn dự định:

var timeAtPress: Date!

Điều đó định nghĩa biến là một Datebiến ( một biến không được bao bọc hoàn toàn), nhưng có lẽ bạn sẽ trì hoãn việc khởi tạo thực tế của biến đó cho đến khi pressedđược gọi.


Ngoài ra, tôi thường sử dụng CFAbsoluteTimeGetCurrent(), ví dụ:

var start: CFAbsoluteTime!

Và khi tôi muốn thiết lập startTime, tôi làm như sau:

start = CFAbsoluteTimeGetCurrent()

Và khi tôi muốn tính số giây đã trôi qua, tôi làm như sau:

let elapsed = CFAbsoluteTimeGetCurrent() - start

Cần lưu ý rằng CFAbsoluteTimeGetCurrenttài liệu cảnh báo chúng tôi:

Các cuộc gọi lặp đi lặp lại đến hàm này không đảm bảo kết quả tăng đơn điệu. Thời gian hệ thống có thể giảm do đồng bộ hóa với tham chiếu thời gian bên ngoài hoặc do người dùng thay đổi đồng hồ rõ ràng.

Điều này có nghĩa là nếu bạn không đủ may mắn để đo thời gian đã trôi qua khi một trong những điều chỉnh này diễn ra, bạn có thể dẫn đến việc tính toán thời gian đã trôi qua không chính xác. Điều này cũng đúng cho NSDate/ Datetính toán. An toàn nhất là sử dụng mach_absolute_timephép tính dựa trên (dễ thực hiện nhất với CACurrentMediaTime):

let start = CACurrentMediaTime()

let elapsed = CACurrentMediaTime() - start

Điều này sử dụng mach_absolute_time, nhưng tránh một số phức tạp được nêu trong Hỏi và Đáp kỹ thuật QA1398 .

Tuy nhiên, hãy nhớ rằng CACurrentMediaTime/ mach_absolute_timesẽ được đặt lại khi thiết bị được khởi động lại. Vì vậy, điểm mấu chốt, nếu bạn cần tính toán chính xác thời gian đã trôi qua khi ứng dụng đang chạy, hãy sử dụng CACurrentMediaTime. Nhưng nếu bạn định tiết kiệm thời gian bắt đầu này trong bộ nhớ liên tục mà bạn có thể nhớ lại khi ứng dụng được khởi động lại vào một ngày nào đó trong tương lai, thì bạn phải sử dụng Datehoặc CFAbsoluteTimeGetCurrentvà chỉ sống với bất kỳ điểm không chính xác nào có thể mắc phải.


4
Wow, cảm ơn Rob! Câu trả lời của bạn rất hữu ích và dễ hiểu. Tôi thực sự đánh giá cao mẹo về CFAbsoluteTime. Tôi chắc chắn sẽ sử dụng nó!
Erik

thứ nguyên cho timeIntervalSinceDate là gì?
eugene

Nó trả về a TimeInterval, được đo bằng giây.
Rob

22

NSDate () và NSCalendar () có vẻ là một lựa chọn tốt. Sử dụng tính toán lịch và để phần toán học thực tế vào khuôn khổ. Đây là một ví dụ nhanh về việc lấy giây giữa haiNSDate()

let startDate = NSDate()
let endDate = NSDate()
let calendar = NSCalendar.currentCalendar()
let dateComponents = calendar.components(NSCalendarUnit.CalendarUnitSecond, fromDate: startDate, toDate: endDate, options: nil)
let seconds = dateComponents.second
println("Seconds: \(seconds)")

Vì một số lý do, điều này luôn trả về 0 cho tôi mặc dù các ngày cách nhau một giờ.
Markymark

10

Theo câu trả lời của Freddy, đây là chức năng trong nhanh 3:

let start = Date()
let end = Date(timeIntervalSince1970: 100)
let calendar = Calendar.current
let unitFlags = Set<Calendar.Component>([ .second])
let datecomponents = calendar.dateComponents(unitFlags, from: start, to: end)
let seconds = datecomponents.second
print(String(describing: seconds))

1
Cảm ơn @LagMaster. Rất vui khi thấy swift đang loại bỏ tiền tố NS.
Freddy

4

Swift 5

let differenceInSeconds = Int(endDate.timeIntervalSince(startDate))

0

Đây là cách bạn có thể nhận được sự khác biệt trong phiên bản mới nhất của Swift 3

let calendar = NSCalendar.current
var compos:Set<Calendar.Component> = Set<Calendar.Component>()
compos.insert(.second)
compos.insert(.minute)
let difference = calendar.dateComponents(compos, from: fromDate, to: toDate)
print("diff in minute=\(difference.minute!)") // difference in minute
print("diff in seconds=\(difference.second!)") // difference in seconds

Tham khảo: Nhận sự khác biệt giữa hai NSDates trong (tháng / ngày / giờ / phút / giây)


-1

Swift 5

    let startDate = Date()
    let endDate = Date()
    let calendar = Calendar.current
    let dateComponents = calendar.compare(startDate, to: endDate, toGranularity: .second)
    let seconds = dateComponents.rawValue
    print("Seconds: \(seconds)")

2
Điều này không cung cấp sự khác biệt trong số giây trong mã mà chỉ sau đó cho dù bắt đầu lớn hơn hay không.
Arun K

-6

Đối với Swift 3 giây giữa 2 thời gian tính bằng "hh: mm"

func secondsIn(_ str: String)->Int{
    var strArr = str.characters.split{$0 == ":"}.map(String.init)
    var sec = Int(strArr[0])! * 3600
    var sec1 = Int(strArr[1])! * 36
    print("sec")
    print(sec+sec1)
    return sec+sec1

}

Sử dụng

var sec1 = secondsIn(shuttleTime)
var sec2 = secondsIn(dateToString(Date()))
print(sec1-sec2)

Câu trả lời này không liên quan đến câu trả lời của op.
Tomasz Nazarenko
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.