Calculate age from birth date - ios

I cant find age in from birth date. What I got is
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
My code
override func viewDidLoad() {
super.viewDidLoad()
var dateString = user.birthday
var dateFormatter = NSDateFormatter()
// this is imporant - we set our input date format to match our input string
dateFormatter.dateFormat = "dd-MM-yyyy"
// voila!
var dateFromString = dateFormatter.dateFromString(dateString)
let age = calculateAge(dateFromString!)
}
func calculateAge (birthday: NSDate) -> NSInteger {
var userAge : NSInteger = 0
var calendar : NSCalendar = NSCalendar.currentCalendar()
var unitFlags : NSCalendarUnit = NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitDay
var dateComponentNow : NSDateComponents = calendar.components(unitFlags, fromDate: NSDate())
var dateComponentBirth : NSDateComponents = calendar.components(unitFlags, fromDate: birthday)
if ( (dateComponentNow.month < dateComponentBirth.month) ||
((dateComponentNow.month == dateComponentBirth.month) && (dateComponentNow.day < dateComponentBirth.day))
)
{
return dateComponentNow.year - dateComponentBirth.year - 1
}
else {
return dateComponentNow.year - dateComponentBirth.year
}
}

update: Xcode 11 • Swift 5.1
You can use the Calendar method dateComponents to calculate how many years from a specific date to today:
extension Date {
var age: Int { Calendar.current.dateComponents([.year], from: self, to: Date()).year! }
}
let dob = DateComponents(calendar: .current, year: 2000, month: 6, day: 30).date!
let age = dob.age // 19

Important:
The timezone must be set to create a UTC birth date otherwise there will be inconsistencies between timezones.
Swift 3
extension Date {
//An integer representation of age from the date object (read-only).
var age: Int {
get {
let now = Date()
let calendar = Calendar.current
let ageComponents = calendar.dateComponents([.year], from: self, to: now)
let age = ageComponents.year!
return age
}
}
init(year: Int, month: Int, day: Int) {
var dc = DateComponents()
dc.year = year
dc.month = month
dc.day = day
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = TimeZone(secondsFromGMT: 0)!
if let date = calendar.date(from: dc) {
self.init(timeInterval: 0, since: date)
} else {
fatalError("Date component values were invalid.")
}
}
}
Usage:
let dob = Date(year: 1975, month: 1, day: 1)
let age = dob.age
print(age)

