| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545 |
- /*
- 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
-
- Include GMT and time zone utilities?
- */
- #import "NSDate+Utilities.h"
- // Thanks, AshFurrow
- static const unsigned componentFlags = (NSCalendarUnitYear |
- NSCalendarUnitMonth |
- NSCalendarUnitDay |
- NSCalendarUnitHour |
- NSCalendarUnitMinute|
- NSCalendarUnitSecond|
- NSCalendarUnitWeekday |
- NSCalendarUnitWeekdayOrdinal);
- @implementation NSDate (Utilities)
- // Courtesy of Lukasz Margielewski
- // Updated via Holger Haenisch
- + (NSCalendar *) currentCalendar
- {
- static NSCalendar *sharedCalendar = nil;
- if (!sharedCalendar)
- sharedCalendar = [NSCalendar autoupdatingCurrentCalendar];
- return sharedCalendar;
- }
- #pragma mark - Relative Dates
- + (NSDate *) systemDate {
- NSDate* sourceDate = [NSDate date];
-
- NSTimeZone* sourceTimeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
- NSTimeZone* destinationTimeZone = [NSTimeZone systemTimeZone];
-
- NSInteger sourceGMTOffset = [sourceTimeZone secondsFromGMTForDate:sourceDate];
- NSInteger destinationGMTOffset = [destinationTimeZone secondsFromGMTForDate:sourceDate];
- NSTimeInterval interval = destinationGMTOffset - sourceGMTOffset;
-
- return [NSDate dateWithTimeInterval:interval sinceDate:sourceDate];
- }
- + (NSDate *) dateWithDaysFromNow: (NSInteger) days
- {
- // Thanks, Jim Morrison
- return [[NSDate date] dateByAddingDays:days];
- }
- + (NSDate *) dateWithDaysBeforeNow: (NSInteger) days
- {
- // Thanks, Jim Morrison
- return [[NSDate date] dateBySubtractingDays:days];
- }
- + (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 - String Properties
- - (NSString *) stringWithFormat: (NSString *) format
- {
- NSDateFormatter *df = [NSDateFormatter new];
- // formatter.locale = [NSLocale currentLocale]; // Necessary?
- df.dateFormat = format;
- return [df stringFromDate:self];
- }
- - (NSString *) stringWithDateStyle: (NSDateFormatterStyle) dateStyle timeStyle: (NSDateFormatterStyle) timeStyle
- {
- NSDateFormatter *df = [NSDateFormatter new];
- df.dateStyle = dateStyle;
- df.timeStyle = timeStyle;
- // formatter.locale = [NSLocale currentLocale]; // Necessary?
- return [df stringFromDate:self];
- }
- - (NSString *) shortString
- {
- return [self stringWithDateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterShortStyle];
- }
- - (NSString *) shortTimeString
- {
- return [self stringWithDateStyle:NSDateFormatterNoStyle timeStyle:NSDateFormatterShortStyle];
- }
- - (NSString *) shortDateString
- {
- return [self stringWithDateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterNoStyle];
- }
- - (NSString *) mediumString
- {
- return [self stringWithDateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterMediumStyle ];
- }
- - (NSString *) mediumTimeString
- {
- return [self stringWithDateStyle:NSDateFormatterNoStyle timeStyle:NSDateFormatterMediumStyle ];
- }
- - (NSString *) mediumDateString
- {
- return [self stringWithDateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterNoStyle];
- }
- - (NSString *) longString
- {
- return [self stringWithDateStyle:NSDateFormatterLongStyle timeStyle:NSDateFormatterLongStyle ];
- }
- - (NSString *) longTimeString
- {
- return [self stringWithDateStyle:NSDateFormatterNoStyle timeStyle:NSDateFormatterLongStyle ];
- }
- - (NSString *) longDateString
- {
- return [self stringWithDateStyle:NSDateFormatterLongStyle timeStyle:NSDateFormatterNoStyle];
- }
- #pragma mark - Comparing Dates
- - (BOOL) isEqualToDateIgnoringTime: (NSDate *) aDate
- {
- NSDateComponents *components1 = [[NSDate currentCalendar] components:componentFlags fromDate:self];
- NSDateComponents *components2 = [[NSDate currentCalendar] components:componentFlags 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 = [[NSDate currentCalendar] components:componentFlags fromDate:self];
- NSDateComponents *components2 = [[NSDate currentCalendar] components:componentFlags 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.weekOfMonth != components2.weekOfMonth) 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];
- }
- // Thanks, mspasov
- - (BOOL) isSameMonthAsDate: (NSDate *) aDate
- {
- NSDateComponents *components1 = [[NSDate currentCalendar] components:NSCalendarUnitYear | NSCalendarUnitMonth fromDate:self];
- NSDateComponents *components2 = [[NSDate currentCalendar] components:NSCalendarUnitYear | NSCalendarUnitMonth fromDate:aDate];
- return ((components1.month == components2.month) &&
- (components1.year == components2.year));
- }
- - (BOOL) isThisMonth
- {
- return [self isSameMonthAsDate:[NSDate date]];
- }
- // Thanks Marcin Krzyzanowski, also for adding/subtracting years and months
- - (BOOL) isLastMonth
- {
- return [self isSameMonthAsDate:[[NSDate date] dateBySubtractingMonths:1]];
- }
- - (BOOL) isNextMonth
- {
- return [self isSameMonthAsDate:[[NSDate date] dateByAddingMonths:1]];
- }
- - (BOOL) isSameYearAsDate: (NSDate *) aDate
- {
- NSDateComponents *components1 = [[NSDate currentCalendar] components:NSCalendarUnitYear fromDate:self];
- NSDateComponents *components2 = [[NSDate currentCalendar] components:NSCalendarUnitYear fromDate:aDate];
- return (components1.year == components2.year);
- }
- - (BOOL) isThisYear
- {
- // Thanks, baspellis
- return [self isSameYearAsDate:[NSDate date]];
- }
- - (BOOL) isNextYear
- {
- NSDateComponents *components1 = [[NSDate currentCalendar] components:NSCalendarUnitYear fromDate:self];
- NSDateComponents *components2 = [[NSDate currentCalendar] components:NSCalendarUnitYear fromDate:[NSDate date]];
-
- return (components1.year == (components2.year + 1));
- }
- - (BOOL) isLastYear
- {
- NSDateComponents *components1 = [[NSDate currentCalendar] components:NSCalendarUnitYear fromDate:self];
- NSDateComponents *components2 = [[NSDate currentCalendar] components:NSCalendarUnitYear 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);
- }
- // Thanks, markrickert
- - (BOOL) isInFuture
- {
- return ([self isLaterThanDate:[NSDate date]]);
- }
- // Thanks, markrickert
- - (BOOL) isInPast
- {
- return ([self isEarlierThanDate:[NSDate date]]);
- }
- #pragma mark - Roles
- - (BOOL) isTypicallyWeekend
- {
- NSDateComponents *components = [[NSDate currentCalendar] components:NSCalendarUnitWeekday fromDate:self];
- if ((components.weekday == 1) ||
- (components.weekday == 7))
- return YES;
- return NO;
- }
- - (BOOL) isTypicallyWorkday
- {
- return ![self isTypicallyWeekend];
- }
- #pragma mark - Adjusting Dates
- // Thaks, rsjohnson
- - (NSDate *) dateByAddingYears: (NSInteger) dYears
- {
- NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
- [dateComponents setYear:dYears];
- NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:dateComponents toDate:self options:0];
- return newDate;
- }
- - (NSDate *) dateBySubtractingYears: (NSInteger) dYears
- {
- return [self dateByAddingYears:-dYears];
- }
- - (NSDate *) dateByAddingMonths: (NSInteger) dMonths
- {
- NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
- [dateComponents setMonth:dMonths];
- NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:dateComponents toDate:self options:0];
- return newDate;
- }
- - (NSDate *) dateBySubtractingMonths: (NSInteger) dMonths
- {
- return [self dateByAddingMonths:-dMonths];
- }
- // Courtesy of dedan who mentions issues with Daylight Savings
- - (NSDate *) dateByAddingDays: (NSInteger) dDays
- {
- NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
- [dateComponents setDay:dDays];
- NSDate *newDate = [[NSCalendar currentCalendar] dateByAddingComponents:dateComponents toDate:self options:0];
- 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)];
- }
- - (NSDateComponents *) componentsWithOffsetFromDate: (NSDate *) aDate
- {
- NSDateComponents *dTime = [[NSDate currentCalendar] components:componentFlags fromDate:aDate toDate:self options:0];
- return dTime;
- }
- #pragma mark - Extremes
- - (NSDate *) dateAtStartOfDay
- {
- NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
- components.hour = 0;
- components.minute = 0;
- components.second = 0;
- return [[NSDate currentCalendar] dateFromComponents:components];
- }
- // Thanks gsempe & mteece
- - (NSDate *) dateAtEndOfDay
- {
- NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
- components.hour = 23; // Thanks Aleksey Kononov
- components.minute = 59;
- components.second = 59;
- return [[NSDate currentCalendar] dateFromComponents:components];
- }
- #pragma mark - Retrieving Intervals
- - (NSInteger) secondsAfterDate: (NSDate *) aDate
- {
- NSTimeInterval ti = [self timeIntervalSinceDate:aDate];
- return (NSInteger) ti;
- }
- - (NSInteger) secondsBeforeDate: (NSDate *) aDate {
- NSTimeInterval ti = [aDate timeIntervalSinceDate:self];
- return (NSInteger) ti;
- }
- - (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);
- }
- // Thanks, dmitrydims
- // I have not yet thoroughly tested this
- - (NSInteger)distanceInDaysToDate:(NSDate *)anotherDate
- {
- NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
- NSDateComponents *components = [gregorianCalendar components:NSCalendarUnitDay fromDate:self toDate:anotherDate options:0];
- return components.day;
- }
- #pragma mark - Decomposing Dates
- - (NSInteger) nearestHour
- {
- NSTimeInterval aTimeInterval = [[NSDate date] timeIntervalSinceReferenceDate] + D_MINUTE * 30;
- NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
- NSDateComponents *components = [[NSDate currentCalendar] components:NSCalendarUnitHour fromDate:newDate];
- return components.hour;
- }
- - (NSInteger) hour
- {
- NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
- return components.hour;
- }
- - (NSInteger) minute
- {
- NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
- return components.minute;
- }
- - (NSInteger) seconds
- {
- NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
- return components.second;
- }
- - (NSInteger) day
- {
- NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
- return components.day;
- }
- - (NSInteger) month
- {
- NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
- return components.month;
- }
- - (NSInteger) week
- {
- NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
- return components.weekOfYear;
- }
- - (NSInteger) weekday
- {
- NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
- return components.weekday;
- }
- - (NSInteger) nthWeekday // e.g. 2nd Tuesday of the month is 2
- {
- NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
- return components.weekdayOrdinal;
- }
- - (NSInteger) year
- {
- NSDateComponents *components = [[NSDate currentCalendar] components:componentFlags fromDate:self];
- return components.year;
- }
- - (NSDateComponents*)dsDayWithCalendar:(NSCalendar*)calendar {
- return [calendar components:NSCalendarUnitCalendar | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitWeekday fromDate:self];
- }
- - (NSDateComponents*)dsMonthWithCalendar:(NSCalendar*)calendar {
- return [calendar components:NSCalendarUnitCalendar | NSCalendarUnitYear | NSCalendarUnitMonth fromDate:self];
- }
- - (NSDateComponents*)dsMonth {
- return [self dsMonthWithCalendar:[NSCalendar currentCalendar]];
- }
- @end
|