Swiftを使用して整数としてNSDates間の秒単位の違いを見つける


96

ボタンを押し続けた時間を計測したいコードを書いています。そのためNSDate()に、ボタンが押されたときを記録し、ボタンが離されたときにそのtimeIntervalSinceDate機能を使用してみました。うまくいくようですが、結果を出力したり、整数に切り替えたりする方法が見つかりません。

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 = ???
}

同様の質問をいくつか見ましたが、Cがわからないので、与えられた答えを理解するのに苦労しました。ボタンが押された時間を知るためのより効率的な方法がある場合は、提案を受け付けています。前もって感謝します。

回答:


211

計算の試みelapsedTimeは正しくありません。Swift 3では、次のようになります。

let elapsed = Date().timeIntervalSince(timeAtPress)

参照の()後に注意してDateください。Date()新しい日付オブジェクトをインスタンス化した後、timeIntervalSinceそのとの間の時間差を返しますtimeAtPress。これは浮動小数点値(技術的にはTimeInterval)を返します。

それをInt値に切り捨てたい場合は、次のように使用できます:

let duration = Int(elapsed)

ところで、timeAtPress変数の定義では、Dateオブジェクトをインスタンス化する必要はありません。私はあなたが意図したと思います:

var timeAtPress: Date!

これは、変数をDate変数(暗黙的にアンラップされた変数)として定義しますが、pressed呼び出されるまで、その変数の実際のインスタンス化をおそらく延期します。


または、私はよく使用しますCFAbsoluteTimeGetCurrent()

var start: CFAbsoluteTime!

そしてを設定したいときstartTimeは、次のようにします。

start = CFAbsoluteTimeGetCurrent()

経過秒数を計算する場合は、次のようにします。

let elapsed = CFAbsoluteTimeGetCurrent() - start

CFAbsoluteTimeGetCurrentドキュメントが私たちに警告していることは注目に値します:

この関数を繰り返し呼び出しても、単調に増加する結果は保証されません。システム時刻は、外部の時刻参照との同期またはユーザーによる明示的な時計の変更が原因で減少する場合があります。

これは、これらの調整の1つが行われたときに経過時間を測定するのに不幸な場合、誤った経過時間の計算で終わる可能性があることを意味します。これはNSDate/ Date計算にも当てはまります。mach_absolute_timeベースの計算を使用するのが最も安全です(で最も簡単に実行できますCACurrentMediaTime)。

let start = CACurrentMediaTime()

そして

let elapsed = CACurrentMediaTime() - start

これはを使用しますmach_absolute_timeが、テクニカルQ&A QA1398で概説されている複雑さの一部を回避します。

ただし、デバイスを再起動するとCACurrentMediaTime/ mach_absolute_timeがリセットされることに注意してください。つまり、アプリの実行中に正確な経過時間の計算が必要な場合は、を使用しますCACurrentMediaTime。ただし、この開始時間を永続的なストレージに保存して、アプリを将来再起動したときに思い出すことができるようにするDate場合はCFAbsoluteTimeGetCurrent、またはを使用する必要があります。


4
わあ、ロブに感謝!あなたの答えは非常に役に立ち、理解しやすかったです。CFAbsoluteTimeについてのヒントを本当に感謝しています。絶対に使います!
エリック

timeIntervalSinceDateのディメンションは何ですか?
eugene 2015年

TimeInterval秒単位で測定されるを返します。
Rob

22

NSDate()とNSCalendar()は良い選択のように思えます。カレンダー計算を使用し、実際の数学の部分はフレームワークに任せます。2つの間の秒数を取得する簡単な例を次に示しますNSDate()

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)")

何らかの理由で、日付が1時間離れていても、これは常に0を返します。
Markymark

10

フレディの答えによると、これはSwift 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
@LagMasterに感謝します。SwiftがNS接頭辞を廃止するのを見て嬉しいです。
フレディ

4

スウィフト5

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

0

これは、最新バージョンの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

参照:(月/日/時間/分/秒)で2つのNSDateの差を取得する


-1

スウィフト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
これは、開始が大きいかどうかに関係なく、コードの秒単位の違いを提供しません。
アルンK

-6

「hh:mm」の2つの時間の間のSwift 3秒

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

}

使用法

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

この答えは、オペレーションの答えとは無関係です。
Tomasz Nazarenko 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.