In Swift 2.0+ age computing code should look something like this:
extension NSDate {
var age:Int {
return NSCalendar.currentCalendar()
.components(NSCalendarUnit.Year,
fromDate: self,
toDate: NSDate(),
options: NSCalendarOptions(rawValue: 0)
.year
}
}

Just use the DateTools pod. Absolutely the easiest way.
https://github.com/MatthewYork/DateTools
For Swift 3
import DateTools
let birthday: Date = ....
let ageString = String((Date() as NSDate).years(from: birthday))

Related

How to fetch all dates between from Date to Date in Swift 3 [duplicate]

I’m creating a date using NSDateComponents().
let startDate = NSDateComponents()
startDate.year = 2015
startDate.month = 9
startDate.day = 1
let calendar = NSCalendar.currentCalendar()
let startDateNSDate = calendar.dateFromComponents(startDate)!
... now I want to print all dates since the startDate until today, NSDate(). I’ve already tried playing with NSCalendarUnit, but it only outputs the whole difference, not the single dates between.
let unit: NSCalendarUnit = [.Year, .Month, .Day, .Hour, .Minute, .Second]
let diff = NSCalendar.currentCalendar().components(unit, fromDate: startDateNSDate, toDate: NSDate(), options: [])
How can I print all dates between two Dateobjects?
Edit 2019
In the meantime the naming of the classes had changed – NSDate is now just Date. NSDateComponents is now called DateComponents. NSCalendar.currentCalendar() is now just Calendar.current.
Just add one day unit to the date until it reaches
the current date (Swift 2 code):
var date = startDateNSDate // first date
let endDate = NSDate() // last date
// Formatter for printing the date, adjust it according to your needs:
let fmt = NSDateFormatter()
fmt.dateFormat = "dd/MM/yyyy"
// While date <= endDate ...
while date.compare(endDate) != .OrderedDescending {
print(fmt.stringFromDate(date))
// Advance by one day:
date = calendar.dateByAddingUnit(.Day, value: 1, toDate: date, options: [])!
}
Update for Swift 3:
var date = startDate // first date
let endDate = Date() // last date
// Formatter for printing the date, adjust it according to your needs:
let fmt = DateFormatter()
fmt.dateFormat = "dd/MM/yyyy"
while date <= endDate {
print(fmt.string(from: date))
date = Calendar.current.date(byAdding: .day, value: 1, to: date)!
}
Using extension:
extension Date {
static func dates(from fromDate: Date, to toDate: Date) -> [Date] {
var dates: [Date] = []
var date = fromDate
while date <= toDate {
dates.append(date)
guard let newDate = Calendar.current.date(byAdding: .day, value: 1, to: date) else { break }
date = newDate
}
return dates
}
}
Usage:
let datesBetweenArray = Date.dates(from: Date(), to: Date())
Same thing but prettier:
extension Date {
func allDates(till endDate: Date) -> [Date] {
var date = self
var array: [Date] = []
while date <= endDate {
array.append(date)
date = Calendar.current.date(byAdding: .day, value: 1, to: date)!
}
return array
}
}
How to get all dates for next 20 days:
if let date = Calendar.current.date(byAdding: .day, value: 20, to: Date()) {
print(Date().allDates(till: date))
}
Your desired code becomes like
let startDate = NSDateComponents()
startDate.year = 2015
startDate.month = 9
startDate.day = 1
let calendar = NSCalendar.currentCalendar()
let startDateNSDate = calendar.dateFromComponents(startDate)!
var offsetComponents:NSDateComponents = NSDateComponents();
offsetComponents.day = 1
var nd:NSDate = startDateNSDate;
println(nd)
while nd.timeIntervalSince1970 < NSDate().timeIntervalSince1970 {
nd = calendar.dateByAddingComponents(offsetComponents, toDate: nd, options: nil)!;
println(nd)
}
Here is Solution of Print all dates between two Dates (Swift 4 Code)
var mydates : [String] = []
var dateFrom = Date() // First date
var dateTo = Date() // Last date
// Formatter for printing the date, adjust it according to your needs:
let fmt = DateFormatter()
fmt.dateFormat = "yyy-MM-dd"
dateFrom = fmt.date(from: strstartDate)! // "2018-03-01"
dateTo = fmt.date(from: strendDate)! // "2018-03-05"
while dateFrom <= dateTo {
mydates.append(fmt.string(from: dateFrom))
dateFrom = Calendar.current.date(byAdding: .day, value: 1, to: dateFrom)!
}
print(mydates) // Your Result
Output is:
["2018-03-01", "2018-03-02", "2018-03-03", "2018-03-04", "2018-03-05"]
I am using this approach (Swift 3):
import Foundation
class Dates {
static func printDatesBetweenInterval(_ startDate: Date, _ endDate: Date) {
var startDate = startDate
let calendar = Calendar.current
let fmt = DateFormatter()
fmt.dateFormat = "yyyy-MM-dd"
while startDate <= endDate {
print(fmt.string(from: startDate))
startDate = calendar.date(byAdding: .day, value: 1, to: startDate)!
}
}
static func dateFromString(_ dateString: String) -> Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
return dateFormatter.date(from: dateString)!
}
}
and I am calling this like:
Dates.printDatesBetweenInterval(Dates.dateFromString("2017-01-02"), Dates.dateFromString("2017-01-9"))
The output is:
2017-01-02
2017-01-03
2017-01-04
2017-01-05
2017-01-06
2017-01-07
2017-01-08
2017-01-09
You can use the compactMap operator.
I like to put these functions in an extension so they are reusable.
It's hard to make a range of dates, so I made a range of ints and loop through that.
extension Calendar {
func getDates(_ startDate: Date, _ endDate: Date) -> [Date] {
// make sure parameters are valid
guard startDate < endDate else { print("invalid parameters"); return [] }
// how many days between dates?
let dayDiff = Int(self.dateComponents([.day], from: startDate, to: endDate).day ?? 0)
let rangeOfDaysFromStart: Range<Int> = 0..<dayDiff + 1
let dates = rangeOfDaysFromStart.compactMap{ self.date(byAdding: .day, value: $0, to: startDate) }
return dates
}
}
Your usage could be:
let startDate = Date(dateString: "1/2/2017", format: "M/d/yyyy")
let endDate = Date(dateString: "1/9/2017", format: "M/d/yyyy")
let dates = Calendar.current.getDates(startDate, endDate)
let f = DateFormatter(withFormat: "yyyy-MM-dd", locale: "us_en")
print(dates.compactMap{f.string(from: $0)}.joined(separator: ", "))
output:
"2017-01-02, 2017-01-03, 2017-01-04, 2017-01-05, 2017-01-06, 2017-01-07, 2017-01-08, 2017-01-09"

