•
Kotlin 표준 라이브러리는 다양한 단위로 시간을 계산하고 측정할 수 있는 도구를 제공한다.
•
정확한 시간 측정은 다음과 같은 활동에 중요하다.
◦
스레드 또는 프로세스 관리
◦
통계 수집
◦
타임아웃 감지
◦
디버깅
•
기본적으로 시간은 단조로운 시간 소스를 사용하여 측정되지만 다른 시간 소스를 구성할 수도 있다.
기간 계산
•
시간의 양을 나타내기 위해 표준 라이브러리는 Duration 클래스를 제공한다.
•
Duration 은 다음의 DurationUnit 열거형 클래스에 정의된 단위로 표현될 수 있다.
◦
NANOSECONDS
◦
MICROSECONDS
◦
MILLISECONDS
◦
SECONDS
◦
MINUTES
◦
HOURS
◦
DAYS
•
Duration 은 양수, 음수, 제로, 양의 무한대, 음의 무한대를 가질 수 있다.
기간 생성
val fiveHundredMilliseconds: Duration = 500.milliseconds
val zeroSeconds: Duration = 0.seconds
val tenMinutes: Duration = 10.minutes
val negativeNanosecond: Duration = (-1).nanoseconds
val infiniteDays: Duration = Double.POSITIVE_INFINITY.days
val negativeInfiniteDays: Duration = Double.NEGATIVE_INFINITY.days
println(fiveHundredMilliseconds) // 500ms
println(zeroSeconds) // 0s
println(tenMinutes) // 10m
println(negativeNanosecond) // -1ns
println(infiniteDays) // Infinity
println(negativeInfiniteDays) // -Infinity
Kotlin
복사
•
Duration 을 생성하려면 Int, Long, Double 타입에서 사용할 수 있는 확장 속성을 이용한다.
•
예를 들어, nanoseconds, microseconds, milliseconds, seconds, minutes, hours, days 가 있다.
기간 산술
val fiveSeconds: Duration = 5.seconds
val thirtySeconds: Duration = 30.seconds
println(fiveSeconds + thirtySeconds) // 35s
println(thirtySeconds - fiveSeconds) // 25s
println(fiveSeconds * 2) // 10s
println(thirtySeconds / 2) // 15s
println(thirtySeconds / fiveSeconds) // 6.0
println(-thirtySeconds) // -30s
println((-thirtySeconds).absoluteValue) // 30s
Kotlin
복사
•
Duration 객체에 대해 기본적인 산술 연산을 수행할 수 있다.
문자열 표현 가져오기
// 초 단위로 2자리 소수점으로 출력
println(5887.milliseconds.toString(DurationUnit.SECONDS, 2)) // 5.89s
Kotlin
복사
•
Duration의 문자열 표현이 필요할 때는 .toString() 함수를 사용한다.
•
기본적으로 시간은 존재하는 각 단위를 사용하여 1h 0m 45.677s 와 같은 형식으로 보고된다.
•
출력을 구성하려면 .toString() 함수를 원하는 DurationUnit 과 소수점 자리 수를 매개변수로 사용한다.
println(86420.seconds.toIsoString()) // PT24H0M20S
Kotlin
복사
•
ISO-8601 호환 문자열을 얻으려면 toIsoString() 함수를 사용한다.
기간 변환
val thirtyMinutes: Duration = 30.minutes
println(thirtyMinutes.inWholeSeconds) // 1800
Kotlin
복사
•
Duration 을 다른 DurationUnit 으로 변환하려면 다음 속성을 사용한다.
◦
inWholeNanoseconds
◦
inWholeMicroseconds
◦
inWholeSeconds
◦
inWholeMinutes
◦
inWholeHours
◦
inWholeDays
println(270.seconds.toDouble(DurationUnit.MINUTES)) // 4.5
Kotlin
복사
•
또는 원하는 DurationUnit 을 함수 매개변수로 사용하여 다음 확장 함수를 사용할 수 있다.
기간 비교
val thirtyMinutes: Duration = 30.minutes
val halfHour: Duration = 0.5.hours
println(thirtyMinutes == halfHour) // true
Kotlin
복사
•
Duration 객체가 같은지 확인하려면 등호 연산자(==)를 사용한다.
println(3000.microseconds < 25000.nanoseconds) // false
Kotlin
복사
•
Duration 객체를 비교하려면 비교 연산자(<, >)를 사용한다.
기간을 구성 요소로 나누기
val thirtyMinutes: Duration = 30.minutes
println(thirtyMinutes.toComponents { hours, minutes, _, _ -> "${hours}h:${minutes}m" }) // 0h:30m
Kotlin
복사
•
Duration 을 시간 구성 요소로 나누고 추가 작업을 수행하려면 toComponents() 함수의 오버로드를 사용한다.
•
원하는 작업을 함수 또는 람다 표현식으로 매개변수로 추가한다.
시간 측정
•
시간의 경과를 추적하기 위해 표준 라이브러리는 다음과 같은 도구를 제공한다.
◦
코드 실행에 걸린 시간을 원하는 시간 단위로 측정한다.
◦
특정 순간을 표시한다.
◦
두 순간의 시간을 비교하고 빼기 연산을 수행한다.
◦
특정 순간 이후 얼마나 시간이 지났는지 확인한다.
◦
현재 시간이 특정 순간을 지나쳤는지 확인한다.
코드 실행 시간 측정
val timeTaken = measureTime {
Thread.sleep(100)
}
println(timeTaken) // 예: 103 ms
Kotlin
복사
•
코드 블록의 실행에 걸린 시간을 측정하려면 measureTime 인라인 함수를 사용한다.
val (value, timeTaken) = measureTimedValue {
Thread.sleep(100)
42
}
println(value) // 42
println(timeTaken) // 예: 103 ms
Kotlin
복사
•
코드 블록의 실행에 걸린 시간을 측정하고 코드 블록의 값을 반환하려면 measureTimedValue 인라인 함수를 사용한다.
순간 표시
import kotlin.time.*
fun main() {
val timeSource = TimeSource.Monotonic
val mark = timeSource.markNow()
}
Kotlin
복사
•
특정 순간을 표시하려면 TimeSource 인터페이스와 markNow() 함수를 사용하여 TimeMark 를 생성한다.
시간차 측정
val timeSource = TimeSource.Monotonic
val mark1 = timeSource.markNow()
Thread.sleep(500) // 0.5초 대기
val mark2 = timeSource.markNow()
repeat(4) { n ->
val mark3 = timeSource.markNow()
val elapsed1 = mark3 - mark1
val elapsed2 = mark3 - mark2
println("Measurement 1.${n + 1}: elapsed1=$elapsed1, elapsed2=$elapsed2, diff=${elapsed1 - elapsed2}")
}
println(mark2 > mark1) // true, mark2가 mark1보다 늦게 캡처되었기 때문
Kotlin
복사
•
같은 시간 소스에서 TimeMark 객체 간의 차이를 측정하려면 빼기 연산자를 사용한다.
•
같은 시간 소스에서 TimeMark 객체를 비교하려면 비교 연산자(<, >)를 사용한다.
기간 확인
val timeSource = TimeSource.Monotonic
val mark1 = timeSource.markNow()
val fiveSeconds: Duration = 5.seconds
val mark2 = mark1 + fiveSeconds
// 아직 5초가 지나지 않았음
println(mark2.hasPassedNow()) // false
// 6초 대기
Thread.sleep(6000)
println(mark2.hasPassedNow()) // true
Kotlin
복사
•
기한이 지났는지 또는 타임아웃이 발생했는지 확인하려면 hasPassedNow() 및 hasNotPassedNow() 확장 함수를 사용한다.
시간 소스
•
기본적으로 시간은 단조로운 시간 소스를 사용하여 측정된다.
•
단조로운 시간 소스는 앞으로만 움직이며 시간대와 같은 변동의 영향을 받지 않는다.
•
단조로운 시간의 대안은 실제 경과 시간으로 벽 시계 시간이라고도 불린다.
•
실제 경과 시간은 다른 시점을 기준으로 측정된다.
플랫폼별 기본 시간 소스
플랫폼 | 소스 |
Kotlin/JVM | System.nanoTime() |
Kotlin/JS (Node.js) | process.hrtime() |
Kotlin/JS (브라우저) | window.performance.now() 또는 Date.now() |
Kotlin/Native | std::chrono::high_resolution_clock 또는 std::chrono::steady_clock |
시간 소스 생성
•
특정 시간 소스를 사용해야 하는 경우도 있다.
object RealtimeMonotonicTimeSource : AbstractLongTimeSource(DurationUnit.NANOSECONDS) {
override fun read(): Long = SystemClock.elapsedRealtimeNanos()
}
Kotlin
복사
•
예를 들어, Android에서 System.nanoTime() 은 기기가 활성 상태일 때만 시간을 측정한다.
•
기기가 깊은 잠에 들어가면 시간을 잃게 되고 그 때 시간을 추적하려면 SystemClock.elapsedRealtimeNanos() 를 사용하는 시간 소스를 생성할 수 있다.
fun main() {
val elapsed: Duration = RealtimeMonotonicTimeSource.measureTime {
Thread.sleep(100)
}
println(elapsed) // 예: 103 ms
}
Kotlin
복사
•
그런 다음 시간 측정을 위해 해당 시간 소스를 사용할 수 있다.