공부/iOS

[Swift] Date formatted, FormatStyle로 날짜 출력하기

안토니1 2023. 7. 19. 16:50

formatted 소개

formatted는 날짜나 시간에 대해서 간편하게 문자열 형태로 생성하게 도와주는 인스턴스 메소드입니다.

iOS15부터 지원하며 기존 swift에서 Date를 다루기 위해 사용해왔던 DateFormatter 보다 훨신 간단하게 날짜를 다룰 수 있습니다.

(ios App Dev tutorial로 UIKit 공부를 하다가 발견하여 공부하게 되었습니다.)

5번째 줄을 보면 formatted(date: .omitted, time: .shortened)로 사용된 것을 확인할 수 있는데요.

사용할 수 있는 옵션은 다음과 같습니다.

  date(ko) date(us)
abbreviated 2023년 7월 19일 Jan 17, 2021,
complete 2023년 7월 19일 수요일 Sunday, January 17, 
long
2023년 7월 19일 January 17, 2021, 
numeric 7/19/2023 1/17/2021,
omitted
X X
  time(ko) time(us)
complete 오후 2:54:54 GMT+9 4:03:12 PM CST
shortened 수요일 오후 2:54 2021, 4:03 PM
standard 오후 2:54:54 2021, 4:03:12 PM
omitted X X

기존 dateFormatter를 선언해 어떻게 출력할지 직접 치지 않아도 간편하게 날짜를 출력할 수 있습니다.

만약 이 이외의 옵션이 필요한 경우에는 어떻게 될까요? 직접 만들면 됩니다!

 

FormatStyle 소개

포멧 만들기

FormatStyle은 날짜 인스턴스의 Locale에 해당하는 문자열을 생성하고,

날짜 및 시간 문자열을 날짜 인스턴스로 변환해주는 Struct 입니다.

순서나 포멧을 다르게 변경하고 싶다면 직접 커스텀하는 방법이 있습니다.

let myFormat = Date.FormatStyle()
    .year(.defaultDigits)
    .month(.abbreviated)
    .day(.twoDigits)
    .hour(.defaultDigits(amPM: .abbreviated))
    .minute(.twoDigits)
    .timeZone(.identifier(.long))
    .era(.wide)
    .dayOfYear(.defaultDigits)
    .weekday(.abbreviated)
    .week(.defaultDigits)
    .locale(Locale(identifier: "en_US"))

print(date.formatted(myFormat))

// ko_KR: 서기 2023년 7월 19일 (수) (주: 29) 오후 3:54 Asia/Seoul
// en_US: Wed, Jul 19, 2023 Anno Domini (week: 29) at 3:54 PM Asia/Seoul

 

Date.FormatStyle의 인스턴스를 전달하는 Date의 인스턴스에서 .formatted 메서드를 호출합니다.

깔끔하게 선언형 형태로 FormatStyle을 만들어 줄 수 있습니다.

위에서 formatted에서 사용하지 못했던 locale이나 timeZone을 쓸 수 있다는 점이 매력적이네요.

기존에 있었던 DateFormatter와 비슷한

 

Parsing Dates and Times

let inputString = "Archive for month 8, archived on day 23 - complete."
let strategy = Date.ParseStrategy(format: "Archive for month \(month: .defaultDigits), archived on day \(day: .twoDigits) - complete.", locale: Locale(identifier: "en_US"), timeZone: TimeZone(abbreviation: "CDT")!)
if let date = try? Date(inputString, strategy: strategy) {
   print(date.formatted()) // "Aug 23, 2000 at 12:00 AM"
}

문자열 형태를 이렇게 쉽게 파싱이 가능하다니...

매번 알고리즘 문자열 문제 풀듯 직접 파싱했었는데 이렇게 간단한 방법이 있는줄 몰랐네요😱

입력이 문장 형태로 들어오더라도 이처럼 Date.ParseStrategy를 사용하면 특정 부분만 따올 수 있습니다.

 

또한 strategy에는 위에서 만들었던 FormatStyle를 사용할 수도 있습니다.

let dateString = Date().formatted(myFormat)
// Wed, Jul 19, 2023 Anno Domini (week: 29) at 4:19 PM Asia/Seoul

if let anniversary = try? Date(dateString, strategy: myFormat) {
    print(anniversary.formatted(date: .abbreviated, time: .shortened))
    //2023년 7월 19일 오후 4:19
} else {
    print("Can't parse string into date with this format.")
}

(위에서 만들었던 myFormat과 해당 결과를 재활용 해줍니다..)

만약 "Wed, Jul 19, 2023 Anno Domini (week: 29) at 4:19 PM Asia/Seoul"

이러한 형태로 문자열이 들어왔다면 해당하는 포멧에 맞게 Date를 파싱해줄 수 있습니다. 

이렇게 간단하게 String 형태의 date 문자열을 손쉽게 Date 타입으로 파싱해줍니다.

 

정리

오늘 공부했던 formatter와 FormatStyle을 활용하면 Date 다루기가 정말 쉬울 것 같습니다.

특히나 Date() -> String, String -> Date() 과정이 너무 쉽게 가능해 놀랐습니다.

기존의 DateFormatter로 충분히 가능한 부분이지만 앞으로는 이와같은 선언형 형태의 코드로 점차 바뀌어나갈 것 같습니다!

 

여담으로 ios App Dev tutorial로 UIKit 공부를 하다 발견했던 내용이지만 이게 정말 튜토리얼이 맞나 싶네요 ㅋㅋㅋㅋ

처음보는 내용을 당연하다는듯 툭 던지고 넘어가는데 세렝게티 사자버전 튜토리얼인가봅니다😂

 

몰랐던 내용을 정리할겸 포스트를 오랜만에 작성해보았습니다.

이번건 정말 유용할 것 같아서 공유하고 싶었거든요.😁