스위프트 날짜 개체를 어떻게 만듭니 까?


156

swift xcode의 날짜에서 날짜 객체를 어떻게 생성합니까?

예를 들어 자바 스크립트에서는 다음을 수행합니다. var day = new Date('2014-05-20');


10
NSDateObjective-C에서와 같이 사용 하시겠습니까?
rmaddy

답변:


263

스위프트는 자체 Date유형이 있습니다. 사용할 필요가 없습니다 NSDate.

Swift에서 날짜 및 시간 생성

Swift에서 날짜 및 시간은 2001 년 1 월 1 일 기준 날짜 00:00:00 UTC 이후 초 수를 측정하는 64 비트 부동 소수점 숫자로 저장됩니다 . 이것은 Date구조 로 표현됩니다 . 다음은 현재 날짜와 시간을 알려줍니다.

let currentDateTime = Date()

다른 날짜-시간을 만들려면 다음 방법 중 하나를 사용할 수 있습니다.

방법 1

2001 년 기준 날짜 이전 또는 이후의 시간 (초)을 알고 있으면이를 사용할 수 있습니다.

let someDateTime = Date(timeIntervalSinceReferenceDate: -123456789.0) // Feb 2, 1997, 10:26 AM

방법 2

물론 년, 월, 일 및 시간 (상대 초가 아닌)을 사용하여을 만드는 것이 더 쉬울 것 Date입니다. 이를 위해 DateComponents구성 요소를 지정한 다음 Calendar날짜를 만드는 데 사용할 수 있습니다 . 는 Calendar제공 Date컨텍스트를. 그렇지 않으면, 어떤 시간대 나 캘린더를 표시 할 것인지 어떻게 알 수 있습니까?

// Specify date components
var dateComponents = DateComponents()
dateComponents.year = 1980
dateComponents.month = 7
dateComponents.day = 11
dateComponents.timeZone = TimeZone(abbreviation: "JST") // Japan Standard Time
dateComponents.hour = 8
dateComponents.minute = 34

// Create date from components
let userCalendar = Calendar.current // user calendar
let someDateTime = userCalendar.date(from: dateComponents)

다른 시간대 약어는 여기 에서 찾을 수 있습니다 . 비워두면 기본값은 사용자의 시간대를 사용하는 것입니다.

방법 3

가장 간결한 방법 (그러나 반드시 최고는 아님)을 사용할 수 있습니다 DateFormatter.

let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd HH:mm"
let someDateTime = formatter.date(from: "2016/10/08 22:31")

유니 코드 기술 표준은 다른 형식으로 보여줄 것을 DateFormatter지원합니다.

노트

날짜와 시간을 읽을 수있는 형식으로 표시하는 방법에 대한 전체 답변 을 참조하십시오 . 다음과 같은 훌륭한 기사를 읽으십시오.


118

이것은 기존 NSDate클래스 의 확장을 사용하여 가장 잘 수행됩니다 .

다음 확장은 지정된 형식의 날짜 문자열을 사용하여 현재 로케일로 날짜를 작성하는 새 초기화 프로그램을 추가합니다.

extension NSDate
{
    convenience
      init(dateString:String) {
      let dateStringFormatter = NSDateFormatter()
      dateStringFormatter.dateFormat = "yyyy-MM-dd"
      dateStringFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
      let d = dateStringFormatter.dateFromString(dateString)!
      self.init(timeInterval:0, sinceDate:d)
    }
 }

이제 다음을 수행하여 Swift에서 NSDate를 만들 수 있습니다.

NSDate(dateString:"2014-06-06")

이 구현은 NSDateFormatter를 캐시하지 않습니다. NSDateFormatter NSDate는 이런 방식으로 많은 파일을 생성 할 것으로 예상되는 경우 성능상의 이유로 할 수 있습니다 .

또한 NSDate올바르게 구문 분석 할 수없는 문자열을 전달 하여 초기화하려고하면이 구현이 단순히 중단 됩니다. 이는에서 반환 한 선택적 값을 강제로 풀기 때문입니다 dateFromString. nil잘못된 구문 분석 을 반환 하려면 실패한 초기화 프로그램을 사용하는 것이 이상적입니다. 그러나 Swift 1.2의 한계로 인해 지금 (2015 년 6 월) 그렇게 할 수 없으므로 다음 팩토리 메소드를 사용하는 것이 가장 좋습니다.

두 문제를 해결하는 더 정교한 예는 여기에 있습니다 : https://gist.github.com/algal/09b08515460b7bd229fa .


스위프트 5 업데이트

extension Date {
    init(_ dateString:String) {
        let dateStringFormatter = DateFormatter()
        dateStringFormatter.dateFormat = "yyyy-MM-dd"
        dateStringFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") as Locale
        let date = dateStringFormatter.date(from: dateString)!
        self.init(timeInterval:0, since:date)
    }
}

