//
//  NSDate+MCSFAdditions.h
//  DTApp
//
//  Created by Ali Lalani on 29/04/08.
//  Copyright 2008 Marketcircle, Inc. All rights reserved.
//

// This should be deleted from BISubstrate once we merge the BP repo with the DL4 repo - it was copied from the MCSharedFoundation code from the DL4 repo


#import <Foundation/Foundation.h>

#import <MCFoundation/NSCalendarDate+MCAdditions.h>

@interface NSDate (MCSFAdditions)
+ (id)mcDateWithYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day;
+ (id)mcDateWithYear:(NSInteger)year month:(NSInteger)month day:(NSInteger)day hour:(NSInteger)hour minute:(NSInteger)minute second:(NSInteger)second;
+ (id)mcDateWithDate:(NSDate *)date andTime:(NSDate *)time;
+ (NSDate *)mcDateWithWeekDay:(NSInteger)weekDay inWeek:(NSInteger)weekNumber inMonth:(NSInteger)month inYear:(NSInteger)year;

+ (BOOL)mcIsLeapYear:(int)aYear;
+ (BOOL)mcIsValidDateWithDay:(int)aDay month:(int)aMonth year:(int)aYear;

+ (NSInteger)mcFirstWeekday;

#pragma mark -
#pragma mark Component Accessors

- (NSInteger)mcDayOfMonth;
- (NSInteger)mcDayOfWeek;
- (NSInteger)mcDayOfYear;
- (NSInteger)mcHourOfDay;
- (NSInteger)mcMinuteOfHour;
- (NSInteger)mcSecondOfMinute;
- (NSInteger)mcSecondOfDay;
- (NSUInteger)mcWeekOfMonth;
- (NSUInteger)mcWeekOfYear;
- (NSInteger)mcLastDayOfMonth;

- (NSInteger)mcMonth;
- (NSInteger)mcYear;

#pragma mark Since Date Methods

- (void)mcYears:(NSInteger *)yp months:(NSInteger *)mop days:(NSInteger *)dp hours:(NSInteger *)hp minutes:(NSInteger *)mip seconds:(NSInteger *)sp sinceDate:(NSDate *)date;
- (NSInteger)mcMinutesSinceDate:(NSDate *)date;
- (NSInteger)mcDaysSinceDate:(NSDate *)date;
/**
 * This is an optimized version of mcDaysSinceDate: that assumes that 
 * self and date both start at the same time.  It is much faster, but 
 * will will return incorrect results if the assumption does not hold true.
 *
 * The reason that this method can return inaccurate results is that the 
 * result is based on the number of 24 hour periods between the two dates.
 * If one date lies within DST while the other does not the interval between
 * two days is not exactly 24 hours so it must be rounded off. If the dates 
 * have different times the rounding can cause the interval to be incorrect.
 */
- (NSInteger)mcDaysSinceAlignedDate:(NSDate *)date;
- (NSInteger)mcMonthsSinceDate:(NSDate *)date;
- (NSInteger)mcYearsSinceDate:(NSDate *)date;
- (NSInteger)mcMinutesSinceBeginningOfDay;
- (NSInteger)mcNumberOfDaysInMonth;
- (NSInteger)mcNumberOfWeeksSpannedByMonth;
- (NSInteger)mcNumberOfWeeksSpannedByMonth:(NSInteger)firstDayOfWeek;
/** 
 * The number of weeks spanned by a month not including the last week if
 * it contains the first of the next month.
 */
- (NSInteger)mcNumberOfInnerWeeksSpannedByMonth;
- (NSInteger)mcNumberOfInnerWeeksSpannedByMonth:(NSInteger)firstDayOfWeek;
- (NSInteger)mcNumberOfWeeksSpannedByTwoMonths;
- (NSInteger)mcNumberOfWeeksSpannedByTwoMonths:(NSInteger)firstDayOfWeek;

#pragma mark Adding Conveniences

- (NSDate *)mcDateByAddingYears:(int)years;
- (NSDate *)mcDateByAddingMonths:(int)months;
- (NSDate *)mcDateByAddingDays:(NSInteger)days;
- (NSDate*)mcDateByAddingWeeks:(int)weeks;
- (NSDate *)mcDateByAddingHours:(int)hours;
- (NSDate *)mcDateByAddingHours:(int)hours andMinutes:(int)minutes;
- (NSDate *)mcDateByAddingMinutes:(NSInteger)minutes;
- (NSDate*)mcDateByAddingSeconds:(int)seconds;

#pragma mark Date Stripping

- (NSDate *)mcDateByStrippingTime;
- (NSDate *)mcDateByStrippingDate;

#pragma mark Comparision Methods

- (BOOL)mcAreDateComponents:(NSUInteger)components sameAsDate:(NSDate*)other;

- (BOOL)mcIsToday;
- (BOOL)mcIsYesterday;
- (BOOL)mcIsTomorrow;

