Wie füge ich einen Monat zu einem NSDate hinzu?


81

Wie füge ich dem NSDate-Objekt einen Monat hinzu?

NSDate *someDate = [NSDate Date] + 30Days.....;

1
Welches Ergebnis möchten Sie, wenn der Starttermin der 31. Januar ist?
Gnasher729

Antworten:


138

Sie müssen NSDateComponents verwenden :

NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
[dateComponents setMonth:1];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *newDate = [calendar dateByAddingComponents:dateComponents toDate:originalDate options:0];
[dateComponents release]; // If ARC is not used, release the date components

Weißt du, wie ich zwischen jetzt und dem Schicksalsdatum vergleichen kann? um zu überprüfen, ob ich dieses Datum bestanden habe?
oder Azran

1
Datumsvergleiche werden mit den NSDate-Funktionen compare, beforeDate und laterDate durchgeführt - siehe dazu die NSDate-Dokumentation: developer.apple.com/library/mac/#documentation/Cocoa/Reference/…
TheEye

1
@orazran können Sie Daten mit: vergleichen [date timeIntervalSinceDate:otherDate], wodurch die Differenz zwischen ihnen in Sekunden zurückgegeben wird (weniger als 0 für vergangene Daten, mehr als 0 für zukünftige Daten).
Abhi Beckert

126

Mit iOS 8 und OS X 10.9 können Sie hinzufügen NSCalendarUnitsmit NSCalendar:

Ziel c

NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *someDate = [cal dateByAddingUnit:NSCalendarUnitMonth value:1 toDate:[NSDate date] options:0];

Swift 3

let date = Calendar.current.date(byAdding: .month, value: 1, to: Date())

Swift 2

let cal = NSCalendar.currentCalendar()
let date = cal.dateByAddingUnit(.Month, value: 1, toDate: NSDate(), options: [])

Die obigen Beispiele rufen eine Methode auf und greifen nicht auf eine Eigenschaft zu.
Kevin

Swift 3: let date = Calendar.current.date (byAdding: .month, value: 1, to: Date ())
Maksym Bilan

Dies sollte die akzeptierte Antwort sein. Die derzeit akzeptierte Antwort lautet nur Objective-C und ist zu ausführlich.
Colin Basnett

23

Für schnelle 3.0

extension Date {
    func addMonth(n: Int) -> Date {
        let cal = NSCalendar.current
        return cal.date(byAdding: .month, value: n, to: self)!
    }
    func addDay(n: Int) -> Date {
        let cal = NSCalendar.current
        return cal.date(byAdding: .day, value: n, to: self)!
    }
    func addSec(n: Int) -> Date {
        let cal = NSCalendar.current
        return cal.date(byAdding: .second, value: n, to: self)!
    }
}

1
Was passiert, wenn ich 1 Monat zum 31. Januar hinzufüge, der am 2. März endet oder ...?
Michał Ziobro

13

So fügen Sie beispielsweise 3dem aktuellen Datum in Swift Monate hinzu :

let date = NSCalendar.currentCalendar().dateByAddingUnit(.MonthCalendarUnit, value: 3, toDate: NSDate(), options: nil)!

In Swift 2.0:

let date = NSCalendar.currentCalendar().dateByAddingUnit(.Month, value: 3, toDate: NSDate(), options: [])
  • Die neue OptionSetTypeStruktur vonNSCalendarUnit können Sie einfacher angeben.Month
  • Parameter, die nehmen OptionSetType(wie der options:Parameter, der nimmt NSCalendarOptions), können nicht sein nil. Übergeben Sie daher eine leere Menge ( []), um "keine Optionen" darzustellen.

.MonthCalendarUnitist veraltet, verwenden.CalendarUnitMonth
Arnold

3

In Swift 2.0

    let startDate = NSDate()
    let dateComponent = NSDateComponents()
    dateComponent.month = 1
    let cal = NSCalendar.currentCalendar()
    let endDate = cal.dateByAddingComponents(dateComponent, toDate: startDate, options: NSCalendarOptions(rawValue: 0))

2

FÜR SWIFT 3.0

Hier ist die Funktion, Sie können Tage, Monat, Tag um eine beliebige Anzahl reduzieren, wie zum Beispiel hier. Ich habe das Jahr des aktuellen Systemdatums um 100 Jahre reduziert. Sie können dies für Tag und Monat tun. Setzen Sie auch einfach den Zähler und speichern Sie dann die Werte in Array, und machen Sie, was Sie mit diesem Array tun möchten

