티스토리 뷰
안녕하세요 :) Zedd입니다.
< 왕초보를 위한 Codable - CodingKey >글에서 DateDecodingStrategy의 각 Strategy가 어떤 역할?...어떤 포맷??인지 궁금해져서....
위 글을 읽고오시면 이해가 더 잘되실수도
Date와 관련된 Strategy는 DateDecodingStrategy말고도 DateEncodingStrategy도 있어요!!! 저는 Decoding으로 설명할거에요 :) Encoding에서도 똑같으니..!!! 각 Strategy가 어떤 역할을 하는건지만 보면 될 것 같습니당
DateDecodingStrategy
저번시간에 올렸듯이
DateDecodingStrategy에는 굉장히 많은 전략이 있습니다.
DateDecodingStrategy라는 enum에 여러 case들이 있는 걸 볼 수 있죠? 밑에 더 있는데..캡쳐가 안대씀
그럼 하나하나 볼게요 XD
● deferredToDate
이건 default Strategy에요!! 딱히..설명은 없습니다...ㅎㅎ
● secondsSince1970
이건 1970년 1월 1일 자정부터 UTC로 초단위로 date를 인코딩/디코딩 하는 전략이에요.
( UTC : Coordinated Universal Time, 협정세계시. 1972년 1월 1일부터 시행된 국제표준시에요. UTC는 그리니치 평균시(Greenwich Mean Time, GMT로 불리기도 하는데, UTC와 GMT는 초의 소숫점단위에서만 차이가 나기 때문에 혼용되어서 사용되곤 한대요 :) 기술적인 표기에서는 UTC가 사용된다고 합니다. GMT는 아시는 분들도 많겠지만, 런던을 기점, 웰링턴을 종점으로 하는 UTC의 빠른시간대입니다. 공식표현은 UTC가 맞아요. )
그러니까 쉽게 생각하세요! 아 ㅇㅇ 1970년 1월 1일 00:00:00부터 몇초가 경과했는지를 나타내는 겁니다.
예를들어 1515083815. 이런 숫자죠. (숫자는 위키백과에서 가져왔어요! https://ko.wikipedia.org/wiki/유닉스_시간)
< 왕초보를 위한 Codable - CodingKey >글에서 Date는
1 | "birth_date" : "2017-01-22T23:16:50+0000" | cs |
이런 포맷이었는데(iso8601전략을 사용했었죠?), 만약
1 | "birth_date" : 1515083815 | cs |
이런 포맷이었다고 생각해봅시다.
그러면 iso8601전략을 사용하면 안되고!!!!!! secondsSince1970전략을 사용해야겠죠?
1 2 3 4 5 6 7 | let decoder = JSONDecoder() decoder.dateDecodingStrategy = .secondsSince1970 ....(중략) print(myPerson.birthday)//2018-01-04 16:36:55 +0000 | cs |
이렇게 해주면!! 이렇게 print가 된답니다.
알아서 이쁘게 변환해서 보여주네요.
디코딩 하는과정은 < 왕초보를 위한 Codable >이나 < 왕초보를 위한 Codable - CodingKey >에서 설명했으니 중략하도록 할게요 :)
● millisecondsSince1970
위에랑 상당히 비슷하죠? 이건 그냥 millisecond단위로 날짜를 인코딩/디코딩 할거냐. 이거에요.
second에서 1000만 곱해주면 되겠죠? 밀리세컨드니까 ㅇㅇ
1 | "birth_date" : 1515083815000.0 | cs |
위에서 사용했던 1515083815에 1000만 곱해줬어요. 소수점을 그냥 넣어봤는데 소수점을 넣든 안넣든 상관없습니다.
둘다 잘 디코딩해줘요!!!
이렇게 값을 해놓고 secondsSince1970라고 전략을 지정해놓으면..안되겠죠?
정말 이상한 값이 나온답니다 :)..
(위 값으로 하면 49981-02-04 07:16:40 +0000...)
1 2 3 4 5 6 7 | "birth_date" : 1515083815000.0 let decoder = JSONDecoder() decoder.dateDecodingStrategy = .millisecondsSince1970 print(myPerson.birthday)//2018-01-04 16:36:55 +0000 | cs |
이렇게 잘 나온답니다 :)
● iso8601
iso8601은 < 왕초보를 위한 Codable - CodingKey >글에서 봤죠?
이런식의 포맷이 iso8601포맷이라고 할 수 있어요.
iso8601은 날짜와 시간에 관련된 데이터 교환을 다루는 국제 표준이라고 합니다 국제표준화기구(ISO)에 의해 공표되었으며, 1988년에 처음으로 공개되었다고 해요 :)
iso8601에는 표기법이 여러개가 있는데,
연월일표기법(YYYY-MM-DD),연과 연중 일수 표기법(YYYY-DDD), 연과 주의 주중 일수 표기법(YYYY-Www-D)이런것들이 있다고 하는데
일단 안먹힙니다...예를들어 2018-01-23이렇게 지정하고 iso8601로 전략을 지정해줘도 인식을 못해요 ㅠㅠ
위 그림의 포맷이어야만 인식을...합니다.
1 | "birth_date" : "1981-02-22T09:00:00+0900" | cs |
이렇게 뒤에 시간대를 붙히는 것도 가능해요!!(인식이 된다는 말)
1 2 3 4 5 6 7 | "birth_date" : "1981-02-22T09:00:00+0900" let decoder = JSONDecoder() decoder.dateDecodingStrategy = .iso8601 print(myPerson.birthday)//1981-02-22 00:00:00 +0000 | cs |
이렇게 잘 출력이 됩니다 :)
● formatted(DateFormatter)
"Date를 주어진 포맷터에 의해 파싱된 문자열로 디코드 합니다."
라는게 이 case의 정의입니다!
오 뭔가 엄청 강력해보이는데..
만약에!!! 제가
1 | "birth_date" : "2018-01-23" | cs |
이러한 포맷으로 Date가 있다고 생각해볼게요.
이거 어케 인코딩/디코딩할거냐 ㅡㅡ어쩔거냐 ㅡㅡ
이럴때 바로 formatted(DateFormatter) 전략을 사용하면 됩니다.
1 | "birth_date" : "2018-01-23" | cs |
DateFormatter라는게 있는건 아시죠?
1 | let formatter = DateFormatter() | cs |
이런거...이걸 저 파라미터에 넣어주면(formatted(DateFormatter)) 나만의 포맷을 인식하게 할 수 있다~이거죠
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | extension DateFormatter { static let yyyyMMdd: DateFormatter = { let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd" formatter.calendar = Calendar(identifier: .iso8601) formatter.timeZone = TimeZone(secondsFromGMT: 0) formatter.locale = Locale(identifier: "ko_kr") return formatter }() } | cs |
이렇게 DateFormatter를 extension해서!!
1 | formatter.dateFormat = "yyyy-MM-dd" | cs |
이게 핵심이죠.
1 | "birth_date" : "2018-01-23" | cs |
제 JSON이 이런 포맷이니까요!!! 년도가 나오고, 월-일
이제!!
1 2 3 4 5 6 7 | "birth_date" : "2018-01-23" let decoder = JSONDecoder() decoder.dateDecodingStrategy = .formatted(DateFormatter.yyyyMMdd) print(myPerson.birthday)//2018-01-23 00:00:00 +0000 | cs |
파라미터에 우리가 만든 fomatter를 넣으면 이런식으로 잘!!!나오게 되는거죠. XD
1 | formatter.dateFormat = "yyyy-MM-dd HH:mm:ss" | cs |
DateFormatter를 이렇게 바꾸게되면
1 2 3 4 5 6 7 | "birth_date" : "2018-01-23 18:15:32" let decoder = JSONDecoder() decoder.dateDecodingStrategy = .formatted(DateFormatter.yyyyMMdd) print(myPerson.birthday)//2018-01-23 18:15:32 +0000 | cs |
이런식으로 할 수 있는거죠 :)
● custom((Decoder) throws -> Date)
마지막입니다 :) 커스텀! 뭔가 사용자정의? 그런 것 같네요.
사용자정의 함수(클로져)를 호출하여 사용자 지정 Date포맷을 지정하는 전략이에요.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in let container = try decoder.singleValueContainer() let dateStr = try container.decode(String.self) var date: Date? if dateStr.count == 10 { let formatter = DateFormatter() formatter.dateFormat = "yyyy-MM-dd" date = formatter.date(from: dateStr)! } return date! }) | cs |
이런식으로?........여기에 올라온 예제인데, 음..이렇게 카운트로 세지 말고도 다른방법으로 하면 더 효율적이겠죠? 예를들어 여기처럼 아예 DateDecodingStrategy를 extension하는 방식? 이 코드는 엄청 길어서...위 코드를 가져왔는데
일단 custom이라는 case를 어떻게 활용하는지에 대해서만 보시면 될 것 같아요!!!!
아무튼 DateDecodingStrategy를 이해하는데 도움이 되었으면 좋겠습니다.
틀린 부분이 있다면 댓글이나 PC화면 오른쪽 하단에 있는 채널서비스로 메세지 주세요 :)
안녕!!
출처 :
http://dinesql.blogspot.kr/2015/05/sql-server-brain-basher-of-week-010.html
https://useyourloaf.com/blog/swift-codable-with-custom-dates/
'Swift' 카테고리의 다른 글
Swift4.1 ) flatMap -> compactMap (2) | 2018.03.11 |
---|---|
Swift ) API Design Guidelines (0) | 2018.01.25 |
Swift ) 왕초보를 위한 Codable - CodingKey (5) | 2018.01.23 |
Swift ) NSCountedSet (2) | 2018.01.22 |
Swift ) Access Control(접근제어) - (2) (1) | 2018.01.17 |
- ios 13
- swift delegate
- Xcode
- swift3
- Combine
- swift tutorial
- 피아노
- 스위프트
- 스위프트 문법
- Swift
- np-hard
- swift sort
- WKWebView
- actor
- IOS
- swift array
- 제이슨 파싱
- swift 공부
- 회고
- WidgetKit
- FLUTTER
- Accessibility
- UIBezierPath
- np-complete
- Git
- WWDC
- github
- SwiftUI
- fastlane
- iOS delegate
- Total
- Today
- Yesterday