How to get week start date and end date by using any Month and week number swift 3?

I have to implement graph so that I need to get week start date and weekend date if I will pass the date object and week number.
How can I achieve that I tried it but didn't get exactly?
Here below is my code:-
Weekday:-
//Day of week
func getDayOfWeek(today:String)->Int? {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
if let todayDate = formatter.date(from: today) {
let myCalendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)!
let myComponents = myCalendar.components(.weekday, from: todayDate)
let weekDay = myComponents.weekday
return weekDay
} else {
return nil
}
}.
extension Date {
var millisecondsSince1970:Int {
return Int((self.timeIntervalSince1970 * 1000.0).rounded())
}
init(milliseconds:Int) {
self = Date(timeIntervalSince1970: TimeInterval(milliseconds / 1000))
}
func startOfWeek(weekday: Int?) -> Date {
var cal = Calendar.current
var component = cal.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)
component.to12am()
cal.firstWeekday = weekday ?? 1
return cal.date(from: component)!
}
func endOfWeek(weekday: Int) -> Date {
let cal = Calendar.current
var component = DateComponents()
component.weekOfYear = 1
component.day = -1
component.to12pm()
return cal.date(byAdding: component, to: startOfWeek(weekday: weekday))!
}
}
internal extension DateComponents {
mutating func to12am() {
self.hour = 0
self.minute = 0
self.second = 0
}
mutating func to12pm(){
self.hour = 23
self.minute = 59
self.second = 59
}
}
This returns start- and end date for a given week number and date
func dayRangeOf(weekOfYear: Int, for date: Date) -> Range<Date>
{
let calendar = Calendar.current
let year = calendar.component(.yearForWeekOfYear, from: date)
let startComponents = DateComponents(weekOfYear: weekOfYear, yearForWeekOfYear: year)
let startDate = calendar.date(from: startComponents)!
let endComponents = DateComponents(day:7, second: -1)
let endDate = calendar.date(byAdding: endComponents, to: startDate)!
return startDate..<endDate
}
print(dayRangeOf(weekOfYear: 12, for: Date()))
Consider that print displays the dates in UTC and the start date depends on the first weekday setting of the current locale.
Edit
A version to determine the range of a given week of month
func dayRangeOf(weekOfMonth: Int, year: Int, month: Int) -> Range<Date>? {
let calendar = Calendar.current
guard let startOfMonth = calendar.date(from: DateComponents(year:year, month:month)) else { return nil }
var startDate = Date()
if weekOfMonth == 1 {
var interval = TimeInterval()
guard calendar.dateInterval(of: .weekOfMonth, start: &startDate, interval: &interval, for: startOfMonth) else { return nil }
} else {
let nextComponents = DateComponents(year: year, month: month, weekOfMonth: weekOfMonth)
guard let weekStartDate = calendar.nextDate(after: startOfMonth, matching: nextComponents, matchingPolicy: .nextTime) else {
return nil
}
startDate = weekStartDate
}
let endComponents = DateComponents(day:7, second: -1)
let endDate = calendar.date(byAdding: endComponents, to: startDate)!
return startDate..<endDate
}
print(dayRangeOf(weekOfMonth: 5, year: 2017, month: 6))
The result type of the second version is an optional because there are a few calculations which could fail for example if the number of week in the particular month is out of range.
For anyone interested in this, it looks like OP confusing weekOfMonth and weekOfYear…
//: Playground - noun: a place where people can play
import UIKit
var str = "Hello, playground"
let cal = Calendar.current
let dateComponents = DateComponents(year: 2018, month: 3, day: 15)
let date = cal.date(from: dateComponents)!
func weekOfMonthStart(forDate date: Date) -> Date {
var compsToWeekOfMonth = cal.dateComponents([.year, .month, .weekOfYear], from: date)
compsToWeekOfMonth.day = cal.range(of: .day, in: .weekOfMonth, for: date)?.lowerBound
return cal.date(from: compsToWeekOfMonth)!
}
Somebody mention an answer that will fail, so a test was included ;)
for i in 0...5000 {
let newDate = cal.date(byAdding: DateComponents(day:i), to: date)!
weekOfMonthStart(forDate: newDate)
}

