Compare time in objective c - objective-c

I want to compare different times of outlets with ipad current time so what i did was this
if(CT!=nil && startTime!=nil &&endTime!=nil)
{
/* If current time is greater than begin time but less than end time then he can give feedack
*/
if (([CT compare:startTime]== NSOrderedDescending) && ([CT compare:endTime]== NSOrderedAscending) ) {
return YES;
}
else if (([CT compare:startTime]== NSOrderedSame) || ([CT compare:endTime]== NSOrderedSame))
{
return YES;
}
else if (([CT compare:startTime]== NSOrderedDescending) && ([CT compare:endTime]== NSOrderedDescending))
{
return NO; // out of outlet timings
}
This seems to be working good till now but when i change the outlet time to
start time = 18:30PM
end time = 2:00 AM
Then in that case the above code fails, when the ipad clocks at 1:00AM then the first if condition fails so i added this code below
if (([CT compare:startTime]== NSOrderedAscending) && ([CT compare:endTime]== NSOrderedAscending))
{
}
Now as a developer i am sure that if the device clocks at 1:00 AM then it wont fail but what if somebody updated the outlet timing to
start time = 9:00AM
end time = 11:00 AM
and current device time = 8:00 AM
then in the above case my the second code will fail.
what i want is some suggestion as in what i can do in the second if condition
Code that creates CT is :
NSDate *sysDate = [NSDate date];
NSDateFormatter *df = [[NSDateFormatter alloc]init];
[df setDateFormat:#"HH:mm:ss"];
NSString *timeString = [df stringFromDate:sysDate];
NSDate *CT = [df dateFromString:timeString];
startTime and endTime are date objects stored in the plist.

Rewrite your conditions as if there were numbers instead of dates and see what they actually do (NSOrderedDescending becomes > "greater than", NSOrderedAscending becomes < "less than"):
if (ctNumber > startNumber && ctNumber < endNumber)
{ ... }
else if (ctNumber == startNumber || ctNumber == endNumber)
{ ... }
else if (ctNumber > startNumber && ctNumber > endNumber)
{ ... }
I hope this way it's obvious the last one is not what you mean at all, and the other condition you tried later was still incorrect. The correct one is (ctNumber < startNumber || ctNumber > endNumber) which is exactly what standalone else would do, so you can just drop it:
if (ctNumber > startNumber && ctNumber < endNumber)
{ ... }
else if (ctNumber == startNumber || ctNumber == endNumber)
{ ... }
else
{ /* otherwise ; everything else ; in all other cases */ ... }
But you really should follow #ILYA2606 advice and compare time intervals (which are numbers) in future to avoid further confusions like this. It will also allow you to use <= and >= and so drop the middle condition:
NSTimeInterval ctNumber = [CT timeIntervalSince1970];
NSTimeInterval startNumber = [startDate timeIntervalSince1970];
NSTimeInterval endNumber = [endDate timeIntervalSince1970];
BOOL ctLiesInsideInterval = (ctNumber >= startNumber && ctNumber <= endNumber);
return ctLiesInsideInterval;
And finally, I have to point out that the date formatter code that creates CT is nonsense and is equivalent to simply using current time:
NSDate* CT = [NSDate date];

Convert NSString to NSDate, compare timeIntervals:
NSDateFormatter *df = [[NSDateFormatter alloc]init];
[df setDateFormat:#"HH:mm:ss"];
NSDate *CTDate = [df dateFromString:CT];
NSDate *startDate = [df dateFromString:startTime];
NSTimeInterval CTInterval = [CTDate timeIntervalSince1970];
NSTimeInterval startInterval = [startDate timeIntervalSince1970];
NSTimeInterval deltaInterval = startInterval - CTInterval;
if(deltaInterval < 0){
//Ascending (CT < startTime)
}
else if(deltaInterval > 0){
//Descending (CT > startTime)
}
else{
//Some (CT = startTime)
}

Try this one..
NSDate *currentDate=[NSDate date];
NSTimeInterval daysInSeconds = 60*60;
NSDate *starttime= [currentDate dateByAddingTimeInterval:daysInSeconds];
daysInSeconds = 2*60*60;
NSDate *endtime= [currentDate dateByAddingTimeInterval:daysInSeconds];
if( [starttime compare:currentDate]==NSOrderedAscending ){
//Ascending (CT < startTime)
}
if( [starttime compare:currentDate]==NSOrderedDescending ){
//Descending (CT > startTime)
}
if( [endtime compare:currentDate]==NSOrderedAscending ){
//Ascending (CT < endtime)
}
if( [endtime compare:currentDate]==NSOrderedDescending ){
//Descending (CT > endtime)
}

Related

Convert the for loop to accept ID type

I want to be able to reuse this method so it's not restricted by the class being called in the for loop declaration.
The problem is the compiler has no idea what id actually is, so I cannot use . notation on it. I need to cast it to a whatever type of event class i'll be passing it, instead of having to repeat the method for SpecialEvent1 SpecialEvent2 SpecialEvent3
So instead of for (SpecialEvent1 *event in day) I want to be able to do something like for (id event in day) but problem occurs when I try to access the time or duration property
- (NSArray *)sumDay:(NSArray *)day {
NSInteger morning = 0, afternoon = 0, evening = 0, night = 0;
for (SpecialEvent1 *event in day) {
NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:event.time];
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitHour fromDate:date];
NSInteger hour = [components hour];
if (hour < 12) {
morning += event.duration;
}
else if (hour < 18) {
afternoon += event.duration;
}
else if (hour < 20) {
evening += event.duration;
}
else {
night += event.duration;
}
}
NSArray *sums = #[#(morning), #(afternoon), #(evening), #(night)];
return sums;
}
Assuming that you aren't interested in objects that don't have a time or duration property, you could define a protocol which says this:
#protocol TimedEvent <NSObject>
-(NSTimeInterval)time;
-(NSTimeInterval)duration;
#end
Then go through the array like this:
- (NSArray *)sumDay:(NSArray *)day {
NSInteger morning = 0, afternoon = 0, evening = 0, night = 0;
for (id<TimedEvent> event in day) {
if (![event conformsToProtocol:#protocol(TimedEvent)]) {
continue;
}
NSDate *date = [NSDate dateWithTimeIntervalSinceReferenceDate:event.time];
NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitHour fromDate:date];
NSInteger hour = [components hour];
if (hour < 12) {
morning += event.duration;
}
else if (hour < 18) {
afternoon += event.duration;
}
else if (hour < 20) {
evening += event.duration;
}
else {
night += event.duration;
}
}
NSArray *sums = #[#(morning), #(afternoon), #(evening), #(night)];
return sums;
}

How to update UILabel frequently?

I want to update text for label frequently but it seems not working.
for (int i = 0; i <100; i++)
{
mylabel.text =[NSString stringWithFormat:#"%d", i];
}
Does anyone suggest for me an idea ? I thought. Maybe, we should update text label in multiple threads.
Watch is best example hope it will help you....
int second,minute; //set second = 0 and minute = 0
[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateCounter:) userInfo:nil repeats:YES];
- (void)updateCounter:(NSTimer *)theTimer {
second++;
if(second < 60)
{
if (second < 10)
{
timerLbl.text = [NSString stringWithFormat:#"00:0%d", second];
}
else
{
timerLbl.text = [NSString stringWithFormat:#"00:%d",second];
}
}
else
{
minute = second / 60;
int sec = second % 60;
if (minute < 10 && sec < 10)
{
timerLbl.text = [NSString stringWithFormat:#"0%d:0%d", minute, sec];
}
if(minute < 10 && sec >= 10)
{
timerLbl.text = [NSString stringWithFormat:#"0%d:%d", minute, sec];
}
if (minute >= 10 && sec < 10)
{
timerLbl.text = [NSString stringWithFormat:#"%d:0%d", minute, sec];
}
if(minute >= 10 && sec >= 10)
{
timerLbl.text = [NSString stringWithFormat:#"%d:%d", minute, sec];
}
}
}
Add below code in viewDidLoad
self.timer = [NSTimer scheduledTimerWithTimeInterval:0.5f
target:self
selector:#selector(showTime)
userInfo:NULL
repeats:YES];
- (void)showTime
{
NSDate *now=[NSDate date];
NSDateFormatter *dateFormatter=[NSDateFormatter new];
[dateFormatter setDateFormat:#"HH:mm:ss"];
timeLabel.text=[dateFormatter stringFromDate:now];
}
Hope this answer will help you....
use NSTimer for the regular interval and call the method where the lable is printed let suppose
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(targetMethod:)
userInfo:nil
repeats:Yes];
in the target method print the label on text
-(void)targetMethod:(NSTimer *)timer{
NSDate* date = [NSDate date];
NSDateFormatter* formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#" HH:MM:SS"];
NSString* str = [formatter stringFromDate:date];
label.text = str;
}
try this it will work surely

Calculating with time and getting a status

I hope you can help me with this:
I´m writing a App that should show if a shop has actually open.
For this i declared for each day and each opening times different variables / NSDate-Objects like (setting the dateformatter I´ve done before):
NSDate *mondayMorningOpening = [dateFormatter dateFromString:#"08:00"];
NSDate *montagMorningClosing = [dateFormatter dateFromString:#"12:30"];
NSDate *mondayNoonOpening = [dateFormatter dateFromString:#"15:00"];
NSDate *montagNoonClosing = [dateFormatter dateFromString:#"21:30"];
I´ve also set a NSDate for the actual time:
NSString *tempDate1 = [dateFormatter stringFromDate:date];
NSDate *actualTime = [dateFormatter dateFromString:tempDate1];
Now I want to calculate if the actual time is before or after the time range for the opening times of the shop. I´ve done this:
if ([actualTime earlierDate: mondayMorningClosing && [aktuelleZeit laterDate: mondayMorningOpening])
{
NSLog (#"The shop is open!");
}
else if ([actualTime earlierDate: mondayNoonClosing]&& [actualTime laterDate: mondayNoonOpening])
{
NSLog (#"The shop is open!");
}
else
{
NSLog (#"The shop is closed!");
}
But no matter what time it is, it´s always shown "The shop is open!".
Maybe you have an idea what to do that i can show the opening status right...
You misunderstood the meaning of earlierDate and laterDate.The methods are not "isEarlierDate" and "isLaterDate", they do not return a BOOL.These methods return a NSDate object, the earlier (or later) of the two dates.They're not nil objects, so they're always evaluated to true.
Compare the two dates taking it's time interval:
if ([actualTime timeIntervalSinceDate: mondayMorningClosing]<0 && [aktuelleZeit timeIntervalSinceDate: mondayMorningOpening]>0)
{
NSLog (#"The shop is open!");
}
You can compare two dates, but as a result you will have a NSDate:
if ([date1 compare:date2] == NSOrderedDescending) {
NSLog(#"date1 is later than date2");
} else if ([date1 compare:date2] == NSOrderedAscending) {
NSLog(#"date1 is earlier than date2");
}
If you have 2 dates you can determine if an NSDate is between those two like this:
- (BOOL)isDate:(NSDate *)date betweenFirstDate:(NSDate *)firstDate andSecondDate:(NSDate *)secondDate
{
BOOL isEqualToFirstOrSecond = [date compare:firstDate] == NSOrderedSame || [date compare:secondDate] == NSOrderedSame;
BOOL isBetweenFirstAndSecond = [date compare:firstDate] == NSOrderedDescending && [date compare:secondDate] == NSOrderedAscending;
return isEqualToFirstOrSecond || isBetweenFirstAndSecond;
}

How would I add only business days to an NSDate?

I have an issue related to calculating business days in Objective-C.
I need to add X business days to a given NSDate.
For example, if I have a date: Friday 22-Oct-2010, and I add 2 business days, I should get: Tuesday 26-Oct-2010.
Thanks in advance.
There are two parts to this:
Weekends
Holidays
I'm going to pull from two other posts to help me out.
For weekends, I'm going to need to know a given date's day of the week. For that, this post comes in handy:
How to check what day of the week it is (i.e. Tues, Fri?) and compare two NSDates?
For holidays, #vikingosegundo has a pretty great suggestion on this post:
List of all American holidays as NSDates
First, let's deal with the weekends;
I've wrapped up the suggestion in the post I cited above into this nice little helper function which tells us if a date is a weekday:
BOOL isWeekday(NSDate * date)
{
int day = [[[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:date] weekday];
const int kSunday = 1;
const int kSaturday = 7;
BOOL isWeekdayResult = day != kSunday && day != kSaturday;
return isWeekdayResult;
}
We'll need a way to increment a date by a given number of days:
NSDate * addDaysToDate(NSDate * date, int days)
{
NSDateComponents * components = [[NSDateComponents alloc] init];
[components setDay:days];
NSDate * result = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:date options:0];
[components release];
return result;
}
We need a way to skip over weekends:
NSDate * ensureDateIsWeekday(NSDate * date)
{
while (!isWeekday(date))
{
// Add one day to the date:
date = addDaysToDate(date, 1);
}
return date;
}
And we need a way to add an arbitrary number of days to a date:
NSDate * addBusinessDaysToDate(NSDate * start, int daysToAdvance)
{
NSDate * end = start;
for (int i = 0; i < daysToAdvance; i++)
{
// If the current date is a weekend, advance:
end = ensureDateIsWeekday(end);
// And move the date forward by one day:
end = addDaysToDate(end, 1);
}
// Finally, make sure we didn't end on a weekend:
end = ensureDateIsWeekday(end);
return end;
}
Note; There is an obvious optimization I skipped - you could easily add more than one day at a time to the current date - but the point of my post is to show you how to do this yourself - and not necessarily to come up with the best possible solution.
Now lets tie that up and see what we have so far:
int main() {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSDate * start = [NSDate date];
int daysToAdvance = 10;
NSDate * end = addBusinessDaysToDate(start, daysToAdvance);
NSLog(#"Result: %#", [end descriptionWithCalendarFormat:#"%Y-%m-%d"
timeZone:nil
locale:nil]);
[pool drain];
return 0;
}
So, we've got weekends covered, now we need to pull in the holidays.
Pulling in some RSS feed, or data from another source is definitely beyond the scope of my post... so, let's just assume you have some dates you know are holidays, or, according to your work calendar, are days off.
Now, I'm going to do this with an NSArray... but, again, this leaves plenty of room for improvement - at minimum it should be sorted. Better yet, some sort of hash set for fast lookups of dates. But, this example should suffice to explain the concept. (Here we construct an array which indicates there are holidays two and three days from now)
NSMutableArray * holidays = [[NSMutableArray alloc] init];
[holidays addObject:addDaysToDate(start, 2)];
[holidays addObject:addDaysToDate(start, 3)];
And, the implementation for this will be very similar to the weekends. We'll make sure the day isn't a holiday. If it is, we'll advance to the next day. So, a collection of methods to help with that:
BOOL isHoliday(NSDate * date, NSArray * holidays)
{
BOOL isHolidayResult = NO;
const unsigned kUnits = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents * components = [[NSCalendar currentCalendar] components:kUnits fromDate:date];
for (int i = 0; i < [holidays count]; i++)
{
NSDate * holiday = [holidays objectAtIndex:i];
NSDateComponents * holidayDateComponents = [[NSCalendar currentCalendar] components:kUnits fromDate:holiday];
if ([components year] == [holidayDateComponents year]
&& [components month] == [holidayDateComponents month]
&& [components day] == [holidayDateComponents day])
{
isHolidayResult = YES;
break;
}
}
return isHolidayResult;
}
and:
NSDate * ensureDateIsntHoliday(NSDate * date, NSArray * holidays)
{
while (isHoliday(date, holidays))
{
// Add one day to the date:
date = addDaysToDate(date, 1);
}
return date;
}
And, finally, make some modifications to our addition function to take into account the holidays:
NSDate * addBusinessDaysToDate(NSDate * start, int daysToAdvance, NSArray * holidays)
{
NSDate * end = start;
for (int i = 0; i < daysToAdvance; i++)
{
// If the current date is a weekend, advance:
end = ensureDateIsWeekday(end);
// If the current date is a holiday, advance:
end = ensureDateIsntHoliday(end, holidays);
// And move the date forward by one day:
end = addDaysToDate(end, 1);
}
// Finally, make sure we didn't end on a weekend or a holiday:
end = ensureDateIsWeekday(end);
end = ensureDateIsntHoliday(end, holidays);
return end;
}
Go ahead and try it:
int main() {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSDate * start = [NSDate date];
int daysToAdvance = 10;
NSMutableArray * holidays = [[NSMutableArray alloc] init];
[holidays addObject:addDaysToDate(start, 2)];
[holidays addObject:addDaysToDate(start, 3)];
NSDate * end = addBusinessDaysToDate(start, daysToAdvance, holidays);
[holidays release];
NSLog(#"Result: %#", [end descriptionWithCalendarFormat:#"%Y-%m-%d"
timeZone:nil
locale:nil]);
[pool drain];
return 0;
}
If you want the whole project, here ya go: http://snipt.org/xolnl
There's nothing built into NSDate or NSCalendar that counts business days for you. Business days depend to some degree on the business in question. In the US, "business day" generally means weekdays that aren't holidays, but each company determines which holidays to observe and when. For example, some businesses move observance of minor holidays to the last week of the year so that employees can be off between Christmas and New Year's Day without taking vacation.
So, you'll need to decide exactly what you mean by business day. It should then be simple enough write a little method to calculate a future date by adding some number of business days. Then use a category to add a method like -dateByAddingBusinessDays: to NSDate.
this answer is late to the party but…. I thought i might improve on above answers to determine business days by working with NSDateComponents directly of your date in a nice loop.
#define CURRENTC [NSCalendar currentCalendar]
#define CURRENTD [NSDate date]
NSInteger theWeekday;
NSDateComponents* temporalComponents = [[NSDateComponents alloc] init];
[temporalComponents setCalendar:CURRENTC];
[temporalComponents setDay: 13];
[temporalComponents setMonth: 2];
[temporalComponents setYear: theYear];
// CURRENTC =the current calendar which determines things like how
// many days in week for local, also the critical “what is a weekend”
// you can also convert a date directly to components. but the critical thing is
// to get the CURRENTC in, either way.
case 3:{ // the case of finding business days
NSDateComponents* startComp = [temporalComponents copy]; // start date components
for (int i = 1; i <= offset; i++) //offset is the number of busi days you want.
{
do {
[temporalComponents setDay: [temporalComponents day] + 1];
NSDate* tempDate = [CURRENTC dateFromComponents:temporalComponents];
theWeekday = [[CURRENTC components:NSWeekdayCalendarUnit fromDate:tempDate] weekday];
} while ((theWeekday == 1) || (theWeekday == 7));
}
[self findHolidaysStart:startComp end:temporalComponents]; // much more involved routine.
[startComp release];
break;
}
// use startComp and temporalcomponents before releasing
// temporalComponents now contain an offset of the real number of days
// needed to offset for busi days. startComp is just your starting date….(in components)
// theWeekday is an integer between 1 for sunday, and 7 for saturday, (also determined
// by CURRENTC
turning this back into NSDate, and you are done. Holidays are much more involved.. but can actually be calculated if just using federal holidays and a few others. because they are always something like “3rd monday of January”
here is what the findHolidaysStart:startComp end: starts out like, you can imagine the rest.
// imported
[holidayArray addObject:[CURRENTC dateFromComponents:startComp]];
[holidayArray addObject:[CURRENTC dateFromComponents:endComp]];
// hardcoded
dateComponents = [[NSDateComponents alloc] init];
[dateComponents setCalendar:CURRENTC];
[dateComponents setDay: 1];
[dateComponents setMonth: 1];
[dateComponents setYear: theYear];
theWeekday = [[CURRENTC components:NSWeekdayCalendarUnit fromDate:[CURRENTC dateFromComponents:dateComponents]] weekday];
if (theWeekday == 1) [dateComponents setDay:2];
if (theWeekday == 7) {[dateComponents setDay:31]; [dateComponents setYear: theYear-1];}
[holidayArray addObject:[CURRENTC dateFromComponents:dateComponents]];
[dateComponents release];
I took #steve's answer and added a method to calculate the days of all the federal holidays in USA and put it all in a Category. I've tested it and it works nicely. Check it out.
#import "NSDate+BussinessDay.h"
#implementation NSDate (BussinessDay)
-(NSDate *)addBusinessDays:(int)daysToAdvance{
NSDate * end = self;
NSArray *holidays = [self getUSHolidyas];
for (int i = 0; i < daysToAdvance; i++)
{
// Move the date forward by one day:
end = [self addDays:1 toDate:end];
// If the current date is a weekday, advance:
end = [self ensureDateIsWeekday:end];
// If the current date is a holiday, advance:
end = [self ensureDateIsntHoliday:end forHolidays:holidays];
}
return end;
}
#pragma mark - Bussiness Days Calculations
-(BOOL)isWeekday:(NSDate *) date{
int day = (int)[[[NSCalendar currentCalendar] components:NSWeekdayCalendarUnit fromDate:date] weekday];
const int kSunday = 1;
const int kSaturday = 7;
BOOL isWeekdayResult = day != kSunday && day != kSaturday;
return isWeekdayResult;
}
-(NSDate *)addDays:(int)days toDate:(NSDate *)date{
NSDateComponents * components = [[NSDateComponents alloc] init];
[components setDay:days];
NSDate * result = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:date options:0];
return result;
}
-(NSDate *)ensureDateIsWeekday:(NSDate *)date{
while (![self isWeekday:date])
{
// Add one day to the date:
date = [self addDays:1 toDate:date];
}
return date;
}
-(BOOL)isHoliday:(NSDate *)date forHolidays:(NSArray *)holidays{
BOOL isHolidayResult = NO;
const unsigned kUnits = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents * components = [[NSCalendar currentCalendar] components:kUnits fromDate:date];
for (int i = 0; i < [holidays count]; i++)
{
NSDate * holiday = [holidays objectAtIndex:i];
NSDateComponents * holidayDateComponents = [[NSCalendar currentCalendar] components:kUnits fromDate:holiday];
if ([components year] == [holidayDateComponents year]
&& [components month] == [holidayDateComponents month]
&& [components day] == [holidayDateComponents day])
{
isHolidayResult = YES;
break;
}
}
return isHolidayResult;
}
-(NSDate *)ensureDateIsntHoliday:(NSDate *)date forHolidays:(NSArray *)holidays{
while ([self isHoliday:date forHolidays:holidays])
{
// Add one day to the date:
date = [self addDays:1 toDate:date];
}
return date;
}
-(NSArray *)getUSHolidyas{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = #"yyyy";
NSString *year = [formatter stringFromDate:[NSDate date]];
NSString *nextYear = [formatter stringFromDate:[NSDate dateWithTimeIntervalSinceNow:(60*60*24*365)]];
formatter.dateFormat = #"M/d/yyyy";
//Constant Holidays
NSDate *newYearsDay = [formatter dateFromString:[NSString stringWithFormat:#"1/1/%#",nextYear]]; //Use next year for the case where we are adding days near end of december.
NSDate *indDay = [formatter dateFromString:[NSString stringWithFormat:#"7/4/%#",year]];
NSDate *vetDay = [formatter dateFromString:[NSString stringWithFormat:#"11/11/%#",year]];
NSDate *xmasDay = [formatter dateFromString:[NSString stringWithFormat:#"12/25/%#",year]];
//Variable Holidays
NSInteger currentYearInt = [[[NSCalendar currentCalendar]
components:NSYearCalendarUnit fromDate:[NSDate date]] year];
NSDate *mlkDay = [self getTheNth:3 occurrenceOfDay:2 inMonth:1 forYear:currentYearInt];
NSDate *presDay = [self getTheNth:3 occurrenceOfDay:2 inMonth:2 forYear:currentYearInt];
NSDate *memDay = [self getTheNth:5 occurrenceOfDay:2 inMonth:5 forYear:currentYearInt]; // Let's see if there are 5 Mondays in May
NSInteger month = [[[NSCalendar currentCalendar] components:NSYearCalendarUnit fromDate:memDay] month];
if (month > 5) { //Check that we are still in May
memDay = [self getTheNth:4 occurrenceOfDay:2 inMonth:5 forYear:currentYearInt];
}
NSDate *labDay = [self getTheNth:1 occurrenceOfDay:2 inMonth:9 forYear:currentYearInt];
NSDate *colDay = [self getTheNth:2 occurrenceOfDay:2 inMonth:10 forYear:currentYearInt];
NSDate *thanksDay = [self getTheNth:4 occurrenceOfDay:5 inMonth:11 forYear:currentYearInt];
return #[newYearsDay,mlkDay,presDay,memDay,indDay,labDay,colDay,vetDay,thanksDay,xmasDay];
}
-(NSDate *)getTheNth:(NSInteger)n occurrenceOfDay:(NSInteger)day inMonth:(NSInteger)month forYear:(NSInteger)year{
NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
dateComponents.year = year;
dateComponents.month = month;
dateComponents.weekday = day; // sunday is 1, monday is 2, ...
dateComponents.weekdayOrdinal = n; // this means, the first of whatever weekday you specified
return [[NSCalendar currentCalendar] dateFromComponents:dateComponents];
}
#end

Counting down the days - iPhone Count Down Timer

I’m trying to make a counter which shows the number of days until we leave on a trip to Europe. It’s only about 70 days (as of today) so I don’t believe that I should have to worry about astronomically large numbers or anything, but I really am stumped - I’ve attached the code that some friends have given me, which don’t work either. Trust me when I say I’ve tried everything I can think of - and before anyone bites my head off, which I have seen done on these forums, yes I did look very extensively at the Apple Documentation, however I’m not 100% sure where to start - I’ve tried NSTimer, NSDate and all their subclasses and methods, but there’s nothing that jumps out immediately.
In terms of what I think I should actually be doing, I think I need to somehow assign an integer value for the “day” today/ now/ the current day, which will change dynamically using the [NSDate date] and then the same for the date that we leave. The countdown is just updating when the method gets called again (I can do this using NSTimer if need be) and the value that is displayed on the countdown is the differnce between these two values.
I don’t especially want to have a flashing kind of thing that updates every second until we leave - personally I think that’s tacky, but if anyone knows how then I’d appreciate it for future reference.
I’ve also done an extensive search of google, and I may simply be using the wrong search terms, but I can’t find anything there either.
Any help is greatly appreciated.
Thank you very much.
Michaeljvdw
- (void)countDownMethod {
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:startDay];
[comps setMonth:startMonth];
[comps setYear:startYear];
[comps setHour:startHour];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:comps];
NSLog(#"%#",date);
[gregorian release];
[comps release];
NSTimeInterval diff = [date timeIntervalSinceNow];
int diffInt = diff;
NSString *days = [NSString stringWithFormat:#"%d",diffInt/86400];
day0.text = #"0";
day1.text = #"0";
day2.text = #"0";
NSLog(#"Days Length: %d",days.length);
if(days.length >= 1){
day2.text = [days substringFromIndex:days.length - 1];
if(days.length >= 2){
day1.text = [days substringWithRange:NSMakeRange(days.length - 2, 1)];
if(days.length >= 3){
day0.text = [days substringWithRange:NSMakeRange(days.length - 3, 1)];
}
}
}
NSString *hours = [NSString stringWithFormat:#"%d",(diffInt%86400)/3600];
hour0.text = #"0";
hour1.text = #"0";
NSLog(#"Hours Length: %d",hours.length);
if(hours.length >= 1){
hour1.text = [hours substringFromIndex:hours.length - 1];
if(hours.length >= 2){
hour0.text = [hours substringWithRange:NSMakeRange(hours.length - 2, 1)];
}
}
NSString *minutes = [NSString stringWithFormat:#"%d",((diffInt%86400)%3600)/60];
minute0.text = #"0";
minute1.text = #"0";
NSLog(#"Minutes Length: %d",minutes.length);
if(minutes.length >= 1){
minute1.text = [minutes substringFromIndex:minutes.length - 1];
if(minutes.length >= 2){
minute0.text = [minutes substringWithRange:NSMakeRange(minutes.length - 2, 1)];
}
}
}
If you know the time in seconds between 2 dates (your NSTimeInterval) then you can easily convert that into a string in the format days:hours:mins:secs as follows.
- (NSString*)secsToDaysHoursMinutesSecondsString:(NSTimeInterval)theSeconds {
div_t r1 = div(theSeconds, 60*60*24);
NSInteger theDays = r1.quot;
NSInteger secsLeftFromDays = r1.rem;
div_t r2 = div(secsLeftFromDays, 60*60);
NSInteger theHours = r2.quot;
NSInteger secsLeftFromHours = r2.rem;
div_t r3 = div(secsLeftFromHours, 60);
NSInteger theMins = r3.quot;
NSInteger theSecs = r3.rem;
NSString* days;
if (theDays < 10) { // make it 2 digits
days = [NSString stringWithFormat:#"0%i", theDays];
} else {
days = [NSString stringWithFormat:#"%i", theDays];
}
NSString* hours;
if (theHours < 10) { // make it 2 digits
hours = [NSString stringWithFormat:#"0%i", theHours];
} else {
hours = [NSString stringWithFormat:#"%i", theHours];
}
NSString* mins;
if (theMins < 10) { // make it 2 digits
mins = [NSString stringWithFormat:#"0%i", theMins];
} else {
mins = [NSString stringWithFormat:#"%i", theMins];
}
NSString* secs;
if (theSecs < 10) { // make it 2 digits
secs = [NSString stringWithFormat:#"0%i", theSecs];
} else {
secs = [NSString stringWithFormat:#"%i", theSecs];
}
return [NSString stringWithFormat:#"%#:%#:%#:%#", days, hours, mins,secs];
}
//Another simple way to get the numbers of days difference to a future day from today.
NSTimeInterval todaysDiff = [todayDate timeIntervalSinceNow];
NSTimeInterval futureDiff = [futureDate timeIntervalSinceNow];
NSTimeInterval dateDiff = futureDiff - todaysDiff;
div_t r1 = div(dateDiff, 60*60*24);
NSInteger theDays = r1.quot;
label.text = [NSString stringWithFormat:#"%i", theDays];