[Xcode / Swift] 날짜와 시간 다루기 | Date() DateComponents()

현재 시점의 날짜와 시간 구하기

Swift 개발 문서에 따르면, Date는 어떠한 달력과 Time Zone과는 독립적인 특정 시점의 시간 포인트이다. Date Class를 생성함으로 인해서 우리가 바로 구할 수 있는 값은 다음과 같다.

init() // 현재 시점의 날짜와 시간(시스템에 찍힌)
init(timeIntervalSinceNow: TimeInterval) //현재 날짜를 기준으로 매개변수로 전달된 TimeInterval만큼 후의 시간(-값을 전달할 경우 전의 시간)
init(timeInterval: TimeInterval, since: Date) //since 매개변수로 전달된 시점의 시간에 TimeInterval만큼 후의 시간(-값을 전달할 경우 전의 시간)
init(timeIntervalSinceReferenceDate: TimeInterval) //21세기 시작 지점 2001. 1. 1 00:00:00 UTC를 기준으로 TimeInterval만큼 후의 시간
init(timeIntervalSince1970: TimeInterval) // epoch(Unix 기준 시작 시점) 1970. 1. 1 00:00:00 UTC를 기준으로 Time Interval만큼 후의 시간
import UIKit

let now = Date() //"Mar 21, 2018 at 1:37 PM"
let tomorrowFromNow = Date(timeIntervalSinceNow: 86400) //"Mar 22, 2018 at 1:37 PM"
let yesterdayFromNow = Date(timeIntervalSinceNow: -86400) //"Mar 20, 2018 at 1:37 PM"
let theDayAfterTomorrow = Date(timeInterval: 86400, since: tomorrowFromNow) //"Mar 23, 2018 at 1:37 PM"
let timeSince2001 = Date(timeIntervalSinceReferenceDate: 86400) //"Jan 2, 2001 at 9:00 AM"
let timeSince1970 = Date(timeIntervalSince1970: 86400) //"Jan 2, 1970 at 9:00 AM"

TimeInterval이란?

timeInterval은 double형의 초라고 생각하면 된다. 복잡하게 생각할 필요 없이 초단위를 넣어주면 된다. 위의 실행 코드를 보면 86400초(하루)를 이용하여 특정 시점의 시간을 구한 것을 볼 수 있다.

또한, TimeInterval을 이용하여 +, -, >, <, >=, +=, 등등 의 연산자를 활용할 수 있다. 연산자에 입력되는 파라메타는 항상 Date, TimeInterval(초) 혹은 Date, Date이어야 한다.

import UIKit

let now = Date() //"Mar 21, 2018 at 1:37 PM"

let tomorrow = now + 86400 //"Mar 22, 2018 at 5:23 PM"
let yesterday = now - 86400 //"Mar 22, 2018 at 5:23 PM"

tomorrow > yesterday // true
now == tomorrow //false

DateFormatter 활용하기

위 예시는 현재 시점을 기준으로 여러가지 연산을 초단위를 이용해서 하는 방법이었다. 그렇다면, 내가 원하는 임의의 날짜는 어떻게 만들 수 있을까. dataFormat을 정확하게 명시한 후, 아래와 같이 date(from: String) 함수를 이용하여 date값으로 바꿀 수 있다.

import UIKit

let date = DateFormatter()
date.locale = Locale(identifier: "ko_kr")
date.dateFormat = "yyyy-MM-dd"

let time = date.date(from: "2017-06-05")

또한, date값을 String으로 바꾸고자 하면 아래와 같은 흐름을 따라가면 된다.

import UIKit

let now = Date()

let date = DateFormatter()
date.locale = Locale(identifier: "ko_kr")
date.timeZone = TimeZone(abbreviation: "KST") // "2018-03-21 18:07:27"
//date.timeZone = TimeZone(abbreviation: "NZST") // "2018-03-21 22:06:39"
date.dateFormat = "yyyy-MM-dd HH:mm:ss"

let kr = date.string(from: now)

날짜 및 시간에서 사용되는 패턴과 identifier, abbreviation임으로 참조 바람.


각각의 시, 분, 초?

위의 내용으로 Date()형과 String과의 변환 관계가 조금 정리된 듯하다. 하지만 그럼, 각각의 일, 월, 시, 분, 초는 어떻게 구할 수 있을까. 여기서 사용하게 되는 것이 Calendar 구조체이다. 이 구조체를 이용하여 달력에 있는 단위(년, 월, 일 등)를 계산하고 비교할 수 있다. 이에 사용되는 핵심 Method는 dateComponents(_:from)이다.

