I'm creating a report generator in Cocoa, and I need to produce convenient date ranges such as "Today", "This Week", "This Month", "This Year", etc.
Is there a good way to do this? Here is my skeleton thus far:
@interface DateRange : NSObject
{
NSDate startDate;
NSDate endDate;
}
@property (nonatomic, retain) NSDate * startDate;
@property (nonatomic, retain) NSDate * endDate;
+ (DateRange *)rangeForDayContainingDate:(NSDate *)date;
+ (DateRange *)rangeForWeekContainingDate:(NSDate *)date;
+ (DateRange *)rangeForMonthContainingDate:(NSDate *)date;
+ (DateRange *)rangeForYearContainingDate:(NSDate *)date;
@end
Some example use cases would be as follows:
DateRange * thisWeek = [DateRange rangeForWeekContainingDate:[NSDate date]];
DateRange * thisYear = [DateRange rangeForYearContainingDate:[NSDate date]];
Essentially, I want the returned DateRange
object to contain the start and end dates for the week, month or year surrounding the target date. For example (in pseudocode):
NSDate * today = [August 25, 2009];
DateRange * thisWeek = [DateRange rangeForWeekContainingDate:today];
assert(thisWeek.startDate == [August 23, 3009]);
assert(thisWeek.endDate == [August 29, 3009]);
update:
I was able to get this working thanks to the answer provided by Kendall Helmstetter Geln. Here is the complete method for a one-week range:
+ (DateRange *)rangeForWeekContainingDate:(NSDate *)date
{
DateRange * range = [[self alloc] init];
// start of the week
NSDate * firstDay;
[[self calendar] rangeOfUnit:NSWeekCalendarUnit
startDate:&firstDay
interval:0
forDate:date];
[range setStartDate:firstDay];
// end of the week
NSDateComponents * oneWeek = [[NSDateComponents alloc] init];
[oneWeek setWeek:1];
[range setEndDate:[[self calendar] dateByAddingComponents:oneWeek
toDate:firstDay
options:0]];
[oneWeek release];
return [range autorelease];
}
We can also use the earlierDate: and laterDate: methods of the NSDate class: NSDate *earlierDate = [date1 earlierDate:date2];//Returns the earlier of 2 dates. Here earlierDate will equal date2. NSDate *laterDate = [date1 laterDate:date2];//Returns the later of 2 dates.
NSDate objects encapsulate a single point in time, independent of any particular calendrical system or time zone. Date objects are immutable, representing an invariant time interval relative to an absolute reference date (00:00:00 UTC on 1 January 2001).
Creating a Date and Time in Swift For this you can use DateComponents to specify the components and then Calendar to create the date. The Calendar gives the Date context. Otherwise, how would it know what time zone or calendar to express it in? Other time zone abbreviations can be found here.
NSDate *date = [NSDate date]; to get the current date and time. Use NSDateFormatter to format it. See this link for a how-to on date and time formatting.
For the sake of completeness, here is my final solution (with thanks to Kendall Helmstetter Geln and jbrennan):
+ (NSCalendar *)calendar
{
NSCalendar * gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
return [gregorian autorelease];
}
////////////////////////////////////////////////////////////////
+ (NSDateComponents *)singleComponentOfUnit:(NSCalendarUnit)unit
{
NSDateComponents * component = [[NSDateComponents alloc] init];
switch (unit)
{
case NSDayCalendarUnit: [component setDay:1]; break;
case NSWeekCalendarUnit: [component setWeek:1]; break;
case NSMonthCalendarUnit: [component setMonth:1]; break;
case NSYearCalendarUnit: [component setYear:1]; break;
}
return [component autorelease];
}
////////////////////////////////////////////////////////////////
+ (WM_DateRange *)rangeForUnit:(NSCalendarUnit)unit
surroundingDate:(NSDate *)date
{
WM_DateRange * range = [[self alloc] init];
// start of the period
NSDate * firstDay;
[[self calendar] rangeOfUnit:unit
startDate:&firstDay
interval:0
forDate:date];
[range setStartDate:firstDay];
// end of the period
[range setEndDate:[[self calendar]
dateByAddingComponents:[self singleComponentOfUnit:unit]
toDate:firstDay
options:0]];
return [range autorelease];
}
////////////////////////////////////////////////////////////////
+ (WM_DateRange *)rangeForDayContainingDate:(NSDate *)date
{ return [self rangeForUnit:NSDayCalendarUnit surroundingDate:date]; }
+ (WM_DateRange *)rangeForWeekContainingDate:(NSDate *)date
{ return [self rangeForUnit:NSWeekCalendarUnit surroundingDate:date]; }
+ (WM_DateRange *)rangeForMonthContainingDate:(NSDate *)date
{ return [self rangeForUnit:NSMonthCalendarUnit surroundingDate:date]; }
+ (WM_DateRange *)rangeForYearContainingDate:(NSDate *)date
{ return [self rangeForUnit:NSYearCalendarUnit surroundingDate:date]; }
////////////////////////////////////////////////////////////////
- (void)dealloc
{
[endDate release];
[startDate release];
[super dealloc];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With