How to get start date and end date of the current month (Swift 3)

I'm trying to get the start and end dates of the current month in dd/MM/yyyy format. I tried using extension as answered in this SO Question.But it seems like it's not what I want(the format is different and also it's giving me last month's last date and current month last but one date ). Can some one help me.
Extension Class:
extension Date {
func startOfMonth() -> Date? {
let comp: DateComponents = Calendar.current.dateComponents([.year, .month, .hour], from: Calendar.current.startOfDay(for: self))
return Calendar.current.date(from: comp)!
}
func endOfMonth() -> Date? {
var comp: DateComponents = Calendar.current.dateComponents([.month, .day, .hour], from: Calendar.current.startOfDay(for: self))
comp.month = 1
comp.day = -1
return Calendar.current.date(byAdding: comp, to: self.startOfMonth()!)
}
}
My Struct:
struct Constants{
// keys required for making a Login call (POST Method)
struct LoginKeys {
.....
}
struct RankingKeys {
static let DateFrom = String(describing: Date().startOfMonth()) //giving me 2016-11-30 16:00:00 +0000
static let DateTo = String(describing: Date().endOfMonth())
//2016-12-30 16:00:00 +0000
}
}
Expected Result:
DateFrom = "01/12/2016"
DateTo = "31/12/2016"
You should write this simple code:
let dateFormatter = DateFormatter()
let date = Date()
dateFormatter.dateFormat = "dd-MM-yyyy"
For start Date:
let comp: DateComponents = Calendar.current.dateComponents([.year, .month], from: date)
let startOfMonth = Calendar.current.date(from: comp)!
print(dateFormatter.string(from: startOfMonth))
For end Date:
var comps2 = DateComponents()
comps2.month = 1
comps2.day = -1
let endOfMonth = Calendar.current.date(byAdding: comps2, to: startOfMonth)
print(dateFormatter.string(from: endOfMonth!))
This is what I'm using. Pretty simple but it works.
extension Calendar {
func dayOfWeek(_ date: Date) -> Int {
var dayOfWeek = self.component(.weekday, from: date) + 1 - self.firstWeekday
if dayOfWeek <= 0 {
dayOfWeek += 7
}
return dayOfWeek
}
func startOfWeek(_ date: Date) -> Date {
return self.date(byAdding: DateComponents(day: -self.dayOfWeek(date) + 1), to: date)!
}
func endOfWeek(_ date: Date) -> Date {
return self.date(byAdding: DateComponents(day: 6), to: self.startOfWeek(date))!
}
func startOfMonth(_ date: Date) -> Date {
return self.date(from: self.dateComponents([.year, .month], from: date))!
}
func endOfMonth(_ date: Date) -> Date {
return self.date(byAdding: DateComponents(month: 1, day: -1), to: self.startOfMonth(date))!
}
func startOfQuarter(_ date: Date) -> Date {
let quarter = (self.component(.month, from: date) - 1) / 3 + 1
return self.date(from: DateComponents(year: self.component(.year, from: date), month: (quarter - 1) * 3 + 1))!
}
func endOfQuarter(_ date: Date) -> Date {
return self.date(byAdding: DateComponents(month: 3, day: -1), to: self.startOfQuarter(date))!
}
func startOfYear(_ date: Date) -> Date {
return self.date(from: self.dateComponents([.year], from: date))!
}
func endOfYear(_ date: Date) -> Date {
return self.date(from: DateComponents(year: self.component(.year, from: date), month: 12, day: 31))!
}
}
How to use
let calendar: Calendar = Calendar.current
let startDate = calendar.startOfMonth(Date())
print("startDate :: \(startDate)")
Here is an easy solution in create an extension for Date like following:
extension Date {
func startOfMonth() -> Date {
let interval = Calendar.current.dateInterval(of: .month, for: self)
return (interval?.start.toLocalTime())! // Without toLocalTime it give last months last date
}
func endOfMonth() -> Date {
let interval = Calendar.current.dateInterval(of: .month, for: self)
return interval!.end
}
// Convert UTC (or GMT) to local time
func toLocalTime() -> Date {
let timezone = TimeZone.current
let seconds = TimeInterval(timezone.secondsFromGMT(for: self))
return Date(timeInterval: seconds, since: self)
}}
And then call with your Date instance like that
print(Date().startOfMonth())
print(Date().endOfMonth())
With Swift 3 & iOS 10 the easiest way I found to do this is Calendar's dateInterval(of:for:):
guard let interval = calendar.dateInterval(of: .month, for: Date()) else { return }
Then use a date formatter to print the dates:
let formatter = DateFormatter()
formatter.dateFormat = "dd-MM-yyyy"
let dateText = formatter.string(from: interval.start)
This Extension Gives you expected output as per you want
Here I return date
extension NSDate {
func startOfMonth() -> NSDate? {
guard
let cal: NSCalendar = NSCalendar.currentCalendar(),
let comp: NSDateComponents = cal.components([.Year, .Month], fromDate: self) else { return nil }
comp.to12pm()
let dateformattor = NSDateFormatter()
dateformattor.dateFormat = "yyyy-MM-dd"
dateformattor.timeZone = NSTimeZone.localTimeZone()
let dt2 = dateformattor.stringFromDate(cal.dateFromComponents(comp)!)
print(dt2)
dateformattor.dateFormat = "yyyy-MM-dd"
dateformattor.timeZone = NSTimeZone.init(abbreviation: "UTC")
return dateformattor.dateFromString(dt2)
}
func endOfMonth() -> NSDate? {
guard
let cal: NSCalendar = NSCalendar.currentCalendar(),
let comp: NSDateComponents = NSDateComponents() else { return nil }
comp.month = 1
comp.day = -1
comp.to12pm()
let dateformattor = NSDateFormatter()
dateformattor.dateFormat = "yyyy-MM-dd"
dateformattor.timeZone = NSTimeZone.localTimeZone()
let dt2 = dateformattor.stringFromDate(cal.dateByAddingComponents(comp, toDate: self.startOfMonth()!, options: [])!)
dateformattor.dateFormat = "yyyy-MM-dd"
dateformattor.timeZone = NSTimeZone.init(abbreviation: "UTC")
return dateformattor.dateFromString(dt2)
}
}
internal extension NSDateComponents {
func to12pm() {
self.hour = 12
self.minute = 0
self.second = 0
}
}
**OUTPUT :- **
Start Date of Month :- 2016-12-01 00:00:00 +0000
End Date of Month :- 2016-12-31 00:00:00 +0000
For the sake of completeness, the API dateInterval(of:start:interval:for:) of Calendar assigns the start date and interval (in seconds) of the current month to the inout parameters.
The date formatter considers the current time zone.
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "dd/MM/yyyy"
var startDate = Date()
var interval = TimeInterval()
Calendar.current.dateInterval(of: .month, start: &startDate, interval: &interval, for: Date())
let endDate = Calendar.current.date(byAdding: .second, value: Int(interval) - 1, to: startDate)!
let fromDate = formatter.string(from: startDate)
let toDate = formatter.string(from: endDate)
print(fromDate, toDate)

