// ===========================================================================
//  NSDate+Extra.m   (c) 2006 __MyCompanyName__. All rights reserved.
//
// ---------------------------------------------------------------------------
// Modification History:
//
//        Created:              1/16/06        Pierce T. Wetter III
//  Last Modified:              1/16/06        Pierce T. Wetter III
//
// ---------------------------------------------------------------------------
//
// ===========================================================================

#import "NSDate+Extra.h"

@implementation NSDate (DayNumbers)


- (int) hourOfDay
{
	return [[NSCalendarDate dateWithTimeIntervalSinceReferenceDate: [self timeIntervalSinceReferenceDate]] hourOfDay];
}

- (int) minuteOfHour
{
	return [[NSCalendarDate dateWithTimeIntervalSinceReferenceDate: [self timeIntervalSinceReferenceDate]] minuteOfHour];
}

- (NSCalendarDate *) dateBySettingDate: (NSDate *) newDate
{
	NSCalendarDate *odate=[NSCalendarDate dateWithTimeIntervalSinceReferenceDate: [self timeIntervalSinceReferenceDate]];
	NSCalendarDate *ndate=[NSCalendarDate dateWithTimeIntervalSinceReferenceDate: [newDate timeIntervalSinceReferenceDate]];
	return [NSCalendarDate dateWithYear: [ndate yearOfCommonEra] month: [ndate monthOfYear] day: [ndate dayOfMonth] 
								   hour: [odate hourOfDay] minute: [odate minuteOfHour] second: [odate secondOfMinute] 
							   timeZone: [odate timeZone]];
}

- (NSCalendarDate *) dateBySettingTime: (NSDate *) newDate
{
	NSCalendarDate *odate=[NSCalendarDate dateWithTimeIntervalSinceReferenceDate: [self timeIntervalSinceReferenceDate]];
	NSCalendarDate *ndate=[NSCalendarDate dateWithTimeIntervalSinceReferenceDate: [newDate timeIntervalSinceReferenceDate]];
	return [NSCalendarDate dateWithYear: [odate yearOfCommonEra] month: [odate monthOfYear] day: [odate dayOfMonth] 
								   hour: [ndate hourOfDay] minute: [ndate minuteOfHour] second: [ndate secondOfMinute] 
							   timeZone: [odate timeZone]];
}

- (NSCalendarDate *) dateBySettingHour: (int) hour
{
	NSCalendarDate *odate=[NSCalendarDate dateWithTimeIntervalSinceReferenceDate: [self timeIntervalSinceReferenceDate]];
	return [NSCalendarDate dateWithYear: [odate yearOfCommonEra] month: [odate monthOfYear] day: [odate dayOfMonth] 
								   hour: hour minute: [odate minuteOfHour] second: [odate secondOfMinute] 
							   timeZone: [odate timeZone]];
}
- (NSCalendarDate *) dateBySettingMinute: (int) minute
{
	NSCalendarDate *odate=[NSCalendarDate dateWithTimeIntervalSinceReferenceDate: [self timeIntervalSinceReferenceDate]];
	return [NSCalendarDate dateWithYear: [odate yearOfCommonEra] month: [odate monthOfYear] day: [odate dayOfMonth] 
								   hour: [odate hourOfDay] minute: minute second: [odate secondOfMinute] 
							   timeZone: [odate timeZone]];
}
// ------------------------------------------------------------------------------
//		• sameDateAs
// ------------------------------------------------------------------------------
// Compare two calendar dates, ignoring intraday time.  Return YES if they
// are both the same date.

- (BOOL) sameDateAs:(NSDate *) other
{
    BOOL retValue = YES;
	
    if (self != other)
    {
        retValue = ([self dayNumber] == [other dayNumber]);
    }
    return retValue;
}
// ------------------------------------------------------------------------------
//		• dateIsToday
// ------------------------------------------------------------------------------
//

- (BOOL) isExpired
{
	return [self dayNumber] < [[NSDate date] dayNumber];
}
- (BOOL) isCurrent
{
	return [self dayNumber] <= [[NSDate date] dayNumber];
}
- (NSString *) dayOfWeekString
{
	return [self descriptionWithCalendarFormat:@"%A" timeZone: nil locale:nil];
}

