두 NSDates 사이의 신속한 일


111

나는 Swift의 두 NSDates / "새로운"Cocoa 사이에 일의 양을 얻을 수있는 새롭고 멋진 가능성이 있는지 궁금합니다.

예를 들어 Ruby에서와 같이 할 것입니다.

(end_date - start_date).to_i

5
나는 당신이 여전히 NSCalendar와 NSDateComponents를 사용해야한다고 생각합니다 (그래서 수백 개의 답변이 있어야합니다). - "새롭고 놀라운 가능성" 을 찾고 있다면 비교를 위해 현재 솔루션을 보여주는 것이 도움이 될 것입니다.
Martin R

1
이것은 이제 매우 쉽고 "NS"를 사용할 필요가 없습니다. 2017 년에 대한 답을 복사하여 붙여 넣었습니다.
Fattie 2017

답변:


247

시차도 고려해야합니다. 예를 들어 날짜 2015-01-01 10:00와 를 비교하면 2015-01-02 09:00해당 날짜 간의 차이가 24 시간 미만 (23 시간)이므로 해당 날짜 사이의 날짜는 0 (영)으로 반환됩니다.

두 날짜 사이의 정확한 날짜를 확인하는 것이 목적이라면 다음과 같이이 문제를 해결할 수 있습니다.

// Assuming that firstDate and secondDate are defined
// ...

let calendar = NSCalendar.currentCalendar()

// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDayForDate(firstDate)
let date2 = calendar.startOfDayForDate(secondDate)

let flags = NSCalendarUnit.Day
let components = calendar.components(flags, fromDate: date1, toDate: date2, options: [])

components.day  // This will return the number of day(s) between dates

Swift 3 및 Swift 4 버전

let calendar = Calendar.current

// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDay(for: firstDate)
let date2 = calendar.startOfDay(for: secondDate)

let components = calendar.dateComponents([.day], from: date1, to: date2)

14
실제로 startOfDayForDate 대신 오후 12시 (정오)를 확인하고 싶을 수 있습니다. 시간대와 DST를 조정하여 지루할 가능성이 낮아야합니다.
brandonscript

11
날짜를 정오로 설정하는 방법은 다음과 같습니다.calendar.date(bySettingHour: 12, minute: 00, second: 00, of: calendar.startOfDay(for: firstDate))
MonsieurDart

정오 설정을위한 더 짧은 버전 ( startOfDay()불필요한 것 같음) : calendar.date(bySettingHour: 12, minute: 0, second: 0, of: firstDate).
jamix

52

Swift 2에 대한 제 대답은 다음과 같습니다.

func daysBetweenDates(startDate: NSDate, endDate: NSDate) -> Int
{
    let calendar = NSCalendar.currentCalendar()

    let components = calendar.components([.Day], fromDate: startDate, toDate: endDate, options: [])

    return components.day
}

위의 @vikingosegundo 게시물 구성 요소와 함께 성공적으로 사용했습니다. 두 날짜 사이의 정확한 일 수를 나타내는 정수를 반환합니다. <좋아요>
내 계정 삭제

좋아 내가하지만, 함수 이름은 "daysBetweenDates"이어야합니다
mbonness

4
이 0을 반환 우리가 비교하는 경우 todaytomorrow
tawheed

39

몇 가지 Swift3 답변이 표시되므로 직접 추가하겠습니다.

public static func daysBetween(start: Date, end: Date) -> Int {
   Calendar.current.dateComponents([.day], from: start, to: end).day!
}

명명은 더 신속하고 한 줄이며 최신 dateComponents()방법을 사용합니다 .


28

Objective-C 답변을 번역했습니다.

let start = "2010-09-01"
let end = "2010-09-05"

let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"

let startDate:NSDate = dateFormatter.dateFromString(start)
let endDate:NSDate = dateFormatter.dateFromString(end)

let cal = NSCalendar.currentCalendar()


let unit:NSCalendarUnit = .Day

let components = cal.components(unit, fromDate: startDate, toDate: endDate, options: nil)


println(components)

결과

<NSDateComponents: 0x10280a8a0>
     Day: 4

가장 어려운 부분은 자동 완성이 fromDate 및 toDate가라고 주장하는 NSDate?것이지만 실제로 NSDate!참조에 표시된 것과 같아야합니다 .

