Làm thế nào để thêm một tháng vào NSDate?


81

Làm thế nào để thêm tháng vào đối tượng NSDate?

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

1
Bạn muốn kết quả nào nếu ngày bắt đầu là ngày 31 tháng 1?
gnasher729

Câu trả lời:


138

Bạn cần sử dụng NSDateComponents :

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

bạn có biết làm thế nào tôi có thể so sánh giữa bây giờ với ngày định mệnh? để kiểm tra xem tôi có vượt qua ngày này không?
hoặc azran

1
So sánh ngày được thực hiện với các hàm NSDate so sánh, ngày trước đó và ngày sau đó - hãy xem tài liệu NSDate cho điều đó: developer.apple.com/library/mac/#documentation/Cocoa/Reference/…
TheEye

1
@orazran bạn có thể so sánh các ngày với : [date timeIntervalSinceDate:otherDate], sẽ trả về sự khác biệt giữa chúng trong vài giây (nhỏ hơn 0 cho các ngày trước, lớn hơn 0 cho các ngày trong tương lai).
Abhi Beckert

126

Với iOS 8 và OS X 10.9, bạn có thể thêm NSCalendarUnitsbằng cách sử dụng NSCalendar:

Objective-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: [])

Các ví dụ trên đang gọi một phương thức, không truy cập một thuộc tính.
Kevin

Swift 3: hãy date = Calendar.current.date (byAdding: .tháng, giá trị: 1, để: Date ())
Maksym Bilan

Đây phải là câu trả lời được chấp nhận. Câu trả lời hiện được chấp nhận là chỉ Objective-C và quá dài dòng.
Colin Basnett

23

Đối với nhanh chóng 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
Điều gì xảy ra nếu tôi thêm 1 tháng vào ngày 31 tháng 1, nó sẽ kết thúc vào ngày 2 tháng 3 hoặc ...?
Michał Ziobro

13

Ví dụ, để thêm 3tháng vào ngày hiện tại trong Swift:

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

Trong Swift 2.0:

let date = NSCalendar.currentCalendar().dateByAddingUnit(.Month, value: 3, toDate: NSDate(), options: [])
  • OptionSetTypeCấu trúc mới của NSCalendarUnitcho phép bạn chỉ định đơn giản hơn.Month
  • Không thể có tham số nhận OptionSetType(như options:tham số lấy NSCalendarOptions) nil, vì vậy hãy chuyển vào một tập hợp trống ( []) để biểu thị "không có tùy chọn".

.MonthCalendarUnitbị phản đối, sử dụng.CalendarUnitMonth
Arnold

3

Trong 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

ĐỐI VỚI SWIFT 3.0

đây là chức năng, bạn có thể giảm ngày, tháng, ngày bằng bất kỳ số nào như ví dụ ở đây, tôi đã giảm năm của ngày hệ thống hiện tại đi 100 năm, bạn có thể làm điều đó cho ngày, tháng cũng chỉ cần đặt bộ đếm và sau đó lưu trữ các giá trị trong mảng và làm bất cứ điều gì bạn muốn làm với mảng đó

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

Các câu trả lời khác hoạt động tốt nếu hành vi mong muốn của bạn là thêm một tháng và cho phép tiết kiệm thời gian ban ngày. Điều này tạo ra kết quả như sau:

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

Tuy nhiên, tôi muốn bỏ qua số giờ bị mất hoặc tăng theo DST, như vậy:

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

Vì vậy, tôi kiểm tra xem ranh giới DST có được vượt qua hay không và nếu có, hãy cộng hoặc trừ một giờ tương ứng:

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
    }

Kiểm tra:

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)
}

Để hoàn thiện, phương thức .asDate () tôi đang sử dụng

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

Bạn có muốn thêm một "tháng" hay chính xác là 30 ngày hoặc một ngày hoặc một năm dựa trên việc người dùng chọn tính toán tự động cho đến nay.

  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]];

////tháng


-3

Bạn muốn thêm "tháng" hay chính xác là 30 ngày? Nếu là 30 ngày, bạn làm như thế này:

// 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

Lưu ý: điều này sẽ không tính đến chuyển đổi thời gian tiết kiệm ánh sáng ban ngày hoặc giây nhuận. Sử dụng câu trả lời của @ TheEye nếu bạn cần


2
Điều này sẽ thất bại nếu sử dụng trên một sự thay đổi DST hoặc giây nhuận, vv
James Webster

@JamesWebster đó là một điểm rất tốt, tôi đã thêm ghi chú bao gồm nó vào câu trả lời của mình. Số giây cộng / trừ cấp độ thấp vẫn thuộc về một trong những câu trả lời. Không phải lúc nào bạn cũng muốn theo dõi những thứ như DST, nó phụ thuộc vào ngày được sử dụng để làm gì.
Abhi Beckert

2
Không có tháng nào cũng có 30 ngày
Adil Malik

Điều này không thêm 30 ngày. Nó cộng thêm 30 lần 86.400 giây, một điều gì đó hoàn toàn khác. Loại mã đó là một lời khuyên cực kỳ tồi tệ.
gnasher729

Đúng là điều này cho kết quả sai trong trường hợp chuyển đổi DST. Tuy nhiên, giây nhuận không phải là vấn đề, vì thời gian Unix không tính chúng.
Martin R
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.