- (BOOL) dateIsToday
{
    return [self sameDateAs:[NSDate date]];
}
- (BOOL) dateIsToday1
{
    return [self sameDateAs:[[NSDate date] dateByAddingDays:1]];
}
- (BOOL) dateIsToday2
{
    return [self sameDateAs:[[NSDate date] dateByAddingDays:2]];
}
- (BOOL) dateIsToday3
{
    return [self sameDateAs:[[NSDate date] dateByAddingDays:3]];
}
- (BOOL) dateIsToday4
{
    return [self sameDateAs:[[NSDate date] dateByAddingDays:4]];
}
- (BOOL) dateIsToday5
{
    return [self sameDateAs:[[NSDate date] dateByAddingDays:5]];
}
- (BOOL) dateIsToday6
{
    return [self sameDateAs:[[NSDate date] dateByAddingDays:6]];
}
- (BOOL) dateIsToday7
{
    return [self sameDateAs:[[NSDate date] dateByAddingDays:7]];
}
- (BOOL) dateIsYesterday
{
    return [self sameDateAs:[[NSDate date] dateByAddingDays:-1]];
}
- (BOOL) dateIsYesterday1
{
    return [self sameDateAs:[[NSDate date] dateByAddingDays:-2]];
}
- (BOOL) dateIsYesterday2
{
    return [self sameDateAs:[[NSDate date] dateByAddingDays:-3]];
}
- (BOOL) dateIsYesterday3
{
    return [self sameDateAs:[[NSDate date] dateByAddingDays:-4]];
}
- (BOOL) dateIsYesterday4
{
    return [self sameDateAs:[[NSDate date] dateByAddingDays:-5]];
}
- (BOOL) dateIsYesterday5
{
    return [self sameDateAs:[[NSDate date] dateByAddingDays:-6]];
}
- (BOOL) dateIsYesterday6
{
    return [self sameDateAs:[[NSDate date] dateByAddingDays:-7]];
}
- (BOOL) dateIsYesterday7
{
    return [self sameDateAs:[[NSDate date] dateByAddingDays:-8]];
}

// ------------------------------------------------------------------------------
//		• dateByAddingDays: days
// ------------------------------------------------------------------------------
//

- (NSDate *)	dateByAddingDays: (int) days
{
    // Tricky: make sure that adding 1 day isn't affected by
    // daylight savings time.  Note whether the
    // daytime hour has changed, and adjust appropriately.  This way, 12:01am
    // becomes 12:01am the next day regardless of daylight savings time.
	
    // There is a known quirk in DST logic.  There is no 02:00:00 throuh 02:59:59
    // on the first day of DST.  So if you have a time in this range
    // and adding a day puts you into DST, the time the next day will
    // be exactly 1 hour less.
    
    // Using the NSTimeZone object is about 20% faster than the old
    // implementation -- mlaster
    
    //NSTimeZone *tz = nil;
    //BOOL dstFlag = NO;
    NSDate *newDate = nil;
	
    //tz = [self timeZone];
    newDate = [self addTimeInterval: (days*60*60*24)];
    /*dstFlag = [tz isDaylightSavingTimeForDate:newDate];
    if (dstFlag != [tz isDaylightSavingTimeForDate:self])
    {
        if (dstFlag == YES)
        {
            newDate = [newDate addTimeInterval:-60*60];
        }
        else
        {
            newDate = [newDate addTimeInterval:60*60];
        }
    }*/
    return newDate;
}

// ------------------------------------------------------------------------------
//		• dayNumber
// ------------------------------------------------------------------------------
// If two NSDates represent times on the same day (relative to the
// receiver's time zone), they will have the same day number.

- (long) dayNumber
{
    return (long) floor(([self timeIntervalSinceReferenceDate] + [[NSTimeZone localTimeZone] secondsFromGMTForDate:self]) / (double)(60*60*24));
}

// ------------------------------------------------------------------------------
//		• compareDay
// ------------------------------------------------------------------------------
// Compare two calendar dates (using the receiver's time zone).  Dates are
// considered equal if they are on the same day at any time.

- (NSComparisonResult) compareDay:(NSDate *) other
{
    NSComparisonResult retValue = NSOrderedSame;
	
    if (self != other)
    {
        long selfDay = 0;
        long otherDay = 0;
		
        selfDay = [self dayNumber];
        otherDay = [other dayNumber];
        if (selfDay < otherDay)
        {
            retValue = NSOrderedAscending;
        }
        else if (selfDay > otherDay)
        {
            retValue = NSOrderedDescending;
			
        }
    }
    return retValue;
}

@end