각 경우에 단위를 다르게 지정하고 싶기 때문에 연산자를 사용한 좋은 솔루션이 어떻게 보일지 모르겠습니다. 시간 간격을 반환 할 수는 있지만 많은 것을 얻지 못할 것입니다.


.DayCalendarUnit더 이상 사용되지 않는 것 같습니다 . 이제 .CalendarUnitDay대신 사용해야한다고 생각 합니다.
TaylorAllred 2015

2
options는 이제 예상 매개 변수입니다
Departamento B

2
Swift 2를 실행하면 다음과 같이 작동합니다.let components = cal.components(.Day, fromDate: startDate, toDate: endDate, options: [])
Andrej

단지 @TaylorAllred .Day지금
윌리엄 GP

28

Date년, 월, 일, 시간, 분, 초의 날짜 차이를 얻는 매우 멋진 확장입니다.

extension Date {

    func years(sinceDate: Date) -> Int? {
        return Calendar.current.dateComponents([.year], from: sinceDate, to: self).year
    }

    func months(sinceDate: Date) -> Int? {
        return Calendar.current.dateComponents([.month], from: sinceDate, to: self).month
    }

    func days(sinceDate: Date) -> Int? {
        return Calendar.current.dateComponents([.day], from: sinceDate, to: self).day
    }

    func hours(sinceDate: Date) -> Int? {
        return Calendar.current.dateComponents([.hour], from: sinceDate, to: self).hour
    }

    func minutes(sinceDate: Date) -> Int? {
        return Calendar.current.dateComponents([.minute], from: sinceDate, to: self).minute
    }

    func seconds(sinceDate: Date) -> Int? {
        return Calendar.current.dateComponents([.second], from: sinceDate, to: self).second
    }

}

1
datesinceDate함수 매개 변수에 있어야합니다 .
TheTiger

@TheTiger-이 답변의 가장 큰 실수를 강조 해주셔서 감사합니다. 곧 답변을 실제로 테스트하고 업데이트하겠습니다.
Krunal

1
천만에요! 나는 그것을 테스트했으며 days잘 작동합니다.
TheTiger

1
좋은 대답입니다. 나는 단지 제안 func years(since date: Date) -> Int? { return Calendar.current.dateComponents[.year], from: date, to: self).years }하고 당신은 그것을로 부를 수 있습니다 let y = date1.years(since: date2). 이는 최신 명명 규칙과 더 일치 할 수 있습니다.
Rob

18

Swift 3 iOS 10 Beta 4 업데이트

func daysBetweenDates(startDate: Date, endDate: Date) -> Int {
    let calendar = Calendar.current
    let components = calendar.dateComponents([Calendar.Component.day], from: startDate, to: endDate)
    return components.day!
}

10

다음은 Swift 3에 대한 답변입니다 (IOS 10 베타 테스트 완료)

func daysBetweenDates(startDate: Date, endDate: Date) -> Int
{
    let calendar = Calendar.current
    let components = calendar.components([.day], from: startDate, to: endDate, options: [])
    return components.day!
}

그러면 이렇게 부를 수 있습니다

let pickedDate: Date = sender.date
let NumOfDays: Int = daysBetweenDates(startDate: pickedDate, endDate: Date())
    print("Num of Days: \(NumOfDays)")

7

Swift 3. 제안에 대해 위의 Emin Buğra Saral 에게 감사드립니다 startOfDay.

extension Date {

    func daysBetween(date: Date) -> Int {
        return Date.daysBetween(start: self, end: date)
    }

    static func daysBetween(start: Date, end: Date) -> Int {
        let calendar = Calendar.current

        // Replace the hour (time) of both dates with 00:00
        let date1 = calendar.startOfDay(for: start)
        let date2 = calendar.startOfDay(for: end)

        let a = calendar.dateComponents([.day], from: date1, to: date2)
        return a.value(for: .day)!
    }
}

용법:

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let start = dateFormatter.date(from: "2017-01-01")!
let end = dateFormatter.date(from: "2018-01-01")!

let diff = Date.daysBetween(start: start, end: end) // 365

1
많은 문제를 피하기 위해 00:00보다는 정오로 둘 다 옮기는 것이 확실히 낫습니다 .
Fattie

3

swift에 내장 된 것은 여전히 ​​매우 기본입니다. 이 초기 단계에 있어야합니다. 그러나 오버로딩 연산자 및 전역 도메인 기능과 함께 제공되는 위험이있는 자신의 것을 추가 할 수 있습니다. 그래도 모듈에 로컬입니다.

