Swift의 시간대 헛소리
그리고 그들이 당신을 미치게 만드는 방법
Calendar
와 함께 작업하는 것이 불가피한 때가 옵니다. 때로는 쉬울 수도 있지만 매우 까다로울 수 있으니 주의하세요 😅그럼 재미있게 즐겨봅시다 👍
서로 다른 두 값
Date
을 비교해야 한다고 가정합니다.let date1 = Date(timeIntervalSince1970: 0) // 1970-01-01 00:00:00
let date2 = Date(timeIntervalSince1970: 60 * 60 * 24) // 1970-01-02 00:00:00
func compareDates(date1: Date, date2: Date){
switch date1 {
case date2:
print("date1 and date2 represent the same point in time")
case ...date2:
print("date1 is earlier in time than date2")
case date2...:
print("date1 is later in time than date2")
default:
return
}
}
compareDates(date1: date1, date2: date2)
우리가 가정하듯이 결과는
"date1 is earlier in time than date2"
입니다. 멋진! 😃같은 날이지만 다른
TimeZone
값을 사용하고 하루의 시작을 비교하려는 경우 어떻게 됩니까? (당신만이 왜 그것이 필요한지 대답할 수 있지만, 당신이 그렇게 한다고 가정하십시오 😅)예를 들어 1971년에 베를린이나 뉴욕이 처음으로 설날을 기념했는지 알고 싶습니다.
...
func startOfDayIn(date: Date, timeZone: TimeZone) -> Date {
var calendar = Calendar.current
calendar.timeZone = timeZone
return calendar.startOfDay(for: date)
}
let date = Date(timeIntervalSince1970: 60 * 60 * 24 * 365) // 1971-01-01 00:00:00
let timeZone1 = TimeZone(secondsFromGMT: 60 * 60 * 1)! // Berlin
let start1 = startOfDayIn(date: date, timeZone: timeZone1)
let timeZone2 = TimeZone(secondsFromGMT: 60 * 60 * -8)! // New York City
let start2 = startOfDayIn(date: date, timeZone: timeZone2)
compareDates(date1: start1, date2: start2)
쉬웠어요 😁 결과적으로..
무엇을 기다립니다??
"date1 is later in time than date2"
😳🤯😱 그게 어떻게 가능해? 베를린의 하루는 뉴욕의 하루보다 일찍 시작했어야 했는데 "date1 is earlier in time than date2"
!!!그럼 이것을 조사해 봅시다. 🧐
먼저 몇 가지 startTimes를 인쇄하여 비교하겠습니다. 우리는 1월 1일을 사용했기 때문에 날짜가 1970년 이전이기 때문에 문제가 되지 않는다고 확신할 수 있습니다.
(-12...12).reversed().forEach { deviation in
let timeZone = TimeZone(secondsFromGMT: 60 * 60 * deviation)!
let start = startOfDayIn(date: date, timeZone: timeZone)
print(start, "| UTC\(deviation >= 0 ? "+" : "")\(deviation)")
}
이는 다음 목록을 제공합니다.
날짜
시간대
1970-12-31 12:00:00 +0000
UTC+12
1970-12-31 13:00:00 +0000
UTC+11
1970-12-31 14:00:00 +0000
UTC+10
1970-12-31 15:00:00 +0000
UTC+9
1970-12-31 16:00:00 +0000
UTC+8
1970-12-31 17:00:00 +0000
UTC+7
1970-12-31 18:00:00 +0000
UTC+6
1970-12-31 19:00:00 +0000
UTC+5
1970-12-31 20:00:00 +0000
표준시+4
1970-12-31 21:00:00 +0000
UTC+3
1970-12-31 22:00:00 +0000
UTC+2
1970-12-31 23:00:00 +0000
UTC+1
1971-01-01 00:00:00 +0000
표준시+0
1970-12-31 01:00:00 +0000
UTC-1
왜 우리는 다시 1970년으로 돌아갔습니까??
1970-12-31 02:00:00 +0000
UTC-2
1970-12-31 03:00:00 +0000
UTC-3
1970-12-31 04:00:00 +0000
UTC-4
1970-12-31 05:00:00 +0000
UTC-5
1970-12-31 06:00:00 +0000
UTC-6
1970-12-31 07:00:00 +0000
UTC-7
1970-12-31 08:00:00 +0000
UTC-8
1970-12-31 09:00:00 +0000
UTC-9
1970-12-31 10:00:00 +0000
UTC-10
1970-12-31 11:00:00 +0000
UTC-11
1970-12-31 12:00:00 +0000
UTC-12
좋습니다.
UTC+0
까지의 첫 번째 줄은 예상대로 표시됩니다. 그런데 왜 나머지는 잘못된 것입니까?해결책은 다소 간단합니다. 전환이 너무 많거나 너무 적습니다
TimeZone
!뉴욕 시간대
UTC-8
를 사용했을 때 날짜 값으로 "1971-01-01 00:00:00"
를 사용했습니다. 그러나 이것은 UTC+0
에 있습니다! UTC-8
의 날짜는 실제로 "1970-12-31 18:00:00 -0800"
입니다. startOfDay
를 호출하면 "1970-12-31 00:00:00 -0800"
UTC+0
에 있는 "1970-12-31 08:00:00 +0000"
를 얻습니다.이것은 결과가 실제로 정확하지만 우리의 기능은 🙈 그렇지 않다는 것을 의미합니다.
그럼 수정하자💪
func adjustedStartOfDayIn(date: Date, timeZone: TimeZone) -> Date {
var calendar = Calendar.current
calendar.timeZone = timeZone
let correctDay = date.addingTimeInterval(TimeInterval(-calendar.timeZone.secondsFromGMT()))
return calendar.startOfDay(for: correctDay)
}
let correctStart1 = adjustedStartOfDayIn(date: date, timeZone: timeZone1)
let correctStart2 = adjustedStartOfDayIn(date: date, timeZone: timeZone2)
compareDates(date1: correctStart1, date2: correctStart1)
이제 예상대로
"date1 is earlier in time than date2"
결과를 얻습니다. 😁여기서 솔루션의 핵심은
date
를 직접 사용하지 않고 특정 시간대와 UTC의 오프셋만큼 이동하여 사용하려는 시간대에서 startOfDay
를 얻는다는 것입니다.결론: 시간대를 혼동하지 마십시오!
전체 코드here를 찾을 수 있습니다.
Reference
이 문제에 관하여(Swift의 시간대 헛소리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/katharinagopp/timezone-shenanigans-in-swift-1654텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)