Giorgio Giorgio - 4 months ago 52
iOS Question

Working with NSDate components in Swift

I have a date that I need to split in some components. for example

let components = NSCalendarUnit.CalendarUnitDay | NSCalendarUnit.CalendarUnitHour
let date = calendar.components(components, fromDate: aDate, toDate: NSDate(), options: nil)
var dateToPrint = "\(date.day) days \(date.hour) hours"


dateToPrint will be the number of days and hours from aDate to now. But if i want the number of weeks instead of days

let components = NSCalendarUnit.CalendarUnitWeek | NSCalendarUnit.CalendarUnitHour
let date = calendar.components(components, fromDate: aDate, toDate: NSDate(), options: nil)
var dateToPrint = "\(date.week) weeks \(date.hour) hours"


date.week does not exist. So how I could resolve this?

Answer

Swift 3 • Xcode 8 (beta 2)

extension Date {
    func xDays(_ x:Int) -> Date {
        return Calendar.current.date(byAdding: .day, value: x, to: self, options: [])!
    }
    func xWeeks(_ x:Int) -> Date {
        return Calendar.current.date(byAdding: .year, value: x, to: self, options: [])!
    }
    var weeksHoursFromToday: NSDateComponents {
        return Calendar.current.components( [.weekOfYear, .hour], from: self, to: Date(), options: [])
    }
    var relativeDateString: String {
        var result = ""
        let weeks = weeksHoursFromToday.weekOfYear
        let hours = weeksHoursFromToday.hour
        if weeks > 0 {
            result +=  "\(weeks) week"
            if weeks > 1 { result += "s" }
            if hours > 0 { result += " and " }
        }
        if hours > 0 {
            result +=  "\(hours) hour"
            if hours > 1 { result += "s" }
        }
        return result
    }
}

let today              = Date()                  // "Jul 7, 2016, 10:31 PM"
let yesterday          = Date().xDays(-1)        // "Jul 6, 2016, 10:31 PM"
let twoWeeksAgo        = Date().xWeeks(-2)       // "Jul 7, 2014, 10:31 PM"
let anotherDate              = Calendar.current.date(era: 1, year: 2013, month: 12, day: 4, hour: 0, minute: 0, second: 0, nanosecond: 0)!  // "Dec 4, 2013, 12:00 AM"
let anotherDate2              = Calendar.current.date(era: 1, year: 2012, month: 12, day: 3, hour: 0, minute: 0, second: 0, nanosecond: 0)!  // "Dec 3, 2012, 12:00 AM"


yesterday.relativeDateString          // "24 hours"
twoWeeksAgo.relativeDateString        // "104 weeks and 72 hours"
anotherDate.relativeDateString              // ""135 weeks and 46 hours"
anotherDate2.relativeDateString              // "187 weeks and 94 hours"

Swift 2

import Foundation
extension NSDate {
    func xDays(x:Int) -> NSDate {
        return NSCalendar.currentCalendar().dateByAddingUnit(.CalendarUnitDay, value: x, toDate: self, options: nil)!
    }
    func xWeeks(x:Int) -> NSDate {
        return NSCalendar.currentCalendar().dateByAddingUnit(.CalendarUnitWeekOfYear, value: x, toDate: self, options: nil)!
    }
    var weeksHoursFromToday: NSDateComponents{
        return NSCalendar.currentCalendar().components( .CalendarUnitWeekOfYear | .CalendarUnitHour, fromDate: self, toDate: NSDate(), options: nil)
    }
    var relativeDateString: String {
        var result = ""
        let weeks = weeksHoursFromToday.weekOfYear
        let hours = weeksHoursFromToday.hour
        if weeks > 0 {
            result +=  "\(weeks) week"
            if weeks > 1 { result += "s" }
            if hours > 0 { result += " and " }
        }
        if hours > 0 {
            result +=  "\(hours) hour"
            if hours > 1 { result += "s" }
        }
        return result
    }
}

let today              = NSDate()                  // "Jun 26, 2015, 1:05 PM"
let yesterday          = NSDate().xDays(-1)        // "Jun 25, 2015, 1:05 PM"
let twoWeeksAgo        = NSDate().xWeeks(-2)       // "Jun 12, 2015, 1:05 PM"
let date4              = NSCalendar.currentCalendar().dateWithEra(1, year: 2013, month: 12, day: 4, hour: 0, minute: 0, second: 0, nanosecond: 0)!  // "Dec 4, 2013, 12:00 AM"
let date5              = NSCalendar.currentCalendar().dateWithEra(1, year: 2012, month: 12, day: 3, hour: 0, minute: 0, second: 0, nanosecond: 0)!  // "Dec 3, 2012, 12:00 AM"


yesterday.relativeDateString          // "24 hours"
twoWeeksAgo.relativeDateString        // "2 weeks"
date4.relativeDateString              // "81 weeks and 61 hours"
date5.relativeDateString              // "133 weeks and 110 hours"