let now = NSDate()
let seventies = NSDate(timeIntervalSince1970: 0)

// Standard solution still works
let days = NSCalendar.currentCalendar().components(.CalendarUnitDay, 
           fromDate: seventies, toDate: now, options: nil).day

// Flashy swift... maybe...
func -(lhs:NSDate, rhs:NSDate) -> DateRange {
    return DateRange(startDate: rhs, endDate: lhs)
}

class DateRange {
    let startDate:NSDate
    let endDate:NSDate
    var calendar = NSCalendar.currentCalendar()
    var days: Int {
        return calendar.components(.CalendarUnitDay, 
               fromDate: startDate, toDate: endDate, options: nil).day
    }
    var months: Int {
        return calendar.components(.CalendarUnitMonth, 
               fromDate: startDate, toDate: endDate, options: nil).month
    }
    init(startDate:NSDate, endDate:NSDate) {
        self.startDate = startDate
        self.endDate = endDate
    }
}

// Now you can do this...
(now - seventies).months
(now - seventies).days

19
하루 길이에 (24 * 60 * 60)을 사용 하지 마십시오 . 일광 절약 시간 전환은 고려하지 않습니다.
Martin R

나는 NSDate가 항상 GMT를 사용하고 일광 절약은 그에 대한 형식화 또는 지역화이기 때문에 조정할 것이라고 생각합니다. 확실히 그것은 몇 달, 몇 년 또는 정말 가변적 인 길이의 무엇이든 까다로워집니다.
다니엘 Schlaug

1
@MartinR 나는 그것을 믿기 위해 그것을 시도해야했지만 실제로, 이제 나는 위키피디아가 이것을 언급하는 것을 보았습니다. 당신이 올바른지. 고집을 부리셔서 감사합니다.
Daniel Schlaug 2014

1
거기에서 정확하도록 편집되었습니다. 그러나 화려 함은 사라졌습니다.
Daniel Schlaug 2014

1
위치, 시점 및 달력 시스템에 의해 정의됩니다. 히브리 달력에는 윤월이 있습니다. 멋진 wwdc 비디오가 있습니다. 달력 계산 수행 — 모든 코코아 코더에게 꼭 필요한 것입니다.
vikingosegundo

3

Swift 3에 대한 제 대답은 다음과 같습니다.

func daysBetweenDates(startDate: NSDate, endDate: NSDate, inTimeZone timeZone: TimeZone? = nil) -> Int {
    var calendar = Calendar.current
    if let timeZone = timeZone {
        calendar.timeZone = timeZone
    }
    let dateComponents = calendar.dateComponents([.day], from: startDate.startOfDay, to: endDate.startOfDay)
    return dateComponents.day!
}

2

아직 Swift 전용 표준 라이브러리는 거의 없습니다. 린 기본 숫자, 문자열 및 컬렉션 유형입니다.

확장을 사용하여 이러한 속기를 정의하는 것은 완벽하게 가능하지만, 실제 기본 제공되는 API에 관한 한 "새로운"Cocoa는 없습니다. Swift는 이미 존재하는 것과 동일한 오래된 장황한 Cocoa API에 직접 매핑됩니다.


2

이 스레드는 1 년이 지났지 만 내 버전을 추가 할 것입니다. 내 코드는 다음과 같습니다.

    var name = txtName.stringValue // Get the users name

    // Get the date components from the window controls
    var dateComponents = NSDateComponents()
    dateComponents.day = txtDOBDay.integerValue
    dateComponents.month = txtDOBMonth.integerValue
    dateComponents.year = txtDOBYear.integerValue

    // Make a Gregorian calendar
    let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)

    // Get the two dates we need
    var birthdate = calendar?.dateFromComponents(dateComponents)
    let currentDate = NSDate()

    var durationDateComponents = calendar?.components(NSCalendarUnit.CalendarUnitDay, fromDate: birthdate!, toDate: currentDate, options: nil)

    let numberOfDaysAlive = durationDateComponents?.day

    println("\(numberOfDaysAlive!)")

    txtGreeting.stringValue = "Hello \(name), You have been alive for \(numberOfDaysAlive!) days."

누군가에게 도움이되기를 바랍니다.

건배,


2

Erin의 방법이 Swift 3으로 업데이트되었습니다. 오늘부터 날짜가 표시됩니다 (시간에 관계 없음).