import UIKit

let date = Date()
let calendar = Calendar.current
let components = calendar.dateComponents([.hour, .minute, .second], from: date)

현재 Calendar는 그레고리안 달력을 사용함으로, Calendar.current는 그레고리안 달력을 의미한다(let calendar = Calendar(identifier: .gregorian) 이렇게 해도 무방하다). 또한, dateComponents의 파라메타로 현재 날짜와 내가 원하는 시간의 요소(시, 분, 초)를 넘겨준다. 이 다음부터는 간단하다. enum의 요소들이 Int?형으로 되어 반환 되기 때문에, 내가 dateComponents의 파라메타로 명시하지 않았던 요소를 부르면 nil값을 반환하고, 나머지는 다 Int?값을 반환한다.

components.month //nil
components.hour //18
components.minute //24

날짜 사이 차이 구하기

날짜 각각의 요소에 접근해 보았기 때문에, 물론, 날짜가 얼마나 차이 나는지도 구할 수 있다. timeIntervalSince함수를 이용하여 interval을 구해 86400초(하루)로 나누어 구하는 방법과 아래 함수로 깔끔하게 구할 수도 있다.

func dateComponents(_ componentsSet<Calendar.Component>, from startDatetoendDate) -> DateComponents
import UIKit

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let startDate = dateFormatter.date(from:"2018-03-01")!
let endDate = dateFormatter.date(from:"2018-05-15")!

let interval = endDate.timeIntervalSince(startDate)
let days = Int(interval / 86400)

print("\(days) 차이.")

let calendar = Calendar.current
let dateGap = calendar.dateComponents([.year,.month,.day,.hour], from: startDate, to: endDate)

if case let (y?, m?, d?, h?) = (dateGap.year, dateGap.month, dateGap.day, dateGap.hour)
{
  print("\(y)\(m)개월 \(d)\(h)시간 후")
}

오늘부터 50일째 되는 날은 언제?

DateComponents에 Int?를 넣어주며 day라는 DateComponents형 변수를 만든다. calendar.date(byAdding: , to:) 함수를 활용하면 현재 날짜로부터 DataComponents의 요소만큼 더해준다.

import UIKit

let now = Date()
let calendar = Calendar.current
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"

let day = DateComponents(day: 49)
if let d100 = calendar.date(byAdding: day, to: now)
{
    print(dateFormatter.string(from: d100))
}

DateFormatter.dateStyle 관련

DateFormatter() has 5 format style options for each of Date and Time. These are:
.none .short .medium .long .full

 DATE      TIME     DATE/TIME STRING
"none"    "none"    
"none"    "short"   9:42 AM
"none"    "medium"  9:42:27 AM
"none"    "long"    9:42:27 AM EDT
"none"    "full"    9:42:27 AM Eastern Daylight Time
"short"   "none"    10/10/17
"short"   "short"   10/10/17, 9:42 AM
"short"   "medium"  10/10/17, 9:42:27 AM
"short"   "long"    10/10/17, 9:42:27 AM EDT
"short"   "full"    10/10/17, 9:42:27 AM Eastern Daylight Time
"medium"  "none"    Oct 10, 2017
"medium"  "short"   Oct 10, 2017, 9:42 AM
"medium"  "medium"  Oct 10, 2017, 9:42:27 AM
"medium"  "long"    Oct 10, 2017, 9:42:27 AM EDT
"medium"  "full"    Oct 10, 2017, 9:42:27 AM Eastern Daylight Time
"long"    "none"    October 10, 2017
"long"    "short"   October 10, 2017 at 9:42 AM
"long"    "medium"  October 10, 2017 at 9:42:27 AM
"long"    "long"    October 10, 2017 at 9:42:27 AM EDT
"long"    "full"    October 10, 2017 at 9:42:27 AM Eastern Daylight Time
"full"    "none"    Tuesday, October 10, 2017
"full"    "short"   Tuesday, October 10, 2017 at 9:42 AM
"full"    "medium"  Tuesday, October 10, 2017 at 9:42:27 AM
"full"    "long"    Tuesday, October 10, 2017 at 9:42:27 AM EDT
"full"    "full"    Tuesday, October 10, 2017 at 9:42:27 AM Eastern Daylight Time

댓글 남기기