9
"편의"라는 단어는 무엇입니까?
제임스 번즈

18
확장이 이미 초기화를 이미 존재하는 지정된 이니셜 라이저 (이 경우 NSDate.init (timeInterval :, sinceDate :) 이니셜 라이저)에 위임하는 이니셜 라이저를 제공하고 있음을 나타냅니다. 이것은 Swift Programming Language 책의 275 페이지에 설명되어 있습니다.
algal

1
위의 코드에서 볼 수있는 결함 중 하나 NSDateFormatter는 함수에 액세스 할 때마다 다시 만드는 것 입니다. 으로 날짜 포맷 가이드 상태 싼 작동하지 포맷터 날짜를 만들기 . 또한 클래스는 iOS7부터 스레드로부터 안전하므로 모든 NSDate확장에 안전하게 사용할 수 있습니다 .
Yevhen Dubinin

@eugenedubinin이 정확합니다. 그렇기 때문에 "이 구현은 성능상의 이유로 NSDateFormatter를 캐시하지 않습니다"라고 말했습니다.
algal

1
Swift 1.2의 한계는 무엇입니까? "failable initializer"기능은 Swift 1.1부터 사용 가능 합니다.
Franklin Yu

48

Swift에는 자체 날짜 유형이 없지만 기존 Cocoa NSDate유형 을 사용하십시오 . 예 :

class Date {

    class func from(year: Int, month: Int, day: Int) -> Date {
        let gregorianCalendar = NSCalendar(calendarIdentifier: .gregorian)!

        var dateComponents = DateComponents()
        dateComponents.year = year
        dateComponents.month = month
        dateComponents.day = day

        let date = gregorianCalendar.date(from: dateComponents)!
        return date
    }

    class func parse(_ string: String, format: String = "yyyy-MM-dd") -> Date {
        let dateFormatter = DateFormatter()
        dateFormatter.timeZone = NSTimeZone.default
        dateFormatter.dateFormat = format

        let date = dateFormatter.date(from: string)!
        return date
    }
}

다음과 같이 사용할 수 있습니다.

var date = Date.parse("2014-05-20")
var date = Date.from(year: 2014, month: 05, day: 20)

var date = gregorian? .dateFromComponents (c) 행을 변경해야했지만 이유를 이해하지 못하고 구문 분석 반환 dateFmt.dateFromString도 불평합니다. 단서가 있습니까? 아, 함수의 반환 유형을 NSDate에서 NSDate로 변경 했습니까? 컴파일 할 수 있습니다. 그러나 왜 null을 허용 해야하는지 잘 모르겠습니다.
상원 의원

1
@TheSenator NSCalendar init는 선택적 (?)을 반환하므로 gregorian은 선택적 (?)입니다. 옵션 체인에 대한 선택적인 필요에 접근하기 gregorian? .dateFromCoomponents는 옵션 gregorian (NSCalendar)에서 값을 풀기위한 옵션 체인입니다. 더 많은 옵션이 체인에 대한 여기
iluvatar_GR

NSGregorianCalendar는 iOS 8부터 사용되지 않으므로 대신 NSCalendarIdentifierGregorian을 사용하십시오
Adam Knights

2
@ 상원 의원은 coz Swift에 Date 구조체가 있다고 불평 하며이 코드는 Date를 클래스로 다시 선언합니다. u는 뭔가해야 그래서 같은 '확장 날짜'와 '정적 FUNC'
Zaporozhchenko 올렉산드르

문자열을 날짜로 다시 구문 분석하는 메모입니다. 에 대한 'YYYY-MM-DD'가있는 문자열 "1979년 7월 1일" NSDateFormatter방법 date(from:). 를 반환합니다 nil. fabric.io 충돌 로그 에서이 문제를 발견했습니다.
AechoLiu

12

Swift 4.2에서 내가 한 방법은 다음과 같습니다.

extension Date {

    /// Create a date from specified parameters
    ///
    /// - Parameters:
    ///   - year: The desired year
    ///   - month: The desired month
    ///   - day: The desired day
    /// - Returns: A `Date` object
    static func from(year: Int, month: Int, day: Int) -> Date? {
        let calendar = Calendar(identifier: .gregorian)
        var dateComponents = DateComponents()
        dateComponents.year = year
        dateComponents.month = month
        dateComponents.day = day
        return calendar.date(from: dateComponents) ?? nil
    }
}

용법:

let marsOpportunityLaunchDate = Date.from(year: 2003, month: 07, day: 07)

하루에 '15'를 전달했지만 반환 날짜가 14 일을 제공합니까? 생각?
Luke Zammit