func daysBetweenDates( endDate: Date) -> Int 
    let calendar: Calendar = Calendar.current 
    let date1 = calendar.startOfDay(for: Date()) 
    let date2 = calendar.startOfDay(for: secondDate) 
    return calendar.dateComponents([.day], from: date1, to: date2).day! 
}

2

이것은 일부 Date와 오늘 사이의 절대적인 차이를 반환합니다 .

extension Date {
  func daysFromToday() -> Int {
    return abs(Calendar.current.dateComponents([.day], from: self, to: Date()).day!)
  }
}

그리고 그것을 사용하십시오 :

if someDate.daysFromToday() >= 7 {
  // at least a week from today
}

2

다음 확장을 사용할 수 있습니다.

public extension Date {
    func daysTo(_ date: Date) -> Int? {
        let calendar = Calendar.current

        // Replace the hour (time) of both dates with 00:00
        let date1 = calendar.startOfDay(for: self)
        let date2 = calendar.startOfDay(for: date)

        let components = calendar.dateComponents([.day], from: date1, to: date2)
        return components.day  // This will return the number of day(s) between dates
    }
}

그런 다음 다음과 같이 호출 할 수 있습니다.

startDate.daysTo(endDate)

1

스위프트 3.2

extension DateComponentsFormatter {
    func difference(from fromDate: Date, to toDate: Date) -> String? {
        self.allowedUnits = [.year,.month,.weekOfMonth,.day]
        self.maximumUnitCount = 1
        self.unitsStyle = .full
        return self.string(from: fromDate, to: toDate)
    }
}

1

모든 대답이 좋습니다. 그러나 현지화의 경우 두 날짜 사이의 소수점 일 수를 계산해야합니다. 지속 가능한 십진수 형식을 제공 할 수 있습니다.

// This method returns the fractional number of days between to dates
func getFractionalDaysBetweenDates(date1: Date, date2: Date) -> Double {

    let components = Calendar.current.dateComponents([.day, .hour], from: date1, to: date2)

    var decimalDays = Double(components.day!)
    decimalDays += Double(components.hour!) / 24.0

    return decimalDays
}

1
extension Date {
    func daysFromToday() -> Int {
        return Calendar.current.dateComponents([.day], from: self, to: Date()).day!
    }
}

그런 다음 다음과 같이 사용하십시오.

    func dayCount(dateString: String) -> String{
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "MMM dd,yyyy hh:mm a"
        let fetchedDate = dateFormatter.date(from: dateString)


        let day = fetchedDate?.daysFromToday()
        if day! > -1{
            return "\(day!) days passed."
        }else{
        return "\(day! * -1) days left."
        }
    }

1

이것은 날짜를 비교하는 결정적인 시간으로 자정 대신 정오를 사용하라는 제안을 포함하는 Swift 5에 대한 Emin의 답변의 업데이트 버전입니다. 또한 선택 사항을 반환하여 다양한 날짜 함수의 잠재적 인 실패를 처리합니다.

    ///
    /// This is an approximation; it does not account for time differences. It will set the time to 1200 (noon) and provide the absolute number
    /// of days between now and the given date. If the result is negative, it should be read as "days ago" instead of "days from today."
    /// Returns nil if something goes wrong initializing or adjusting dates.
    ///

    func daysFromToday() -> Int?
    {
        let calendar = NSCalendar.current

        // Replace the hour (time) of both dates with noon. (Noon is less likely to be affected by DST changes, timezones, etc. than midnight.)
        guard let date1 = calendar.date(bySettingHour: 12, minute: 00, second: 00, of: calendar.startOfDay(for: Date())),
              let date2 = calendar.date(bySettingHour: 12, minute: 00, second: 00, of: calendar.startOfDay(for: self)) else
        {
            return nil
        }

        return calendar.dateComponents([.day], from: date1, to: date2).day
    }

Swift 네이티브 캘린더를 사용해야합니다 (NS 삭제). 시간을 오후 12 시로 설정할 때 경비를 사용하는 것은 무의미합니다. 결코 실패하지 않을 것입니다.
Leo Dabus

시간을 정오로 설정하기 전에 startOfDay를 호출하는 것도 의미가 없습니다.
Leo Dabus

0

Swift 3-오늘부터 현재까지의 일

func daysUntilDate(endDateComponents: DateComponents) -> Int
    {
        let cal = Calendar.current
        var components = cal.dateComponents([.era, .year, .month, .day], from: NSDate() as Date)
        let today = cal.date(from: components)
        let otherDate = cal.date(from: endDateComponents)

        components = cal.dateComponents([Calendar.Component.day], from: (today! as Date), to: otherDate!)
        return components.day!
    }

