/*
|
Erica Sadun, http://ericasadun.com
|
iPhone Developer's Cookbook 3.x and beyond
|
BSD License, Use at your own risk
|
*/
|
|
/*
|
#import <humor.h> : Not planning to implement: dateByAskingBoyOut and dateByGettingBabysitter
|
----
|
General Thanks: sstreza, Scott Lawrence, Kevin Ballard, NoOneButMe, Avi`, August Joki. Emanuele Vulcano, jcromartiej, Blagovest Dachev, Matthias Plappert, Slava Bushtruk, Ali Servet Donmez, Ricardo1980, pip8786, Danny Thuerin, Dennis Madsen
|
*/
|
|
#import "NSDate-Utilities.h"
|
|
#define DATE_COMPONENTS (NSYearCalendarUnit| NSMonthCalendarUnit | NSDayCalendarUnit | NSWeekCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSWeekdayCalendarUnit | NSWeekdayOrdinalCalendarUnit)
|
#define CURRENT_CALENDAR [NSDate calendarInstance]
|
|
static NSCalendar *calendar = nil;
|
|
@implementation NSDate (Utilities)
|
|
+ (NSCalendar *)calendarInstance
|
{
|
if (!calendar)
|
{
|
calendar = [NSCalendar currentCalendar];
|
}
|
return calendar;
|
}
|
|
#pragma mark Relative Dates
|
|
+ (NSDate *) dateWithDaysFromNow: (NSInteger) days
|
{
|
NSTimeInterval aTimeInterval = [[NSDate date] timeIntervalSinceReferenceDate] + D_DAY * days;
|
NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
|
return newDate;
|
}
|
|
+ (NSDate *) dateWithDaysBeforeNow: (NSInteger) days
|
{
|
NSTimeInterval aTimeInterval = [[NSDate date] timeIntervalSinceReferenceDate] - D_DAY * days;
|
NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
|
return newDate;
|
}
|
|
+ (NSDate *) dateTomorrow
|
{
|
return [NSDate dateWithDaysFromNow:1];
|
}
|
|
+ (NSDate *) dateYesterday
|
{
|
return [NSDate dateWithDaysBeforeNow:1];
|
}
|
|
+ (NSDate *) dateWithHoursFromNow: (NSInteger) dHours
|
{
|
NSTimeInterval aTimeInterval = [[NSDate date] timeIntervalSinceReferenceDate] + D_HOUR * dHours;
|
NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
|
return newDate;
|
}
|
|
+ (NSDate *) dateWithHoursBeforeNow: (NSInteger) dHours
|
{
|
NSTimeInterval aTimeInterval = [[NSDate date] timeIntervalSinceReferenceDate] - D_HOUR * dHours;
|
NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
|
return newDate;
|
}
|
|
+ (NSDate *) dateWithMinutesFromNow: (NSInteger) dMinutes
|
{
|
NSTimeInterval aTimeInterval = [[NSDate date] timeIntervalSinceReferenceDate] + D_MINUTE * dMinutes;
|
NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
|
return newDate;
|
}
|
|
+ (NSDate *) dateWithMinutesBeforeNow: (NSInteger) dMinutes
|
{
|
NSTimeInterval aTimeInterval = [[NSDate date] timeIntervalSinceReferenceDate] - D_MINUTE * dMinutes;
|
NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
|
return newDate;
|
}
|
|
#pragma mark Comparing Dates
|
|
- (BOOL) isEqualToDateIgnoringTime: (NSDate *) aDate
|
{
|
NSDateComponents *components1 = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:self];
|
NSDateComponents *components2 = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:aDate];
|
return ((components1.year == components2.year) &&
|
(components1.month == components2.month) &&
|
(components1.day == components2.day));
|
}
|
|
- (BOOL) isToday
|
{
|
return [self isEqualToDateIgnoringTime:[NSDate date]];
|
}
|
|
- (BOOL) isTomorrow
|
{
|
return [self isEqualToDateIgnoringTime:[NSDate dateTomorrow]];
|
}
|
|
- (BOOL) isYesterday
|
{
|
return [self isEqualToDateIgnoringTime:[NSDate dateYesterday]];
|
}
|
|
// This hard codes the assumption that a week is 7 days
|
- (BOOL) isSameWeekAsDate: (NSDate *) aDate
|
{
|
NSDateComponents *components1 = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:self];
|
NSDateComponents *components2 = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:aDate];
|
|
// Must be same week. 12/31 and 1/1 will both be week "1" if they are in the same week
|
if (components1.week != components2.week) return NO;
|
|
// Must have a time interval under 1 week. Thanks @aclark
|
return (fabs([self timeIntervalSinceDate:aDate]) < D_WEEK);
|
}
|
|
- (BOOL) isThisWeek
|
{
|
return [self isSameWeekAsDate:[NSDate date]];
|
}
|
|
- (BOOL) isNextWeek
|
{
|
NSTimeInterval aTimeInterval = [[NSDate date] timeIntervalSinceReferenceDate] + D_WEEK;
|
NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
|
return [self isSameWeekAsDate:newDate];
|
}
|
|
- (BOOL) isLastWeek
|
{
|
NSTimeInterval aTimeInterval = [[NSDate date] timeIntervalSinceReferenceDate] - D_WEEK;
|
NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
|
return [self isSameWeekAsDate:newDate];
|
}
|
|
- (BOOL) isSameMonthAsDate: (NSDate *) aDate
|
{
|
NSDateComponents *components1 = [CURRENT_CALENDAR components:NSYearCalendarUnit fromDate:self];
|
NSDateComponents *components2 = [CURRENT_CALENDAR components:NSYearCalendarUnit fromDate:aDate];
|
return ((components1.month == components2.month) &&
|
(components1.year == components2.year));
|
}
|
|
- (BOOL) isThisMonth
|
{
|
return [self isSameMonthAsDate:[NSDate date]];
|
}
|
|
- (BOOL) isSameYearAsDate: (NSDate *) aDate
|
{
|
NSDateComponents *components1 = [CURRENT_CALENDAR components:NSYearCalendarUnit fromDate:self];
|
NSDateComponents *components2 = [CURRENT_CALENDAR components:NSYearCalendarUnit fromDate:aDate];
|
return (components1.year == components2.year);
|
}
|
|
- (BOOL) isThisYear
|
{
|
return [self isSameYearAsDate:[NSDate date]];
|
}
|
|
- (BOOL) isNextYear
|
{
|
NSDateComponents *components1 = [CURRENT_CALENDAR components:NSYearCalendarUnit fromDate:self];
|
NSDateComponents *components2 = [CURRENT_CALENDAR components:NSYearCalendarUnit fromDate:[NSDate date]];
|
|
return (components1.year == (components2.year + 1));
|
}
|
|
- (BOOL) isLastYear
|
{
|
NSDateComponents *components1 = [CURRENT_CALENDAR components:NSYearCalendarUnit fromDate:self];
|
NSDateComponents *components2 = [CURRENT_CALENDAR components:NSYearCalendarUnit fromDate:[NSDate date]];
|
|
return (components1.year == (components2.year - 1));
|
}
|
|
- (BOOL) isEarlierThanDate: (NSDate *) aDate
|
{
|
return ([self compare:aDate] == NSOrderedAscending);
|
}
|
|
- (BOOL) isLaterThanDate: (NSDate *) aDate
|
{
|
return ([self compare:aDate] == NSOrderedDescending);
|
}
|
|
#pragma mark Roles
|
- (BOOL) isTypicallyWeekend
|
{
|
NSDateComponents *components = [CURRENT_CALENDAR components:NSYearCalendarUnit fromDate:self];
|
if ((components.weekday == 1) ||
|
(components.weekday == 7))
|
return YES;
|
return NO;
|
}
|
|
- (BOOL) isTypicallyWorkday
|
{
|
return ![self isTypicallyWeekend];
|
}
|
|
#pragma mark Adjusting Dates
|
|
- (NSDate *) dateByAddingDays: (NSInteger) dDays
|
{
|
NSTimeInterval aTimeInterval = [self timeIntervalSinceReferenceDate] + D_DAY * dDays;
|
NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
|
return newDate;
|
}
|
|
- (NSDate *) dateBySubtractingDays: (NSInteger) dDays
|
{
|
return [self dateByAddingDays: (dDays * -1)];
|
}
|
|
- (NSDate *) dateByAddingHours: (NSInteger) dHours
|
{
|
NSTimeInterval aTimeInterval = [self timeIntervalSinceReferenceDate] + D_HOUR * dHours;
|
NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
|
return newDate;
|
}
|
|
- (NSDate *) dateBySubtractingHours: (NSInteger) dHours
|
{
|
return [self dateByAddingHours: (dHours * -1)];
|
}
|
|
- (NSDate *) dateByAddingMinutes: (NSInteger) dMinutes
|
{
|
NSTimeInterval aTimeInterval = [self timeIntervalSinceReferenceDate] + D_MINUTE * dMinutes;
|
NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
|
return newDate;
|
}
|
|
- (NSDate *) dateBySubtractingMinutes: (NSInteger) dMinutes
|
{
|
return [self dateByAddingMinutes: (dMinutes * -1)];
|
}
|
|
- (NSDate *) dateAtStartOfDay
|
{
|
NSDateComponents *components = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:self];
|
components.hour = 0;
|
components.minute = 0;
|
components.second = 0;
|
return [CURRENT_CALENDAR dateFromComponents:components];
|
}
|
|
- (NSDateComponents *) componentsWithOffsetFromDate: (NSDate *) aDate
|
{
|
NSDateComponents *dTime = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:aDate toDate:self options:0];
|
return dTime;
|
}
|
|
#pragma mark Retrieving Intervals
|
|
- (NSInteger) minutesAfterDate: (NSDate *) aDate
|
{
|
NSTimeInterval ti = [self timeIntervalSinceDate:aDate];
|
return (NSInteger) (ti / D_MINUTE);
|
}
|
|
- (NSInteger) minutesBeforeDate: (NSDate *) aDate
|
{
|
NSTimeInterval ti = [aDate timeIntervalSinceDate:self];
|
return (NSInteger) (ti / D_MINUTE);
|
}
|
|
- (NSInteger) hoursAfterDate: (NSDate *) aDate
|
{
|
NSTimeInterval ti = [self timeIntervalSinceDate:aDate];
|
return (NSInteger) (ti / D_HOUR);
|
}
|
|
- (NSInteger) hoursBeforeDate: (NSDate *) aDate
|
{
|
NSTimeInterval ti = [aDate timeIntervalSinceDate:self];
|
return (NSInteger) (ti / D_HOUR);
|
}
|
|
- (NSInteger) daysAfterDate: (NSDate *) aDate
|
{
|
NSTimeInterval ti = [self timeIntervalSinceDate:aDate];
|
return (NSInteger) (ti / D_DAY);
|
}
|
|
- (NSInteger) daysBeforeDate: (NSDate *) aDate
|
{
|
NSTimeInterval ti = [aDate timeIntervalSinceDate:self];
|
return (NSInteger) (ti / D_DAY);
|
}
|
|
#pragma mark Decomposing Dates
|
|
- (NSInteger) nearestHour
|
{
|
NSTimeInterval aTimeInterval = [[NSDate date] timeIntervalSinceReferenceDate] + D_MINUTE * 30;
|
NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
|
NSDateComponents *components = [CURRENT_CALENDAR components:NSHourCalendarUnit fromDate:newDate];
|
return components.hour;
|
}
|
|
- (NSInteger) hour
|
{
|
NSDateComponents *components = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:self];
|
return components.hour;
|
}
|
|
- (NSInteger) minute
|
{
|
NSDateComponents *components = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:self];
|
return components.minute;
|
}
|
|
- (NSInteger) seconds
|
{
|
NSDateComponents *components = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:self];
|
return components.second;
|
}
|
|
- (NSInteger) day
|
{
|
NSDateComponents *components = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:self];
|
return components.day;
|
}
|
|
- (NSInteger) month
|
{
|
NSDateComponents *components = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:self];
|
return components.month;
|
}
|
|
- (NSInteger) week
|
{
|
NSDateComponents *components = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:self];
|
return components.week;
|
}
|
|
- (NSInteger) weekday
|
{
|
NSDateComponents *components = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:self];
|
return components.weekday;
|
}
|
|
- (NSInteger) nthWeekday // e.g. 2nd Tuesday of the month is 2
|
{
|
NSDateComponents *components = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:self];
|
return components.weekdayOrdinal;
|
}
|
- (NSInteger) year
|
{
|
NSDateComponents *components = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:self];
|
return components.year;
|
}
|
@end
|