How to get the current day number in current month and year

I am using this code to get the number of day in the current week:
static func currentDayOfWeek() -> Int {
let comp = NSCalendar.current.dateComponents([.weekday], from: Date())
if comp.weekday == 1 {
return 7
}
return comp.weekday! - 1
}
Monday = 1
Tuesday = 2
...........
Sunday = 7
I can't manage to figure out how to get the current day number of the month and year.
For example for today current day number for the month should be 3 and for the year it should be 277.
Any suggestions ?
let dayYear = Calendar.current.ordinality(of: .day, in: .year, for: Date())
let dayMonth = Calendar.current.ordinality(of: .day, in: .month, for: Date())
func currentDayOfMonth()->Int {
return NSCalendar.currentCalendar().ordinalityOfUnit(NSCalendarUnit.Day, inUnit: NSCalendarUnit.Month, forDate: NSDate())
}
func currentDayOfYear()->Int {
return NSCalendar.currentCalendar().ordinalityOfUnit(NSCalendarUnit.Day, inUnit: NSCalendarUnit.Year, forDate: NSDate())
}
The original answer is from this post.
This will return "Monday" or the day of the week:
func getDayOfWeek(_ today:String) -> String? {
let weekdays = [1:"Sunday", 2:"Monday", 3:"Tuesday", 4:"Wednesday", 5:"Thursday", 6:"Friday", 7:"Saturday"]
let formatter = DateFormatter()
formatter.dateFormat = "MM-dd-yyyy"
if let todayDate = formatter.date(from: today) {
let myCalendar = Calendar(identifier: .gregorian)
let weekDay = myCalendar.component(.weekday, from: todayDate)
let day = weekdays[weekDay]
return day
} else {
return nil
}
}
getDayOfWeek("10-03-2016")
This will return "1" or the day's number for the week:
func getDayOfWeek(_ today:String) -> Int? {
let formatter = DateFormatter()
formatter.dateFormat = "MM-dd-yyyy"
if let todayDate = formatter.date(from: today) {
let myCalendar = Calendar(identifier: .gregorian)
let weekDay = myCalendar.component(.weekday, from: todayDate)
return weekDay
} else {
return nil
}
}
getDayOfWeek("10-03-2016")

