Comparing two NSDate - ios

I have a UIViewController with 2 buttons: today and yesterday. Every time the client clicked on today it needs to set the property _date for today and the same with yesterday.
The method which I set the property value is the following:
-(IBAction)dateButtonTouched:(id)sender
{
if(![sender isSelected])
{
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components = [cal components:( NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ) fromDate:[[NSDate alloc] init]];
[components setMinute:-[components minute]];
[components setSecond:-[components second]];
if([sender tag] == YESTERDAY)
{
[components setHour:-24];
_date= [cal dateByAddingComponents:components toDate: [NSDate date] options:0]; //YESTERDAY
}
else
{
NSDate *today = [NSDate date];
[components setHour:0];
_date= [cal dateByAddingComponents:components toDate: today options:0]; //TODAY
}
NSLog(#"user selected date %#",_date);
}
}
in the following method I'm trying to check if _date is today or yesterday:
-(void) viewWillLayoutSubviews
{
NSDateFormatter *dateFormat = [NSDateFormatter new];
[dateFormat setDateFormat:#"MM-dd-YY"];
self.dateLabel.text = [dateFormat stringFromDate:_date];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components = [cal components:( NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit ) fromDate:[[NSDate alloc] init]];
[components setMinute:-[components minute]];
[components setSecond:-[components second]];
[components setHour:0];
NSDate *today = [cal dateByAddingComponents:components toDate: [NSDate date] options:0]; //TODAY
[components setHour:-24];
NSDate *yesterday = [cal dateByAddingComponents:components toDate: [NSDate date] options:0]; //YESTERDAY
if([_date isEqualToDate:yesterday])
{
//do something
}
else if( [_date isEqualToDate:today])
{
//do something
}
}
The _date is never today or yesterday although if I debug it, print it or compare the description is the same.

An NSDate instance represents a specific moment in time. It is much more specific than "yesterday" or "today". Instead of trying to reset the hours, minutes, and seconds via date components, Maybe you should compare the components you're interested in: day, month, and year. Or you can use a calendar to compare at the component level:
NSDate *today = [NSDate date];
NSDate *someDay; // the date to compare
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *difference = [cal components:NSDayCalendarUnit fromDate:today toDate:someDay options:nil];
if (difference.day == -1) {
// yesterday
} else if (difference.day == 0) {
// today
}
Without knowing exactly what you want to do, it's harder to get more specific.

An NSDate object contains both date and time, encoded as a value that is essentially the number of microseconds since Jan 1 2000.
When you do two successive [NSDate date] operations you will get two different values, if not because the time has actually changed that much between the two then because most computer clock implementations assure that you get distinct values with each access.
NSDate's isEqualToDate function compares all of the bits of the two NSDate objects to see if they are exactly equal. This means that if the two are even a microsecond apart they will not appear to be equal.
If you want to see if two NSDate values are the same day you should either use NSDateFormatter to format them into strings and compare the strings, or use one of the NSDateComponent functions to calculate the number of days between them (several ways to do this).

Related

How to check whether a date belongs to this week or not in iOS?

Hello I have a date string like this.11/14/2016. What I want to do is check it whether is it
Today or This week or This month. I can compare today and the month. But how can I check whether this date belongs to "This Week"
Please help me.
Thanks
Given two dates,
NSDate *now = [NSDate date];
NSDate *then = // some other date
Find out if they're in the same week with:
BOOL sameWeek = [[NSCalendar currentCalendar] isDate:then equalToDate:now
toUnitGranularity:NSCalendarUnitWeekOfYear];
That line asks if they're "equal" with a granularity of a week, meaning that they're "equal" if they're in the same week.
Try below code,
- (void)thisWeek:(NSDate *)date
{
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *todaysComponents = [gregorian components:NSCalendarUnitWeekOfYear fromDate:[NSDate date]];
NSUInteger todaysWeek = [todaysComponents weekOfYear];
NSDateComponents *otherComponents = [gregorian components:NSCalendarUnitWeekOfYear fromDate:date];
NSUInteger datesWeek = [otherComponents weekOfYear];
//NSLog(#"Date %#",date);
if(todaysWeek==datesWeek){
NSLog(#"Date is in this week");
}else if(todaysWeek+1==datesWeek){
NSLog(#"Date is in next week");
}
}

How to add current Time(HH:MM:SS) to NSDate?

I am using https://github.com/ruslanskorb/RSDayFlow to add calendar to my application.
I override the method as
// Prints out the selected date.
- (void)datePickerView:(RSDFDatePickerView *)view didSelectDate:(NSDate *)date {
self.transactionDate = date;
self.inputDateField.text = [[Helper getDateFormatterForClient] stringFromDate:self.transactionDate];
NSLog(#"transactionDate=%#", self.transactionDate);
[self.inputDateField resignFirstResponder];
}
All I want to add is current time HH:MM:SS to the date user selects.
I have no idea how to do this, any help is greatly appreciated
UPDATE
Currently, when the date is selected, I get
2015-01-15 10:34:35.210 myapp-ios[21476:60b] transactionDate=2015-01-15 08:00:00 +0000
If by "current time HH:MM:SS to the date" you mean that you want to replace the selected date's HH:MM:SS with the current HH:MM:SS, you can extract the relevant date components from the selected date, get the current datetime, extract the relevant time components, then add those components back into self.transactionDate, ex:
// Prints out the selected date.
- (void)datePickerView:(RSDFDatePickerView *)view didSelectDate:(NSDate *)date {
self.transactionDate = date;
self.inputDateField.text = [[Helper getDateFormatterForClient] stringFromDate:self.transactionDate];
NSLog(#"transactionDate=%#", self.transactionDate);
[self.inputDateField resignFirstResponder];
// Create an instance of the current calendar
NSCalendar *calendar = [NSCalendar currentCalendar];
// Break self.transactionDate into day, month, and year components
NSDateComponents* dateComponents = [[NSCalendar currentCalendar] components:NSCalendarUnitYear|
NSCalendarUnitMonth|NSCalendarUnitDay fromDate:self.transactionDate];
// Save transaction date with just the day, month, and year
self.transactionDate = [[NSCalendar currentCalendar] dateFromComponents:dateComponents];
// Get the current datetime
NSDate *currentDate = [NSDate date];
// Extract the hour, minute, and second components
NSDateComponents *components = [calendar components:(NSCalendarUnitHour|
NSCalendarUnitMinute|NSCalendarUnitSecond) fromDate:currentDate];
// Add those hour, minute, and second components to
// self.transactionDate
self.transactionDate = [calendar dateByAddingComponents:components
toDate:self.transactionDate options:0];
}
This method Which I have created the in the category of `NSDate'.
+ (NSDate *)getDateWithCurrentTime:(NSDate *)date {
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components =
[gregorian components:(NSCalendarUnitDay |
NSCalendarUnitYear|NSCalendarUnitMonth) fromDate:date];
NSDateComponents *CurrentDateComponent =
[gregorian components:(NSCalendarUnitHour |
NSCalendarUnitMinute|NSCalendarUnitSecond) fromDate:[NSDate date]];
[components setHour:[CurrentDateComponent hour]];
[components setMinute:[CurrentDateComponent minute]];
[components setSecond:[CurrentDateComponent second]];
[components setTimeZone:[NSTimeZone systemTimeZone]];
return [gregorian dateFromComponents:components];
}

Get days between days

Before giving downvote, comment the reason
I have created a UIDatePicker with minimum & maximum date values (i.e. 6 months of date picker) Now, i need to get 7 days from selected date. There i need to check the conditions,
If date is today date i need to get 7 days from today onwards
If date is last date (i.e. last date of picker) need to get last 7 days including last day
If date is middle of today's date & last date i need to get last 3 days, next 3 days including today date. And, also while getting last & next 3 days it shouldn't get exceed with picker's date limit.
Here's my code snippet:
- (void)addDays:(NSInteger)range {
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"dd-MM-yyyy"];
NSDate *startDate = self.selectedDate;
for (int x = 0; x <= range; x++) {
NSLog(#"%#", [dateFormat stringFromDate:startDate]);
startDate = [startDate dateByAddingTimeInterval:(60 * 60 * 24)];
}
}
- (void)minusDays:(NSInteger)range {
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"dd-MM-yyyy"];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *comps = [NSDateComponents new];
for (NSInteger i=0; i<range; i++) {
comps.day += -1;
NSDate *date = [calendar dateByAddingComponents:comps toDate:self.selectedDate options:0];
NSDateComponents *components = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:date];
NSLog(#"%#", [dateFormat stringFromDate:[calendar dateFromComponents:components]]);
}
}
- (void)calculateDateRange {
if ([dateArray count] > 0) {
[dateArray removeAllObjects];
}
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *lastcomponents = [calendar components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:[NSDate date]];
lastcomponents.month += 6;
NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:#"yyyy/MM/dd"];
NSDate *currentDate = [NSDate date];
NSDate *selectedD = self.selectedDate;
NSDate *endDate = [calendar dateFromComponents:lastcomponents];
NSDate *fromDate;
NSDate *toDate;
[calendar rangeOfUnit:NSDayCalendarUnit startDate:&fromDate interval:NULL forDate:currentDate];
[calendar rangeOfUnit:NSDayCalendarUnit startDate:&toDate interval:NULL forDate:selectedD];
NSDateComponents *difference = [calendar components:NSDayCalendarUnit fromDate:fromDate toDate:toDate options:0];
NSInteger first = [difference day];
[calendar rangeOfUnit:NSDayCalendarUnit startDate:&fromDate interval:NULL forDate:selectedD];
[calendar rangeOfUnit:NSDayCalendarUnit startDate:&toDate interval:NULL forDate:endDate];
NSDateComponents *difference2 = [calendar components:NSDayCalendarUnit fromDate:fromDate toDate:toDate options:0];
NSInteger second = [difference2 day];
if ((first == 0 || first < 3) && second > 7) {
[self addDays:7];
} else if (first >= 3 && second > 7) {
[self minusDays:3];
[self addDays:3];
}else if (second == 7 || second < 7) {
[self minusDays:7];
}
}
This is working fine. But, can't get exact last & previous days.
Anyone has idea on this?
My interpretation of your needs
You have a date picker. When a date is picked you need to create a 7 day range around that selected date.
So, if the selected date is 15/11/2014 then you want 3 days either side so...
12/11/2014 - 18/11/2014.
However, the date range cannot exceed the limits of the date picker. So if the minimum date on the date picker is set to 14/11/2014 then (in the above example) the date range would be...
14/11/2014 - 21/11/2014
Even after your additional explanation this is still my interpretation. And my code does exactly this.
Solution
You CANNOT use 60*60*24 to mean one day. This is just wrong. When dealing with dates you should always be using NSDateComponents and NSCalendar.
Also, break down your problem into small steps. There is no reason to do everything in one giant function.
OK I guess you have a datePicker action somewhere so I'd code it like this...
- (void)datePickerDateChanged
{
NSDate *minimumDate = self.datePicker.minimumDate;
NSDate *maximumDate = self.datePicker.maximumDate;
NSDate *selectedDate = self.datePicker.date;
NSDate *startDate;
NSDate *endDate;
if ([self numberOfDaysFromDate:minimumDate toDate:selectedDate] < 3) {
// get 7 days after minimumDate
startDate = minimumDate;
endDate = [self dateByAddingDays:6 toDate:minimumDate];
} else if ([self numberOfDaysFromDate:selectedDate toDate:maximumDate] < 3) {
// get 7 days before maximumDate
startDate = [self dateByAddingDays:-6 toDate:maximumDate];
endDate = maximumDate;
} else {
// get 3 days before and 3 days after selectedDate
startDate = [self dateByAddingDays:-3 toDate:selectedDate];
endDate = [self dateByAddingDays:3 toDate:selectedDate];
}
// Here startDate and endDate define your date range.
}
- (NSDate *)dateByAddingDays:(NSInteger)days toDate:(NSDate *)date
{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [NSDateComponents new];
components.day = days;
return [calendar dateByAddingComponents:components toDate:date options:0];
}
- (NSInteger)numberOfDaysFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate
{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:NSDayCalendarUnit fromDate:fromDate toDate:toDate options:0];
// always return positive. We just want magnitude of days.
return components.day > 0 ? components.day : -components.day;
}
This is untested and just a first attempt.

Find all days of a week/month/year and add to NSMutableArray

I have an NSMutableArray, and i want to be able to pull out only the rows that are in a cetain time frame such as each week or month or year. I can get a date thats a week back so i would have the current date and the date a week back, but i need to be able to grab all those days then add them to an array so i can search through them.
This is how i am grabbing the day and the day a week back.
-(void)getCalDays {
cal = [NSCalendar currentCalendar];
NSDate *date = [NSDate date];
NSDateComponents *comps = [cal components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)fromDate:date];
today = [cal dateFromComponents:comps];
NSLog(#"today is %#", today);
[self getWeek];
}
-(void)getWeek {
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setDay:-6];
weekDate = [cal dateByAddingComponents:components toDate:today options:0];
NSLog(#"Week of %# THRU %#", today, weekDate);
}
So how can i find all the days in between the two dates and load them into an array?
You're on your way. The key is to advance the component's day in a loop and extract a date from them.
NSMutableArray *result = [NSMutableArray array];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *startDate = // your input start date
NSDate *endDate = // your input end date
NSDateComponents *comps = [cal components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)fromDate:startDate];
NSDate *date = [cal dateFromComponents:comps];
while (![date isEqualToDate:endDate]) {
[result addObject:date];
[comps setDay:(comps.day + 1)];
date = [cal dateFromComponents:comps];
}
Note that this will result in a collection of dates inclusive of the first date, exclusive of the last date. You can probably work out on your own how to change the edge conditions.

How to check whether now date is during 9:00-18:00

When my app is launched I want to check whether the date is between 9:00-18:00.
And I can get the time of now using NSDate. How can I check the time?
So many answers and so many flaws...
You can use NSDateFormatter in order to get an user-friendly string from a date. But it is a very bad idea to use that string for date comparisons!
Please ignore any answer to your question that involves using strings...
If you want to get information about a date's year, month, day, hour, minute, etc., you should use NSCalendar and NSDateComponents.
In order to check whether a date is between 9:00 and 18:00 you can do the following:
NSDate *date = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *dateComponents = [calendar components:NSHourCalendarUnit fromDate:date];
if (dateComponents.hour >= 9 && dateComponents.hour < 18) {
NSLog(#"Date is between 9:00 and 18:00.");
}
EDIT:
Whoops, using dateComponents.hour <= 18 will result in wrong results for dates like 18:01. dateComponents.hour < 18 is the way to go. ;)
Construct dates for 09:00 and 18:00 today and compare the current time with those dates:
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *now = [NSDate date];
NSDateComponents *components = [cal components:NSEraCalendarUnit|NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:now];
[components setHour:9];
[components setMinute:0];
[components setSecond:0];
NSDate *nineHundred = [cal dateFromComponents:components];
[components setHour:18];
NSDate *eighteenHundred = [cal dateFromComponents:components];
if ([nineHundred compare:now] != NSOrderedDescending &&
[eighteenHundred compare:now] != NSOrderedAscending)
{
NSLog(#"Date is between 09:00 and 18:00");
}

Resources