Get last tuesday in month ios - ios

Can get last weekday in the month through NSDateComponents? For example: last monday in month or last friday in month. etc

Just another way to solve. Find the first day of the next month, then search backwards for Tuesday.
let calendar = NSCalendar.currentCalendar()
let today = NSDate()
let components = calendar.components([.Year, .Month], fromDate: today)
components.month += 1
// If today is 2016-07-12 then nextMonth will be the
// first day of the next month: 2016-08-01
if let nextMonth = calendar.dateFromComponents(components) {
// Search backwards for weekday = Tuesday
let options: NSCalendarOptions = [.MatchPreviousTimePreservingSmallerUnits, .SearchBackwards]
calendar.nextDateAfterDate(nextMonth, matchingUnit: .Weekday, value: 3, options: options)
}

Here's a solution; tested, and fairly robust, I think.
We'll let NSCalendar walk through the month, a day at a time, and pull out all matching weekdays as NSDates. Then you can answer questions like, "The 3rd Wednesday of this month"
I believe the comments are clear about what is happening, and why.
If you need further clarification, I'll be happy to do so.
//What weekday are we interested in? 1 = Sunday . . . 7 = Saturday
NSInteger targetWeekday = 1;
//Using this methodology, GMT timezone is important to set
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
calendar.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
//set the components to the first of the current month
NSDateComponents *startComponents = [calendar components:NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
startComponents.day = 1;
//the enumeration starts "afterDate", so shift the start back one day (86400 seconds) to include the 1st of the month
NSDate *startDate = [[calendar dateFromComponents:startComponents] dateByAddingTimeInterval:-86400];
//the enumeration searches for a match; we'll match at the midnight hour and find every occurance of midnight
NSDateComponents *dayByDay = [[NSDateComponents alloc] init];
dayByDay.hour = 0;
//I've opted to put all matching weekdays of the month into an array, so you can find any instance easily
__block NSMutableArray *foundDates = [NSMutableArray arrayWithCapacity:5];
[calendar enumerateDatesStartingAfterDate:startDate
matchingComponents:dayByDay
options:NSCalendarMatchPreviousTimePreservingSmallerUnits
usingBlock:^(NSDate *date, BOOL exactMatch, BOOL *stop){
NSDateComponents *thisComponents = [calendar components:NSCalendarUnitMonth | NSCalendarUnitWeekday fromDate:date];
//as long as the month stays the same... (or the year, if you wanted to)
if (thisComponents.month == startComponents.month) {
//does this date match our target weekday search?
if (thisComponents.weekday == targetWeekday) {
//then add it to our result array
[foundDates addObject:date];
}
//once the month has changed, we're done
} else {
*stop = YES;
}
}];
//Now, with our search result array, we can find the 1st, last, or any specific occurance of that weekday on that month
NSLog(#"Found these: %#", foundDates);
So, if you only wanted the last one, then just use [foundDates lastObject]

Try this code. This works for me.
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comps = [gregorian components:NSWeekdayCalendarUnit fromDate:[NSDate date]];
int weekday = [comps weekday];
int lastTues;
int lastSatDay;
if (weekday==1) {
lastTues=5;
lastSatDay=1;
}
else if (weekday==2)
{
lastTues=6;
lastSatDay=2;
}
else if (weekday==3)
{
lastTues=7;
lastSatDay=3;
}
else if (weekday==4)
{
lastTues=1;
lastSatDay=4;
}
else if (weekday==5)
{
lastTues=2;
lastSatDay=5;
}
else if (weekday==6)
{
lastTues=3;
lastSatDay=6;
}
else if (weekday==7)
{
lastTues=4;
lastSatDay=7;
}
NSDate *lastTuesDay = [[NSDate date] addTimeInterval:-3600*24*(lastTues)];
NSDate *lastSaturday = [[NSDate date] addTimeInterval:-3600*24*(lastSatDay)];

Related

How do I get the NSDates from a week? Provided I know the weekOfMonth

I need to know the NSDate's present in a particular week. I know the weekOfMonth, month and year.
For example, if my weekOfMonth is 0 and month is 2 and the year is 2016. I want to get the dates available in the current week (from Sunday to Saturday). But as the first day of this week (Sunday) falls on the previous month, I need to get the dates from 1-Feb-2016 to 6-Feb-2016 (Monday to Saturday).
NSDateComponents *comp = [[NSDateComponents alloc] init];
comp.month = components.month;
comp.year = components.year;
comp.day = ??; // What should I give here to get the current start date of the week?
Or if I could know the start date and end date of the current week, that would be also helpful.
here's a slightly clunky approach, based on getting the date using dayOfWeek = 0, and then stepping forward until the resultant date is in the same month
int monthTarget = 2;
int dayOfWeekTarget = 0;
int yearTarget = 2016;
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *comp = [[NSDateComponents alloc] init];
[comp setMonth:monthTarget];
[comp setYear:yearTarget];
[comp setWeekOfMonth:dayOfWeekTarget];
[comp setDay:dayOfWeekTarget];
// see what this gives us
NSDate *firstDate = [calendar dateFromComponents:comp];
NSDateComponents *firstDayComponents = [calendar components:NSCalendarUnitMonth | NSCalendarUnitDay fromDate:firstDate];
NSInteger day = [firstDayComponents day];
NSInteger month = [firstDayComponents month];
// move forward if we have to
while (month < monthTarget)
{
dayOfWeekTarget++;
[comp setDay:dayOfWeekTarget];
firstDate = [calendar dateFromComponents:comp];
firstDayComponents = [calendar components:NSCalendarUnitMonth | NSCalendarUnitDay fromDate:firstDate];
day = [firstDayComponents day];
month = [firstDayComponents month];
}
I'm sure you can tidy this up a bit, but the approach is here!

Calculating certain NSDates from days of weeks/weeks of years

Is there an easy way to calculate dates according to a criteria with NSCalendar and/or NSCalendarComponents? I've been looking at the documentation for a while but it seems a bit complicated. For example, I need
"Wednesday 6:00pm"s for the next 15 even-numbered weeks (including this one if it's even numbered and not past that date/time yet.)
Here is a method for determining which Wednesday to start with and then getting the next 14 even week Wednesdays. This doesn't take the time portion of your question into account, but you can use similar methods to handle the time.
+ (NSArray *)nextFifteenEvenNumberedWeekWednesdays:(NSDate *)startingDate
{
static const NSInteger Wednesday = 4;
static const NSInteger OneDay = 60 * 60 * 24;
NSCalendar *calender = [NSCalendar currentCalendar];
NSDateComponents *startingDateComponents = [calender components:(NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitWeekday | NSCalendarUnitWeekOfYear)
fromDate:startingDate];
// Go to the closest Wednesday
NSInteger daysToWednesday = Wednesday - startingDateComponents.weekday;
if (startingDateComponents.weekday > Wednesday) {
// We already passed wednesday, so go to the next wednesday
if (startingDateComponents.weekOfYear % 2 == 0) {
// If this date is past Wednesday but is on an even week, then moving to the next wednesday
// will be an odd week. So skip forward one week.
startingDate = [startingDate dateByAddingTimeInterval:7 * OneDay];
}
daysToWednesday = 7 + daysToWednesday; // get the next Wednesday
}
startingDate = [startingDate dateByAddingTimeInterval:daysToWednesday * OneDay]; // Move to wednesday
NSMutableArray *wednesdays = [NSMutableArray array];
for (NSInteger i = 0; i < 15; i++) {
// Add every other wednesday
[wednesdays addObject:[startingDate dateByAddingTimeInterval:14 * i * OneDay]];
}
return [wednesdays copy];
}
I ended up answering my own question. It's really easy when you know -[NSCalendar dateBySettingUnit:value:ofDate:options:] auto-increments forward to the next matching date.
NSCalendar *calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierISO8601];
NSDate *date = [NSDate date];
// find the next Wednesday 6 o'clock
date = [calendar dateBySettingUnit:NSCalendarUnitSecond value:0 ofDate:date options:0];
date = [calendar dateBySettingUnit:NSCalendarUnitMinute value:0 ofDate:date options:0];
date = [calendar dateBySettingUnit:NSCalendarUnitHour value:18 ofDate:date options:0];
date = [calendar dateBySettingUnit:NSCalendarUnitWeekday value:4 ofDate:date options:0];
// skip one week if it's not an even week
NSDateComponents *components = [calendar components:NSCalendarUnitWeekOfYear fromDate:date];
date = [calendar dateByAddingUnit:NSCalendarUnitWeekOfYear value:components.weekOfYear % 2 toDate:date options:0];
// 15 weeks of this
for (int i = 0; i < 15; i++)
{
NSDate *testDate = [calendar dateByAddingUnit:NSCalendarUnitWeekOfYear value:i * 2 toDate:date options:0];
NSLog(#"Date: %#", testDate);
}

NSCalendar - ordinal number of week changes at 23:58:45

I'm trying to get the ordinal number of a week using NSCalendar so that I can calculate the number of weeks between two dates, however the method I'm using is demonstrating some weird behaviour.
I'm expecting a new week to begin every Sunday at 00:00:00, but instead it seems to happen at 23:58:45. I've tried changing the firstWeekday property of the calendar but that doesn't have any effect.
Example Code (note: 2014-03-09 is a Sunday)
- (void)testTimeWeeksBegins
{
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
// Make NSDates
NSDateComponents *comps = [[NSDateComponents alloc] init];
comps.year = 2014;
comps.month = 3;
comps.day = 9;
comps.hour = 23;
comps.minute = 58;
comps.second = 44;
NSDateComponents *compsToAdd = [[NSDateComponents alloc] init];
compsToAdd.second = 1;
NSDate *date23_58_44 = [calendar dateFromComponents:comps];
NSDate *date23_58_45 = [calendar dateByAddingComponents:compsToAdd toDate:date23_58_44 options:0];
// Calculate ordinality of week on both dates
NSUInteger ord23_58_44 = [calendar ordinalityOfUnit:NSWeekOfYearCalendarUnit inUnit:NSEraCalendarUnit forDate:date23_58_44];
NSUInteger ord23_58_45 = [calendar ordinalityOfUnit:NSWeekOfYearCalendarUnit inUnit:NSEraCalendarUnit forDate:date23_58_45];
// Output
NSLog(#"Date is %# and week number is %d", date23_58_44, ord23_58_44);
NSLog(#"Date is %# and week number is %d", date23_58_45, ord23_58_45);
}
Output
Date is 2014-03-09 23:58:44 +0000 and week number is 105043
Date is 2014-03-09 23:58:45 +0000 and week number is 105044
Am I being stupid and missing something obvious or is this a bug? I suppose my workaround would be to use a date with a time after 23:58:45, to ensure no problems in future?

NSCalendar, why does setting the firstWeekday doesn't effect calculation outcome?

i need to calculate the weekday for a given date, however, depending on the calendar a week can star on Monday and somwhere on Sunday
so i wanted to set it, to start on Monday, using
[[NSCalendar currentCalendar] setFirstWeekday:2];
however, the calculation outcome is the same
{
[[NSCalendar currentCalendar] setFirstWeekday:1];
NSDateComponents *weekdayComponents = [[NSCalendar currentCalendar] components:(NSDayCalendarUnit | NSWeekdayCalendarUnit) fromDate:date];
NSInteger weekday = [weekdayComponents weekday] - 1;
NSLog(#"%d", weekday);
}
{
[[NSCalendar currentCalendar] setFirstWeekday:2];
NSDateComponents *weekdayComponents = [[NSCalendar currentCalendar] components:(NSDayCalendarUnit | NSWeekdayCalendarUnit) fromDate:date];
NSInteger weekday = [weekdayComponents weekday] - 1;
NSLog(#"%d", weekday);
}
returns same numbers, but why?
The behavior you see is correct. The weekday component is not affected by the firstWeekday property. If you have a date representing a sunday it will always be a sunday wether you start your week on that sunday or on monday. What this should affect is the week number in the week property of your date components.
I believe you need to use the ordinalityOfUnit:inUnit:forDate: method rather than attempting to extract the date components. So something like this:
NSUInteger weekday = [[NSCalendar currentCalendar] ordinalityOfUnit:NSWeekdayCalendarUnit inUnit:NSWeekCalendarUnit forDate:date];
Basically that call is asking for the day (NSWeekdayCalendarUnit) in the week (NSWeekCalendarUnit) for the given date.
If that doesn't work as is, you may need to create your own calendar, rather than trying to modifying the first week day on the currentCalendar.
For example:
NSCalendarIdentifier calendarIdentifier = [[NSCalendar currentCalendar] calendarIdentifier];
NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:calendarIdentifier] autorelease];
[calendar setFirstWeekday:2];
Then use that new calendar object rather than [NSCalendar currentCalendar] in the ordinalityOfUnit:inUnit:forDate: call.
A useful function to get corrected weekday number for different firstWeekday cases
Swift 3.0
func dayOfWeek(day: Int, month: Int, year: Int) -> Int {
let calendar = Calendar.current
let dateComponents = DateComponents(year: year, month: month, day: day)
guard let date = calendar.date(from: dateComponents) else {
fatalError("Can't create date form specified date components")
}
var weekday = calendar.component(.weekday, from: date)
//handling the case when calendar starts from Monday: firstWeekday == 2
if calendar.firstWeekday == 2 {
weekday = (weekday == 1) ? 7 : (weekday - 1)
}
return weekday
}

How to determine if an NSDate is today?

How to check if an NSDate belongs to today?
I used to check it using first 10 characters from [aDate description]. [[aDate description] substringToIndex:10] returns string like "YYYY-MM-DD" so I compared the string with the string returned by [[[NSDate date] description] substringToIndex:10].
Is there more fast and/or neat way to check?
Thanks.
In macOS 10.9+ & iOS 8+, there's a method on NSCalendar/Calendar that does exactly this!
- (BOOL)isDateInToday:(NSDate *)date
So you'd simply do
Objective-C:
BOOL today = [[NSCalendar currentCalendar] isDateInToday:date];
Swift 3:
let today = Calendar.current.isDateInToday(date)
You can compare date components:
NSDateComponents *otherDay = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:aDate];
NSDateComponents *today = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:[NSDate date]];
if([today day] == [otherDay day] &&
[today month] == [otherDay month] &&
[today year] == [otherDay year] &&
[today era] == [otherDay era]) {
//do stuff
}
Edit:
I like stefan's method more, I think it makes for a cleaner and more understandable if statement:
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components = [cal components:(NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:[NSDate date]];
NSDate *today = [cal dateFromComponents:components];
components = [cal components:(NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:aDate];
NSDate *otherDate = [cal dateFromComponents:components];
if([today isEqualToDate:otherDate]) {
//do stuff
}
Chris, I've incorporated your suggestion. I had to look up what era was, so for anyone else who doesn't know, it distinguishes between BC and AD. This is probably unnecessary for most people, but it's easy to check and adds some certainty, so I've included it. If you're going for speed, this probably isn't a good method anyway.
NOTE as with many answers on SO, after 7 years this is totally out of date. In Swift now just use .isDateInToday
This is an offshoot to your question, but if you want to print an NSDate with "Today" or "Yesterday", use the function
- (void)setDoesRelativeDateFormatting:(BOOL)b
for NSDateFormatter
I would try to get today's date normalized to midnight and the second date, normalize to midnight then compare if it is the same NSDate.
From an Apple example here's how you normalize to midnight today's date, do the same for the second date and compare:
NSCalendar * gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents * components =
[gregorian components:
(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit)
fromDate:[NSDate date]];
NSDate * today = [gregorian dateFromComponents:components];
Working Swift extension of the suggestion by Catfish_Man:
extension Date {
var isToday: Bool {
Calendar.current.isDateInToday(self)
}
}
No need to juggle with components, eras and stuff.
NSCalendar provides an method to get the beginning of a certain time unit for an existing date.
This code will get the begin of today and another date and compare that. If it evaluates to NSOrderedSame, both dates are during the same day — so today.
NSDate *today = nil;
NSDate *beginningOfOtherDate = nil;
NSDate *now = [NSDate date];
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&today interval:NULL forDate:now];
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit startDate:&beginningOfOtherDate interval:NULL forDate:beginningOfOtherDate];
if([today compare:beginningOfOtherDate] == NSOrderedSame) {
//otherDate is a date in the current day
}
extension NSDate {
func isToday() -> Bool {
let cal = NSCalendar.currentCalendar()
var components = cal.components([.Era, .Year, .Month, .Day], fromDate:NSDate())
let today = cal.dateFromComponents(components)!
components = cal.components([.Era, .Year, .Month, .Day], fromDate:self)
let otherDate = cal.dateFromComponents(components)!
return today.isEqualToDate(otherDate)
}
Worked for me on Swift 2.0
Swift version of the best answer:
let cal = NSCalendar.currentCalendar()
var components = cal.components([.Era, .Year, .Month, .Day], fromDate:NSDate())
let today = cal.dateFromComponents(components)!
components = cal.components([.Era, .Year, .Month, .Day], fromDate:aDate);
let otherDate = cal.dateFromComponents(components)!
if(today.isEqualToDate(otherDate)) {
//do stuff
}
Refer to Apple's documentation entry entitled "Performing Calendar Calculations" [link].
Listing 13 on that page suggests that to determine the number of midnights between days, you use:
- (NSInteger)midnightsFromDate:(NSDate *)startDate toDate:(NSDate *)endDate
{
NSCalendar *calendar = [NSCalendar autoupdatingCurrentCalendar];
NSInteger startDay = [calendar ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSEraCalendarUnit
forDate:startDate];
NSInteger endDay = [calendar ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSEraCalendarUnit
forDate:endDate];
return endDay - startDay;
}
You may then determine if two days are the same by using that method and seeing if it returns 0 or not.
You could also check the time interval between the date you have, and the current date:
[myDate timeIntervalSinceNow]
This will give you the time interval, in seconds, between myDate and the current date/time.
Link.
Edit: Note to everyone: I'm well aware that [myDate timeIntervalSinceNow] does not unambiguously determine whether myDate is today.
I am leaving this answer as is so that if someone is looking for something similar and [myDate timeIntervalSinceNow] is useful, they may find it here.
Swift Extension based on the best answers:
extension NSDate {
func isToday() -> Bool {
let cal = NSCalendar.currentCalendar()
if cal.respondsToSelector("isDateInToday:") {
return cal.isDateInToday(self)
}
var components = cal.components((.CalendarUnitEra | .CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay), fromDate:NSDate())
let today = cal.dateFromComponents(components)!
components = cal.components((.CalendarUnitEra | .CalendarUnitYear | .CalendarUnitMonth | .CalendarUnitDay), fromDate:self);
let otherDate = cal.dateFromComponents(components)!
return today.isEqualToDate(otherDate)
}
}
If you have a lot of these date comparisons, then the calls to calendar:components:fromDate start to take up a lot of time. According to some profiling I have done, they seem to be quite expensive.
Say you are trying to determine which from some array of dates, say NSArray *datesToCompare, are the same day as some given day, say NSDate *baseDate, then you can use something like the following (partly adapted from an answer above):
NSDate *baseDate = [NSDate date];
NSArray *datesToCompare = [NSArray arrayWithObjects:[NSDate date],
[NSDate dateWithTimeIntervalSinceNow:100],
[NSDate dateWithTimeIntervalSinceNow:1000],
[NSDate dateWithTimeIntervalSinceNow:-10000],
[NSDate dateWithTimeIntervalSinceNow:100000],
[NSDate dateWithTimeIntervalSinceNow:1000000],
[NSDate dateWithTimeIntervalSinceNow:50],
nil];
// determine the NSDate for midnight of the base date:
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateComponents* comps = [calendar components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit)
fromDate:baseDate];
NSDate* theMidnightHour = [calendar dateFromComponents:comps];
// set up a localized date formatter so we can see the answers are right!
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
// determine which dates in an array are on the same day as the base date:
for (NSDate *date in datesToCompare) {
NSTimeInterval interval = [date timeIntervalSinceDate:theMidnightHour];
if (interval >= 0 && interval < 60*60*24) {
NSLog(#"%# is on the same day as %#", [dateFormatter stringFromDate:date], [dateFormatter stringFromDate:baseDate]);
}
else {
NSLog(#"%# is NOT on the same day as %#", [dateFormatter stringFromDate:date], [dateFormatter stringFromDate:baseDate]);
}
}
Output:
Nov 23, 2011 1:32:00 PM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 1:33:40 PM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 1:48:40 PM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 10:45:20 AM is on the same day as Nov 23, 2011 1:32:00 PM
Nov 24, 2011 5:18:40 PM is NOT on the same day as Nov 23, 2011 1:32:00 PM
Dec 5, 2011 3:18:40 AM is NOT on the same day as Nov 23, 2011 1:32:00 PM
Nov 23, 2011 1:32:50 PM is on the same day as Nov 23, 2011 1:32:00 PM
There is an easier way than many of the above answers!
NSDate *date = ... // The date you wish to test
NSCalendar *calendar = [NSCalendar currentCalendar];
if([calendar isDateInToday:date]) {
//do stuff
}
This could probably be reworked as an NSDate category, but i used:
// Seconds per day (24h * 60m * 60s)
#define kSecondsPerDay 86400.0f
+ (BOOL) dateIsToday:(NSDate*)dateToCheck
{
// Split today into components
NSCalendar* gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents* comps = [gregorian components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit)
fromDate:[NSDate date]];
// Set to this morning 00:00:00
[comps setHour:0];
[comps setMinute:0];
[comps setSecond:0];
NSDate* theMidnightHour = [gregorian dateFromComponents:comps];
[gregorian release];
// Get time difference (in seconds) between date and then
NSTimeInterval diff = [dateToCheck timeIntervalSinceDate:theMidnightHour];
return ( diff>=0.0f && diff<kSecondsPerDay );
}
(However, comparing the two date strings as in the original question almost feels 'cleaner'..)
for iOS7 and earlier:
//this is now => need that for the current date
NSDate * now = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar setTimeZone:[NSTimeZone systemTimeZone]];
NSDateComponents * components = [calendar components:( NSYearCalendarUnit| NSMonthCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate: now];
[components setMinute:0];
[components setHour:0];
[components setSecond:0];
//this is Today's Midnight
NSDate *todaysMidnight = [calendar dateFromComponents: components];
//now timeIntervals since Midnight => in seconds
NSTimeInterval todayTimeInterval = [now timeIntervalSinceDate: todaysMidnight];
//now timeIntervals since OtherDate => in seconds
NSTimeInterval otherDateTimeInterval = [now timeIntervalSinceDate: otherDate];
if(otherDateTimeInterval > todayTimeInterval) //otherDate is not in today
{
if((otherDateTimeInterval - todayTimeInterval) <= 86400) //86400 == a day total seconds
{
#"yesterday";
}
else
{
#"earlier";
}
}
else
{
#"today";
}
now = nil;
calendar = nil;
components = nil;
todaysMidnight = nil;
NSLog("Thank you :-)");
Check our Erica Sadun's great NSDate extension. Very simple to use. Fine it here:
http://github.com/erica/NSDate-Extensions
It's already there in this post: https://stackoverflow.com/a/4052798/362310
The correct and safe solution without force-unwrapping, working on Swift 2.2 and before iOS 8:
func isToday() -> Bool {
let calendar = NSCalendar.currentCalendar()
if #available(iOS 8.0, *) {
return calendar.isDateInToday(self)
}
let todayComponents = calendar.components([.Era, .Year, .Month, .Day], fromDate:NSDate())
let dayComponents = calendar.components([.Era, .Year, .Month, .Day], fromDate:self)
guard let today = calendar.dateFromComponents(todayComponents),
day = calendar.dateFromComponents(dayComponents) else {
return false
}
return today.compare(day) == .OrderedSame
}
Here's my 2 cent answer building on the accepted answer but supporting the newer API as well. Note: I use the Gregorian calendar as most time stamps are GMT but change yours as you see fit
func isDateToday(date: NSDate) -> Bool {
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
if calendar.respondsToSelector("isDateInToday:") {
return calendar.isDateInToday(date)
}
let dateComponents = NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitDay
let today = calendar.dateFromComponents(calendar.components(dateComponents, fromDate: NSDate()))!
let dateToCompare = calendar.dateFromComponents(calendar.components(dateComponents, fromDate: date))!
return dateToCompare == today
}
My solution is calculate how much days passed since 1970 by division and compare the integer part
#define kOneDay (60*60*24)
- (BOOL)isToday {
NSInteger offset = [[NSTimeZone defaultTimeZone] secondsFromGMT];
NSInteger days =[self timeIntervalSince1970] + offset;
NSInteger currentDays = [[NSDate date] timeIntervalSince1970] + offset;
return (days / kOneDay == currentDays / kOneDay);
}
NSDate *dateOne = yourDate;
NSDate *dateTwo = [NSDate date];
switch ([dateOne compare:dateTwo])
{
case NSOrderedAscending:
NSLog(#”NSOrderedAscending”);
break;
case NSOrderedSame:
NSLog(#”NSOrderedSame”);
break;
case NSOrderedDescending:
NSLog(#”NSOrderedDescending”);
break;
}

Resources