`Date`는 단일 시간, `Calendar`는 달력 시스템과 관련된 연산 및 정보(e.g 연도, 월)를 다루는 구조체
<br>
## Date
>날짜와 시간을 처리하고 관리하기 위한 구조체
<br>
#### Date 사용법
- `Date`는 어떤 특정한 달력체계나 시간대에 의존하지 않고, **단일한 시간 지점**을 나타내는데 사용된다.
- `Date`는 어떤 절대적인 기준 날짜를 기준으로 상대적인 시간 간격을 표현한다.
- `Date` 구조체는 날짜를 비교하거나 두 날짜 사이의 시간 간격을 계산하는 등의 작업을 수행하기 위한 다양한 메서드를 제공한다.
- `Date` 값을 `DateFormatter`를 사용하여 로컬화된 문자열로 변환하거나, `Calendar`를 사용하여 달력 기능을 수행할 수 있다.
- Swift의 `Date`는 Objective-C에서 사용되는 `NSDate` 클래스와 상호 운용이 가능하며, 코드 내에서 서로 교환해서 사용할 수 있다.
<br>
#### 주요 메서드
###### 1. 현재 날짜 및 시간 얻기
```swift
let currentDate = Date()
```
- 2023-02-01 18:00:20 +0000 형태
<br>
###### 2. 날짜 및 시간 연산
```swift
let futureDate = currentDate.addingTimeInterval(3600) // 현재 시간으로부터 1시간 후(second로 계산)
let pastDate = currentDate.addingTimeInterval(-3600) // 현재 시간으로부터 1시간 전
let timeDifference = futureDate.timeIntervalSince(currentDate) // 두 날짜 간의 시간 간격
```
- **`addingTimeInterval(_:)`**
- `Date`에 지정된 시간 간격을 더해 새로운 `Date` 값을 생성하는 메서드
- 파라미터 `timeInterval`은 초 단위임
- **`timeIntervalSince(_:)`**
- 두 `Date` 간의 시간 간격을 초 단위로 반환하는 메서드
<br>
###### 3. `Date` 포맷팅
```swift
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let formattedDate = dateFormatter.string(from: currentDate)
```
- 포맷 패턴 예시
- yyyy-MM-dd HH:mm:ss: 년, 월, 일, 시간, 분, 초
- E, d MMM yyyy HH:mm:ss Z: 요일, 일, 월의 약어, 년, 시간, 분, 초, 시간대
- MMMM d, yyyy: 월의 전체 이름, 일, 년
<br>
###### 4. `Date` 간 비교
```swift
if currentDate.compare(anotherDate) == .orderedAscending {
// 현재 날짜가 다른 날짜보다 이전일 때
}
```
- **`compare(_:)`**
- `Date` 객체를 비교해서 `ComparisonResult` 열거형을 반환하는 메서드
- `.orderedAscending`: 현재 날짜가 다른 날짜보다 이전일 때
- `.orderedSame`: 두 날짜가 같을 때
- `.orderedDescending`: 현재 날짜가 다른 날짜보다 이후일 때
<br>
###### 5. `Date` ⇌ 문자열 변환
```swift
let formattedDate = dateFormatter.string(from: currentDate)
let dateString = "2023-02-01"
let convertedDate = dateFormatter.date(from: dateString)
```
- 앞서 설정한 `dateFormat` 속성에 맞게 `Date` ⇌ 문자열을 변환할 수 있음
<br><br>
## Calendar
> 날짜와 시간을 표현하는 데 사용되는 달력 단위(년, 월, 일 등)와 시간의 절대적인 지점(특정 날짜 및 시간) 간의 관계를 정의하고, 날짜의 계산 및 비교를 위한 기능을 제공하는 구조체
<br>
#### Calendar 사용법
- `Calendar`는 다양한 **달력 시스템에 대한 정보**를 포함하고 있다.
- e.g. 언제 연도가 시작되며, 그 길이는 어떻게 정의되며, 연도는 어떻게 나뉘는지와 관련된 정보들
- `Calendar`는 특정 달력 단위(년, 월, 일 등)의 범위를 결정하는 등의 계산을 지원한다.
- **`Calendar`는 주어진 절대적인 시간에 달력 단위(예: 1년, 1달, 1일)를 추가하는 등의 계산을 지원한다.**
- 이를 통해 특정 날짜에 일정 기간을 더하거나 빼는 등의 조작이 가능하다.
<br>
#### 주요 메서드
###### 1. `Date` 구성 요소 추출
```swift
let calendar = Calendar.current
let date = Date()
let components = calendar.dateComponents([.year, .month, .day], from: date)
```
- **`dateComponents(_:from:)`**
- `Calendar` 객체를 사용하여 `Date`의 구성 요소를 추출할 수 있음
- 지정된 날짜에서 `components`에 지정된 구성 요소(년, 월, 일 등)를 추출하여 반환함
<br>
###### 2. 특정 `Date`의 시간 변경
```swift
let calendar = Calendar.current
let date = Date()
let modifiedDate = calendar.date(bySettingHour: 12, minute: 0, second: 0, of: date)
```
- **`date(bySettingHour:minute:second:of:matchingPolicy:repeatedTimePolicy:direction:)`**
- 주어진 `Date`의 시간을 설정하고 새로운 `Date`를 반환함
- 특정 날짜의 시간을 변경하고 싶을 때 사용
<br>
###### 3. 두 날짜 간의 차이 계산
```swift
let calendar = Calendar.current
let startDate = Date()
let endDate = calendar.date(byAdding: .day, value: 5, to: startDate)!
let components = calendar.dateComponents([.day, .hour], from: startDate, to: endDate) //day: 5 hour: 0
```
- **`dateComponents(_:from:to:)`**
- 두 날짜 간의 차이를 계산하고, 그 결과를 `DateComponents`로 반환함
<br>
###### 4. 특정 단위(e.g. 년, 월, 일 등)의 범위 계산
```swift
let calendar = Calendar.current
let date = Date()
let dayRange = calendar.range(of: .day, in: .month, for: currentDate)
let numberOfDaysInMonth = dayRange!.count
```
- **`range(of:in:for:)`**
- 특정한 시간 단위(예: 일)가 다른 큰 시간 단위(예: 월) 안에서 차지할 수 있는 절대적인 시간 값의 범위를 반환함
- e.g. 이번 달에 몇일이 포함되어 있는지 계산하기
<br><br>
## DateComponents
>날짜와 시간의 각 구성 요소(년, 월, 일, 시, 분, 초 등)를 나타내는 구조체. 주로 `Calendar` 와 함께 사용되어 날짜와 시간을 조작하는 데에 유용함
<br>
```swift
init(
calendar: Calendar? = nil,
timeZone: TimeZone? = nil,
era: Int? = nil, // 연대
year: Int? = nil,
month: Int? = nil,
day: Int? = nil,
hour: Int? = nil,
minute: Int? = nil,
second: Int? = nil,
nanosecond: Int? = nil,
weekday: Int? = nil, // 요일 (1=일요일, 2=월요일, ..., 7=토요일)
weekdayOrdinal: Int? = nil, // 해당 월의 몇 번째 요일인지를 나타내는 값
quarter: Int? = nil, // 분기
weekOfMonth: Int? = nil, // 해당 월의 몇 번째 주인지를 나타내는 값
weekOfYear: Int? = nil, // 해당 연도의 몇 번째 주인지를 나타내는 값
yearForWeekOfYear: Int? = nil // 해당 주가 속한 연도
)
```
<br>
<br><br>
---
**참고 문서**
- https://developer.apple.com/documentation/foundation/dates_and_times
- https://developer.apple.com/documentation/foundation/date
- https://developer.apple.com/documentation/foundation/calendar
- https://developer.apple.com/documentation/foundation/datecomponents
<br>
<br>
<br>
<br>