다음과 같은 함수 호출

// Days from today until date
   var examnDate = DateComponents()
   examnDate.year = 2016
   examnDate.month = 12
   examnDate.day = 15
   let daysCount = daysUntilDate(endDateComponents: examnDate)

0

더 쉬운 옵션은 날짜에 확장을 만드는 것입니다.

public extension Date {

        public var currentCalendar: Calendar {
            return Calendar.autoupdatingCurrent
        }

        public func daysBetween(_ date: Date) -> Int {
            let components = currentCalendar.dateComponents([.day], from: self, to: date)
            return components.day!
        }
    }

0
  func completeOffset(from date:Date) -> String? {

    let formatter = DateComponentsFormatter()
    formatter.unitsStyle = .brief

    return  formatter.string(from: Calendar.current.dateComponents([.year,.month,.day,.hour,.minute,.second], from: date, to: self))




}

년 월 일과 시간이 문자열로 필요하면 이것을 사용하십시오.

var tomorrow = Calendar.current.date (byAdding : .day, value : 1, to : Date ())!

let dc = tomorrow.completeOffset (from : Date ())


0

좋은 편리한 한 라이너 :

extension Date {
  var daysFromNow: Int {
    return Calendar.current.dateComponents([.day], from: Date(), to: self).day!
  }
}

0

스위프트 4

 func getDateHeader(indexPath: Int) -> String {
    let formatter2 = DateFormatter()
    formatter2.dateFormat = "MM-dd-yyyy"
    var dateDeadline : Date?

    dateDeadline = formatter2.date(from: arrCompletedDate[indexPath] as! String)

    let currentTime = dateDeadline?.unixTimestamp
    let calendar = NSCalendar.current

    let date = NSDate(timeIntervalSince1970: Double(currentTime!))
    if calendar.isDateInYesterday(date as Date) { return "Yesterday" }
    else if calendar.isDateInToday(date as Date) { return "Today" }
    else if calendar.isDateInTomorrow(date as Date) { return "Tomorrow" }
    else {
        let startOfNow = calendar.startOfDay(for: NSDate() as Date)
        let startOfTimeStamp = calendar.startOfDay(for: date as Date)
        let components = calendar.dateComponents([.day], from: startOfNow, to: startOfTimeStamp)
        let day = components.day!
        if day < 1 { return "\(abs(day)) days ago" }
        else { return "In \(day) days" }
    }
}

0

Swift 5.2.4 솔루션 :

import UIKit

let calendar = Calendar.current

let start = "2010-09-01"
let end = "2010-09-05"

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"

let firstDate = dateFormatter.date(from: start)!
let secondDate = dateFormatter.date(from: end)!

// Replace the hour (time) of both dates with 00:00
let date1 = calendar.startOfDay(for: firstDate)
let date2 = calendar.startOfDay(for: secondDate)

let components = calendar.dateComponents([Calendar.Component.day], from: date1, to: date2)

components.day  // This will return the number of day(s) between dates

-1

2017 버전, 복사 및 붙여 넣기

func simpleIndex(ofDate: Date) -> Int {
    
    // index here just means today 0, yesterday -1, tomorrow 1 etc.
    
    let c = Calendar.current
    let todayRightNow = Date()
    
    let d = c.date(bySetting: .hour, value: 13, of: ofDate)
    let t = c.date(bySetting: .hour, value: 13, of: todayRightNow)
    
    if d == nil || today == nil {
    
        print("weird problem simpleIndex#ofDate")
        return 0
    }
    
    let r = c.dateComponents([.day], from: today!, to: d!)
    // yesterday is negative one, tomorrow is one
    
    if let o = r.value(for: .day) {
        
        return o
    }
    else {
    
        print("another weird problem simpleIndex#ofDate")
        return 0
    }
}

-2
let calendar = NSCalendar.currentCalendar();
let component1 = calendar.component(.Day, fromDate: fromDate)
let component2 = calendar.component(.Day, fromDate: toDate)
let difference  = component1 - component2

1
즉, 1 월 21 일부터 2 월 22 일까지 날짜 수 부분의 차이를 측정합니다. 즉, 1 월 21 일부터 2 월 22 일까지 32 일이 아닌 1 일이 주어집니다.
Peter Johnson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.