- (BOOL)mcIsSameDayAsDate:(NSDate *)otherDate;
- (BOOL)mcIsSameWeekAsDate:(NSDate *)otherDate;
- (BOOL)mcIsLaterThanDate:(NSDate *)aDate;
- (BOOL)mcIsLaterThanOrSameAsDate:(NSDate *)aDate;
- (BOOL)mcIsEarlierThanDate:(NSDate *)aDate;
- (BOOL)mcIsEarlierThanOrSameAsDate:(NSDate *)aDate;
- (BOOL)mcIsEqualToNearestSecondDate: (NSDate*)date;

#pragma mark Date Iterator Methods

- (NSDate *)mcNextDay;
- (NSDate *)mcPreviousDay;
- (NSDate *)mcNextDateOccurringOnDaysOfTheWeek:(NSArray *)daysOfWeek;
- (NSDate *)mcNextDateOccurringOnDaysOfTheMonth:(NSArray *)daysOfMonth;
- (NSNumber *)mcNextMonthOccurringInMonthsOfTheYear:(NSArray *)monthsOfTheYear;
- (NSDate *)mcDateAsBeginningOfNextHour;
- (NSDate *)mcDateAsBeginningOfMonth;
- (NSDate *)mcDateAsEndOfMonth;
- (NSDate *)mcDateAsBeginningOfYear;
- (NSDate*)mcDateAsEndOfYear;

- (NSDate *)mcDateAsBeginningOfMinute;
- (NSDate *)mcDateAsBeginningOfDay;
- (NSDate *)mcDateAsBeginningOfWeek;
- (NSDate *)mcDateAsBeginningOfLocalizedWeek;
- (NSDate *)mcDateAsBeginningOfWeek:(NSInteger)firstDayOfWeek;

- (NSDate *)mcDateAsEndOfDay;
- (NSDate *)mcDateAsEndOfScheduleDay;
- (NSDate *)mcDateAsEndOfWeek;
- (NSDate *)mcDateAsEndOfLocalizedWeek;
- (NSDate *)mcDateAsEndOfWeek:(NSInteger)firstDayOfWeek;

#pragma mark Date Offset Methods

/// @NOTE These three methods have been ported to Touch, but not tested (they are not currenty used)
- (NSDate *)mcDateWithOffset:(NSString *)offset skipDays:(NSString *)skipDays;
- (NSDate *)mcDateWithOffset:(NSString *)offset;
- (NSArray *)mcDatesForWeekOfDateWithWeekStartingDay:(int)startOfWeek;

#pragma mark -
#pragma mark Date and Time Format

+ (NSDate *)mcDateWithString:(NSString *)dateString calendarFormat:(NSString *)format;
+ (NSDate *)mcDateWithTimestampString:(NSString *)dateString containsDate:(BOOL)hasDate fractionalSeconds:(BOOL)hasFraction containsTimezone:(BOOL)hasTimezone;
+ (NSString *)mcLongMonthStringForMonthOfYear:(NSInteger)monthOfYear;
+ (NSString *)mcShortMonthStringForMonthOfYear:(NSInteger)monthOfYear;
+ (NSString *)mcLongWeekDayStringForDayOfWeek:(NSInteger)dayOfWeek;
+ (NSString *)mcShortWeekDayStringForDayOfWeek:(NSInteger)dayOfWeek;
- (NSString *)mcLongWeekDayString;
- (NSString *)mcShortWeekDayString;

- (NSString *)mcShortDate;
- (NSString *)mcLongDate;

- (NSString *)mcMediumDate;
- (NSString *)mcMediumDateWithWeekDay;

- (NSString *)mcShortTime;
- (NSString *)mcShortTimeNumbersOnly; // discards the am/pm designation string
- (NSString *)mcShortTimeAmPmString; // returns the am/pm designation string
- (NSString *)mcLongTime;

- (NSString *)mcShortDateTime;
- (NSString *)mcMediumDateTime;
- (NSString *)mcMediumDateTimeRelative;
- (NSString *)mcMediumDateTimeWithWeekDay;
- (NSString *)mcLongDateTime;
- (NSString *)mcCustomFormat:(NSString *)format;

// Relative Conveniences
- (NSString *)mcRelativeDateString; // returns nil if the day is neither Yesterday, Today or Tomorrow
- (NSString *)mcLongDateRelative; // Yesterday/Today/Tomorrow
- (NSString *)mcMediumDateRelative;
- (NSString *)mcMediumDateWithWeekDayRelative;
- (NSString *)mcMediumDateTimeWithWeekDayRelative;
- (NSString *)mcShortDateRelative;
- (NSString *)iCalRepresentation;
- (NSString *)iCalDateOnlyRepresentation;
- (NSString*)pgStringRepresentation;
- (NSDate *)dateWithOffset:(NSString *)offset;
- (NSDate *)dateWithOffset:(NSString *)offset skipDays:(NSString *)skipDays;
@end
