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)")
Related
I have to show weekdays date in CollectionView start from Monday to Saturday. Until the end of the week, I have to show that weekdays date only. My task image Image. Please help/advise me how to do this task.
I am getting weekdays but its start from current day, But i need start date from monday,
func arrayOfDates() -> NSArray {
let numberOfDays: Int = 6
let formatter: DateFormatter = DateFormatter()
formatter.dateFormat = "dd"
let startDate = Date()
let calendar = Calendar.current
var offset = DateComponents()
var dates: [Any] = [formatter.string(from: startDate)]
for i in 1..<numberOfDays {
offset.day = i
let nextDay: Date? = calendar.date(byAdding: offset, to: startDate)
let nextDayString = formatter.string(from: nextDay!)
dates.append(nextDayString)
}
return dates as NSArray
}
Try this
func formattedDaysInThisWeekNet() -> [String]
{
// create calendar
let calendar = NSCalendar(identifier: NSCalendar.Identifier.gregorian)!
// today's date
let today = NSDate()
let weekday = calendar.component(.weekday, from: today as Date)
let beginningOfWeek : NSDate
if weekday != 2 { // if today is not Monday, get back
beginningOfWeek = calendar.nextDate(after: today as Date, matching: .weekday, value: 1, options: [.matchNextTime, .searchBackwards])! as NSDate
} else { // today is Monday
beginningOfWeek = calendar.startOfDay(for: today as Date) as NSDate
}
var formattedDays = [String]()
for i in 0..<7 {
let date = calendar.date(byAdding: .day, value: i, to: beginningOfWeek as Date, options: [])!
formattedDays.append(formatDate(date: date as NSDate))
let firstDate = calendar.date(byAdding: .day, value: 0, to: beginningOfWeek as Date, options: [])!
let lastDate = calendar.date(byAdding: .day, value: 6, to: beginningOfWeek as Date, options: [])!
let fullString = "\(formatDateFull(date: firstDate as NSDate)) - \(formatDateFull(date: lastDate as NSDate))" as String
fulldateLbl.text = "< \(fullString) >"
print(fullString)
}
return formattedDays
}
enum Days: Int {
case Sat = 0, Sun, Mon, Tue, Wed, Thu, Fri
static var all = [Mon, Tue, Wed, Thu, Fri, Sat]
}
func getWeekDays(date: Date) -> [Date] {
var weekDates = [Date]()
let cal = Calendar.current
var comps = cal.dateComponents([.weekOfYear, .yearForWeekOfYear], from: date)
let days = Days.all
for day in days {
comps.weekday = day.rawValue
weekDates.append(cal.date(from: comps)!)
}
return weekDates
}
print(getWeekDays(date: Date())) // print all dates from Monday to Saturday
Hi guys thank you for your response. I completed This task.
func arrayOfDates() -> NSArray {
var calendar = Calendar(identifier: Calendar.Identifier.gregorian)
let today = calendar.startOfDay(for: Date())
let dayOfWeek = calendar.component(.weekday, from: today) - calendar.firstWeekday
let weekdays = calendar.range(of: .weekday, in: .weekOfYear, for: today)!
let dayss = (weekdays.lowerBound ..< weekdays.upperBound)
.compactMap { calendar.date(byAdding: .day, value: $0 - dayOfWeek, to: today) }
//.filter { !calendar.isDateInWeekend($0) }
let formatter = DateFormatter()
formatter.dateFormat = "dd"
let strings = dayss.map { formatter.string(from: $0) }
self.dates = strings as NSArray
return dates as NSArray
}
But here I have one question, How to disable the previous dates. I need to select only current date and next dates.
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"
in my app I have a list of contacts including the contacts birthday.
Now I want to see which of my contacts have birthday within in the next 7 days.
I am using a filter on my list to filter and return only thos contacts that match
let timeSpan = 7
let cal = Calendar.current
let now = Date()
var birthDays = contactList.filter { (contact) -> Bool in
if let birthDate = contact.birthDate {
let difference = cal.dateComponents([.day,.year], from: birthDate as Date, to: now! )
print("BD:\(birthDate) : DIFF \(difference.day!)")
return ((difference.day! <= timeSpan) && difference.day! >= 0)
}
return false
}
My hope was so. However the result was weired. So I added that ugly print into my closure in order to see the result of 'difference'
What is odd is that for instance the following:
Today is 2017-08-18 one of my contacts was born on 1987-08-19.
So instead of returning a difference.day of 1 I receive 364. If I swap from: and to: in the dateComponents I receive difference.day of -364.
My expectation was to have a difference.day = 1.
Again in Playground
import UIKit
var now = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let s = dateFormatter.date(from: "1987-08-19")
let cal = Calendar.current
let difference = cal.dateComponents([Calendar.Component.day,Calendar.Component.month,Calendar.Component.year], from: s!, to: now )
print("\(difference.day!)") // result is difference.day = 30
What am I doing wrong?
Thanks
You can create an extension to return the number of days from the next birthday as follow:
extension Date {
var year: Int { return Calendar.current.component(.year, from: self) }
var month: Int { return Calendar.current.component(.month, from: self) }
var day: Int { return Calendar.current.component(.day, from: self) }
var noon: Date { return Calendar.current.date(bySettingHour: 12, minute: 0, second: 0, of: self)! }
var daysFromBirthday: Int {
let nextBirthDate = DateComponents(calendar: .current, year: Date().year + (month < Date().month ? 1 : 0), month: month, day: day, hour: 12).date ?? Date.distantFuture
return Calendar.current.dateComponents([.day], from: Date().noon, to: nextBirthDate).day ?? 0
}
}
And you can now filter your objects as follow:
let timeSpan = 0...7
let birthDays = contactList.filter {
timeSpan ~= $0.birthDate?.daysFromBirthday ?? -1
}
The problem was you were checking the difference of the days from the user's birthday but in the app we will need to get the difference between the current date and the birthday during this year. Say in the example that you have said, it's the difference between 2017-08-19(this year's birthday) and 2017-08-18(current date). You could try the code below.
var now = Date()
dateFormatter.dateFormat = "yyyy-MM-dd"
let s = dateFormatter.date(from: "1987-08-19")
let cal = Calendar.current
let currentDateComponentsYear = cal.dateComponents([.year,.month,.day], from: newDate!)
var dateComponents = cal.dateComponents([.year,.month,.day], from: s!)
dateComponents.year = currentDateComponentsYear.year
let currentYearBDay = cal.date(from: dateComponents)
currentDateComponentsYear.month
let difference = cal.dateComponents([Calendar.Component.year,Calendar.Component.month,Calendar.Component.day], from:newDate! , to: currentYearBDay! )
let daysDiffernce:Int?
if dateComponents.month == 1 && currentDateComponentsYear.month == 12 && difference.day! < 0 {
let range = cal.range(of: .day, in: .month, for: newDate!)!
let numDays = range.count
daysDiffernce = difference.day! + numDays
} else {
daysDiffernce = difference.day
}
print("\(daysDiffernce!)") //result 1
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)
}
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))