Swift - Get last 7 days starting from today in array

How to get previous 7 days of the month I know how to get if today is 18, but what if today id 3rd November? How to get the last 4 days from the previous month(October) in Int?
Use NSCalendar and NSDateComponents:
let cal = NSCalendar.currentCalendar()
// start with today
var date = cal.startOfDayForDate(NSDate())
var days = [Int]()
for i in 1 ... 7 {
// get day component:
let day = cal.component(.DayCalendarUnit, fromDate: date)
days.append(day)
// move back in time by one day:
date = cal.dateByAddingUnit(.DayCalendarUnit, value: -1, toDate: date, options: nil)!
}
println(days)
Update for Swift 2.2 (Xcode 7.3.1):
let cal = NSCalendar.currentCalendar()
var date = cal.startOfDayForDate(NSDate())
var days = [Int]()
for i in 1 ... 7 {
let day = cal.component(.Day, fromDate: date)
days.append(day)
date = cal.dateByAddingUnit(.Day, value: -1, toDate: date, options: [])!
}
print(days)
Update for Swift 3 (Xcode 8 beta 2):
let cal = Calendar.current
var date = cal.startOfDay(for: Date())
var days = [Int]()
for i in 1 ... 7 {
let day = cal.component(.day, from: date)
days.append(day)
date = cal.date(byAdding: .day, value: -1, to: date)!
}
print(days)
Inspired by this answer,
Get list of previous N days as an array of strings.
extension Date {
static func getDates(forLastNDays nDays: Int) -> [String] {
let cal = NSCalendar.current
// start with today
var date = cal.startOfDay(for: Date())
var arrDates = [String]()
for _ in 1 ... nDays {
// move back in time by one day:
date = cal.date(byAdding: Calendar.Component.day, value: -1, to: date)!
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let dateString = dateFormatter.string(from: date)
arrDates.append(dateString)
}
print(arrDates)
return arrDates
}
}
Usage:
let last7Days = Date.getDates(forLastNDays: 7)
debugPrint(last7Days)
//Today(2017-11-19) it prints: ["2017-11-18", "2017-11-17", "2017-11-16", "2017-11-15", "2017-11-14", "2017-11-13", "2017-11-12"]
You can create an extension using Calendar to help you with your calendrical calculations:
Swift 3 or later
extension Date {
var day: Int {
return Calendar.current.component(.day, from: self)
}
func adding(days: Int) -> Date {
return Calendar.current.date(byAdding: .day, value: days, to: self)!
}
var last7days: [Int] {
return (1...7).map {
adding(days: -$0).day
}
}
func near(days: Int) -> [Int] {
return days == 0 ? [day] : (1...abs(days)).map {
adding(days: $0 * (days < 0 ? -1 : 1) ).day
}
}
}
usage:
let last7Days = Date().last7days // [29, 28, 27, 26, 25, 24, 23]
let last7Days2 = Date().near(days: -7) // [29, 28, 27, 26, 25, 24, 23]
let next7Days = Date().near(days: 7) // [27, 28, 29, 30, 31, 1, 2]
Same strategy as #rintaro answer, as short as possible ;) (added support to negative values and made it as a Date extension to be able to use any date as input)
extension Date {
func closest(days: Int) -> [Int] {
return days == 0 ? [] : (1...abs(days)).map { delta -> Int in Calendar.current.component(.day, from: Calendar.current.date(byAdding: .day, value: delta * (days >= 0 ? 1 : -1), to: self)!) }
}
}
usage:
let next7Days2 = Date().closest(days: 7) // [27, 28, 29, 30, 31, 1, 2]
let last7Days3 = Date().closest(days: -7) // [25, 24, 23, 22, 21, 20, 19]
let next2Days = Date().closest(days: 2) // [27, 28]
let last2Days = Date().closest(days: -2) // [25, 24]
Same strategy as #MartinR answer, as short as possible:
let cal = NSCalendar.currentCalendar()
let date = NSDate()
var result = map(-6...0) { delta -> Int in
cal.component(.DayCalendarUnit, fromDate: cal.dateByAddingUnit(.DayCalendarUnit, value: delta, toDate: date, options: nil)!)
}
It's might not be the fastest code. But you get the idea :)
import Foundation
let lastSevenDay: [Int] = {
var days = [Int]()
let secondsInADay: NSTimeInterval = 24 * 60 * 60
let now = NSDate()
let calendar = NSCalendar(calendarIdentifier: NSGregorianCalendar)!
for i in 1...7 {
let theDate = now.dateByAddingTimeInterval(-secondsInADay * NSTimeInterval(7 - i))
let dateComponent = calendar.components(NSCalendarUnit.CalendarUnitDay, fromDate: theDate)
let dayOfMonth = dateComponent.day
days.append(dayOfMonth)
}
return days
}()
I modified the rintaro answer a bit to get past dates in a NSArray of NSDictionaries to get all values including past days, months and years. You only need to call this snippet like this
println(getPastDates(2))
to get a full list with past dates like that
(
{
day = 30;
month = 11;
year = 2014;
},
{
day = 29;
month = 11;
year = 2014;
}
)
func getPastDates(days: Int) -> NSArray {
var dates = NSMutableArray()
let cal = NSCalendar.currentCalendar()
var today = cal.startOfDayForDate(NSDate())
for i in 1 ... days {
let day = cal.component(.DayCalendarUnit, fromDate: today)
let month = cal.component(.MonthCalendarUnit, fromDate: today)
let year = cal.component(.YearCalendarUnit, fromDate: today)
var date = NSMutableDictionary()
date.setValue(day, forKey: "day")
date.setValue(month, forKey: "month")
date.setValue(year, forKey: "year")
dates.addObject(date)
// move back in time by one day:
today = cal.dateByAddingUnit(.DayCalendarUnit, value: -1, toDate: today, options: nil)!
}
return dates
}
I update
Alejandro Luengo's code. It works Swift4
func getPastDates(days: Int) -> NSMutableArray {
let dates = NSMutableArray()
let calendar = Calendar.current
var today = calendar.startOfDay(for: Date())
for _ in 1 ... days {
let day = calendar.component(.day, from: today)
let month = calendar.component(.month, from: today)
let year = calendar.component(.year, from: today)
let date = NSMutableDictionary()
date.setValue(day, forKey: "day")
date.setValue(month, forKey: "month")
date.setValue(year, forKey: "year")
dates.add(date)
today = calendar.date(byAdding: .day, value: -1, to: today)!
}
return dates
}
Swift4
Same strategy as #MartinR, #rintaro answer, as short as possible:
let calendar = Calendar.current
let date = Date()
let result: [Int] = (-6...0).map { delta -> Int in
calendar.component(.day, from: calendar.date(byAdding: .day, value: delta, to: date)!)
}
You want to use NSCalendar to get the last 7 days. Here's a code snippet to demonstrate it in action for 3rd November:
let dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = .ShortStyle
dateFormatter.timeStyle = .NoStyle
dateFormatter.locale = NSLocale(localeIdentifier: "en_GB")
let date = dateFormatter.dateFromString("03/11/14")!
println("date = \(dateFormatter.stringFromDate(date))")
let calendar = NSCalendar(calendarIdentifier: NSGregorianCalendar)!
var previous7days: Array<Int> = []
for i in 0...6 {
let prevDate = calendar.dateByAddingUnit(.CalendarUnitDay, value: -i, toDate: date, options: nil)
previous7days.insert(calendar.component(.CalendarUnitDay, fromDate: prevDate!), atIndex: 0)
}
println("last 7 days: \(previous7days)")

Resources