@LukeZammit 시간대 추가dateComponents
Adrian

행운없이 이것을 시도했습니다-dateComponents.timeZone = TimeZone.current, 생각하십시오?
Luke Zammit

5

Apple 문서 에 따르면

예 :

var myObject = NSDate()
let futureDate = myObject.dateByAddingTimeInterval(10)
let timeSinceNow = myObject.timeIntervalSinceNow

3
좋았지 만 질문에 대답하지 못했습니다. 질문은 시간 간격에 관한 것이 아닙니다.
zaph

4

Swift 3.0에서는이 방법으로 날짜 객체를 설정했습니다.

extension Date
{
    init(dateString:String) {
        let dateStringFormatter = DateFormatter()
        dateStringFormatter.dateFormat = "yyyy-MM-dd"
        dateStringFormatter.locale = Locale(identifier: "en_US_POSIX")
        let d = dateStringFormatter.date(from: dateString)!
        self(timeInterval:0, since:d)
    }
}

당신이 원하는 어디에서나 @ Zonker.in. 제네바. 별도의 파일을 작성하고 "Extension", idk라고합니다.
Zaporozhchenko Oleksandr

2

개인적으로 나는 그것이 실패한 초 기자이어야한다고 생각합니다.

extension Date {

    init?(dateString: String) {
        let dateStringFormatter = DateFormatter()
        dateStringFormatter.dateFormat = "yyyy-MM-dd"
        if let d = dateStringFormatter.date(from: dateString) {
            self.init(timeInterval: 0, since: d)
        } else {
            return nil
        }
    }
}

그렇지 않으면 형식이 잘못된 문자열은 예외를 발생시킵니다.


2

@mythz 답변에 따르면 swift3구문을 사용하여 업데이트 된 버전의 확장 프로그램을 게시하기로 결정했습니다 .

extension Date {
    static func from(_ year: Int, _ month: Int, _ day: Int) -> Date?
    {
        let gregorianCalendar = Calendar(identifier: .gregorian)
        let dateComponents = DateComponents(calendar: gregorianCalendar, year: year, month: month, day: day)
        return gregorianCalendar.date(from: dateComponents)
    }
}

나는 parse방법을 사용하지 않지만 누군가가 필요하다면이 게시물을 업데이트 할 것입니다.


1

한 장소의 날짜 값과 다른 장소의 시간 값을 결합해야하는 경우가 종종 있습니다. 이것을 달성하기 위해 도우미 기능을 작성했습니다.

let startDateTimeComponents = NSDateComponents()
startDateTimeComponents.year = NSCalendar.currentCalendar().components(NSCalendarUnit.Year, fromDate: date).year
startDateTimeComponents.month = NSCalendar.currentCalendar().components(NSCalendarUnit.Month, fromDate: date).month
startDateTimeComponents.day = NSCalendar.currentCalendar().components(NSCalendarUnit.Day, fromDate: date).day
startDateTimeComponents.hour = NSCalendar.currentCalendar().components(NSCalendarUnit.Hour, fromDate: time).hour
startDateTimeComponents.minute = NSCalendar.currentCalendar().components(NSCalendarUnit.Minute, fromDate: time).minute
let startDateCalendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)
combinedDateTime = startDateCalendar!.dateFromComponents(startDateTimeComponents)!

0

Apple의 데이터 포맷 가이드 에 따르면

날짜 포맷터를 만드는 것은 저렴한 작업이 아닙니다. 포맷터를 자주 사용하는 경우에는 여러 인스턴스를 작성하고 폐기하는 것보다 단일 인스턴스를 캐시하는 것이 일반적으로 더 효율적입니다. 한 가지 방법은 정적 변수를 사용하는 것입니다

그리고 @Leon에 동의하지만 이것이 실패 가능한 이니셜 라이저 여야한다는 것에 동의하지만 시드 데이터를 입력하면 실패 할 수없는 것을 가질 수 있습니다 (있는 것처럼 UIImage(imageLiteralResourceName:)).

내 접근 방식은 다음과 같습니다.

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: "en_US_POSIX")
    return formatter
  }()
}

extension Date {
    init?(yyyyMMdd: String) {
        guard let date = DateFormatter.yyyyMMdd.date(from: yyyyMMdd) else { return nil }
        self.init(timeInterval: 0, since: date)
    }

    init(dateLiteralString yyyyMMdd: String) {
        let date = DateFormatter.yyyyMMdd.date(from: yyyyMMdd)!
        self.init(timeInterval: 0, since: date)
    }
}

이제 간단하게 전화를 걸 수 있습니다.

// For seed data
Date(dateLiteralString: "2020-03-30")

// When parsing data
guard let date = Date(yyyyMMdd: "2020-03-30") else { return nil }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.