func currentTime(){

    let date = Date()
    let calendar = Calendar.current
    var year = calendar.component(.year, from: date)
    let month = calendar.component(.month, from: date)
    let  day = calendar.component(.day, from: date)
    let pastyear = year - 100
    var someInts = [Int]()
    printLog(msg: "\(day):\(month):\(year)" )

    for _ in pastyear...year        {
        year -= 1
                     print("\(year) ")
        someInts.append(year)
    }

    print(someInts)
}

1

Andere Antworten funktionieren einwandfrei, wenn Ihr gewünschtes Verhalten einen Monat hinzufügt und Sommerzeit berücksichtigt. Dies führt zu folgenden Ergebnissen:

01/03/2017 00:00 + 1 month -> 31/03/2017 23:00
01/10/2017 00:00 + 1 month -> 01/11/2017 01:00

Ich wollte jedoch die durch die Sommerzeit verlorene oder gewonnene Stunde ignorieren, so dass:

01/03/2017 00:00 + 1 month -> 01/04/2017 00:00
01/10/2017 00:00 + 1 month -> 01/11/2017 00:00

Also überprüfe ich, ob eine Sommerzeitgrenze überschritten wird, und wenn ja, addiere oder subtrahiere ich eine Stunde entsprechend:

func offsetDaylightSavingsTime() -> Date {
        // daylightSavingTimeOffset is either + 1hr or + 0hr. To offset DST for a given date, we need to add an hour or subtract an hour
        // +1hr -> +1hr
        // +0hr -> -1hr
        // offset = (daylightSavingTimeOffset * 2) - 1 hour

        let daylightSavingsTimeOffset = TimeZone.current.daylightSavingTimeOffset(for: self)
        let oneHour = TimeInterval(3600)
        let offset = (daylightSavingsTimeOffset * 2) - oneHour
        return self.addingTimeInterval(offset)
    }

    func isBetweeen(date date1: Date, andDate date2: Date) -> Bool {
        return date1.compare(self).rawValue * self.compare(date2).rawValue >= 0
    }

    func offsetDaylightSavingsTimeIfNecessary(nextDate: Date) -> Date {
        if let nextDST = TimeZone.current.nextDaylightSavingTimeTransition(after: self) {
            if nextDST.isBetweeen(date: self, andDate: nextDate){
                let offsetDate = nextDate.offsetDaylightSavingsTime()
                let difference = offsetDate.timeIntervalSince(nextDate)
                return nextDate.addingTimeInterval(difference)
            }
        }

        return nextDate
    }

    func dateByAddingMonths(_ months: Int) -> Date? {
        if let dateWithMonthsAdded = Calendar.current.date(byAdding: .month, value: months, to: self) {
            return self.offsetDaylightSavingsTimeIfNecessary(nextDate: dateWithMonthsAdded)
        }

        return self
    }

Prüfung:

func testDateByAddingMonths() {

    let date1 = "2017-01-01T00:00:00Z".asDate()
    let date2 = "2017-02-01T00:00:00Z".asDate()
    let date3 = "2017-03-01T00:00:00Z".asDate()
    let date4 = "2017-04-01T00:00:00Z".asDate()
    let date5 = "2017-05-01T00:00:00Z".asDate()
    let date6 = "2017-06-01T00:00:00Z".asDate()
    let date7 = "2017-07-01T00:00:00Z".asDate()
    let date8 = "2017-08-01T00:00:00Z".asDate()
    let date9 = "2017-09-01T00:00:00Z".asDate()
    let date10 = "2017-10-01T00:00:00Z".asDate()
    let date11 = "2017-11-01T00:00:00Z".asDate()
    let date12 = "2017-12-01T00:00:00Z".asDate()
    let date13 = "2018-01-01T00:00:00Z".asDate()
    let date14 = "2018-02-01T00:00:00Z".asDate()

    var testDate = "2017-01-01T00:00:00Z".asDate()
    XCTAssertEqual(testDate, date1)

    testDate = testDate.dateByAddingMonths(1)!
    XCTAssertEqual(testDate, date2)

    testDate = testDate.dateByAddingMonths(1)!
    XCTAssertEqual(testDate, date3)

    testDate = testDate.dateByAddingMonths(1)!
    XCTAssertEqual(testDate, date4)

    testDate = testDate.dateByAddingMonths(1)!
    XCTAssertEqual(testDate, date5)

    testDate = testDate.dateByAddingMonths(1)!
    XCTAssertEqual(testDate, date6)

    testDate = testDate.dateByAddingMonths(1)!
    XCTAssertEqual(testDate, date7)

    testDate = testDate.dateByAddingMonths(1)!
    XCTAssertEqual(testDate, date8)

    testDate = testDate.dateByAddingMonths(1)!
    XCTAssertEqual(testDate, date9)

    testDate = testDate.dateByAddingMonths(1)!
    XCTAssertEqual(testDate, date10)

    testDate = testDate.dateByAddingMonths(1)!
    XCTAssertEqual(testDate, date11)

    testDate = testDate.dateByAddingMonths(1)!
    XCTAssertEqual(testDate, date12)

    testDate = testDate.dateByAddingMonths(1)!
    XCTAssertEqual(testDate, date13)

    testDate = testDate.dateByAddingMonths(1)!
    XCTAssertEqual(testDate, date14)
}

Der Vollständigkeit halber verwende ich die .asDate () -Methode

extension String {

    static let dateFormatter = DateFormatter()
    func checkIsValidDate() -> Bool {
        return self.tryParseToDate() != nil
    }

    func tryParseToDate() -> Date? {
        String.dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
        return String.dateFormatter.date(from: self)
    }

    func asDate() -> Date {
        return tryParseToDate()!
    }
}

1

Möchten Sie einen "Monat" oder genau 30 Tage oder einen Tag oder ein Jahr hinzufügen, basierend darauf, dass der Benutzer die automatische Berechnung bis heute auswählt.

  NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] 
  init];
    [dateFormatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
    NSDateComponents *components = [calendar components:(NSCalendarUnitHour | NSCalendarUnitMinute) fromDate:[NSDate date]];

        NSDateComponents *dayComponent = [[NSDateComponents alloc] 
 init];
        int changeid = [here number of days intValue];

        dayComponent.hour = changeid;

        NSCalendar *theCalendar = [NSCalendar currentCalendar];
        NSDate *nextDate = [theCalendar 
 dateByAddingComponents:dayComponent toDate:[dateFormatter 
  dateFromString:self.fromDateTF.text] options:0];

        NSLog(@"nextDate: %@ ...", nextDate);
        [self.toDateTF setText:[dateFormatter 
            stringFromDate:nextDate]];

////Monat


-3

Möchten Sie einen "Monat" oder genau 30 Tage hinzufügen? Wenn es 30 Tage sind, machen Sie es so:

// get a date
NSDate *date = [NSDate dateWithNaturalLanguageString:@"2011-01-02"];

// add 30 days to it (in seconds)
date = [date dateByAddingTimeInterval:(30 * 24 * 60 * 60)];

NSLog(@"%@", date); // 2011-02-01

Hinweis: Dies berücksichtigt keine Sommerzeitübergänge oder Schaltsekunden. Verwenden Sie die Antwort von @ TheEye, wenn Sie diese benötigen


2
Dies würde fehlschlagen, wenn es über eine Sommerzeitänderung oder Schaltsekunden usw. verwendet wird.
James Webster

@ JamesWebster, das ist ein sehr guter Punkt. Ich habe meiner Antwort eine Notiz hinzugefügt. Die niedrigen Additions- / Subtraktionssekunden gehören immer noch zu den Antworten. Sie möchten nicht immer Dinge wie die Sommerzeit verfolgen, es hängt davon ab, wofür das Datum verwendet wird.
Abhi Beckert

2
Nein, jeder Monat hat 30 Tage
Adil Malik

Dies fügt keine 30 Tage hinzu. Es werden 30 mal 86.400 Sekunden hinzugefügt, was etwas völlig anderes ist. Diese Art von Code ist ein unglaublich schlechter Rat.
Gnasher729

Es ist wahr, dass dies bei Sommerzeitübergängen zu einem falschen Ergebnis führt. Schaltsekunden sind jedoch kein Problem, da die Unix-Zeit sie nicht zählt.
Martin R
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.