Problems with NSTimeInterval timeIntervalSinceDate - objective-c

I want to code an alarm clock for iOS.
My code for calculating the difference between current time and alarm time:
NSDate *date = picker.date;
NSLog(#"[date description] %#",[date description]);
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
[outputFormatter setDateFormat:#"HH:mm:ss"]; //24h time format
NSString *dateString = [outputFormatter stringFromDate:picker.date];
NSLog(#"[date description] %#",dateString);
NSDate *startDate = [outputFormatter dateFromString:dateString];
NSDate *currentTime = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"HH:mm:ss"];
NSString *resultString = [dateFormatter stringFromDate: currentTime];
NSDate *endDate = [dateFormatter dateFromString:resultString];
NSTimeInterval timeDifference = [endDate timeIntervalSinceDate:startDate];
double minutes = timeDifference / 60;
double hours = minutes / 60;
double seconds = timeDifference;
...which leads to these variables:
startDate = 2000-01-01 06:45:26 +0000
endDate = 2000-01-01 22:46:36 +0000
seconds = 57670 (= 16.01944 hours).
How to get to calculate the real time difference of 28740 seconds?

Just pass timeDifference in below method. It will give you Hours,Minutes and Seconds.
- (NSString *)timeFormatted:(int)totalSeconds{
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
int hours = totalSeconds / 3600;
return hours==0 ? [NSString stringWithFormat:#"%02d:%02d", minutes, seconds] : [NSString stringWithFormat:#"%02d:%02d:%02d",hours, minutes, seconds];
}

try below code:
Get time difference in hour, minutes,seconds from NSTimeInterval:
//.......
NSTimeInterval timeDifference = [endDate timeIntervalSinceDate:startDate];
long ti = lroundf(timeInterval);
int hour = ti / 3600;
int mins = (ti % 3600) / 60;
int secs = ti % 60;
OR
Get time difference in hour, minutes,seconds from Dates:
// Get the system calendar
NSCalendar *objCalendar = [NSCalendar currentCalendar];
// Create the NSDates
NSDate *currentTime = [[NSDate alloc] init];
NSDate *startDate = picker.date;
// Get conversion to months, days, hours, minutes
unsigned int unitFlags = NSHourCalendarUnit | NSMinuteCalendarUnit | NSDayCalendarUnit | NSMonthCalendarUnit;
NSDateComponents *TimeInfo = [objCalendar components:unitFlags fromDate: currentTime toDate:startDate options:0];
NSLog(#" %dmin %dhours %ddays %dmoths ",[TimeInfo minute], [TimeInfo hour], [TimeInfo day], [TimeInfo month]);

Related

Converting time to HH:MM

I currently have a float value like 12.5, 4, 17.5. I want these to correspond to the times 12:30PM, 4:00AM, and 5:30PM.
I've currently achieved something close to this with the hack
if (time > 12.5) {
time = abs(roundedValue - 12);
[lab setText:[NSString stringWithFormat:#"%i:00PM",(int)time]];
} else {
[lab setText:[NSString stringWithFormat:#"%i:00AM",(int)time]];
}
But I know this is bad practice. What's a better way to convert these numbers to times?
This is just basic math, you have a value, say 12.5, which consists of a number of hours, 12, and a fraction of an hour, 0.5. There are 60 mins in an hour so the number of minutes is just the fraction times 60.
If you want to use the 12 hour clock there is a small quirk, hours > 12 need to be reduced by 12 but noon (12) is pm and midnight (0 or 24) is am. So the test for am/pm is not the same test as whether to subtract 12.
Here is one way to do it (with minimal checking):
NSString *hoursToString(double floatHours)
{
int hours = trunc(floatHours); // number of hours
int mins = round( (floatHours - hours) * 60 ); // mins is the fractional part times 60
// rounding might result in 60 mins...
if (mins == 60)
{
mins = 0;
hours++;
}
// we haven't done a range check on floatHours, also the above can add 1, so reduce to 0 -> 23
hours %= 24;
// if you are using 24 hour clock you can finish here and format to the two values
BOOL pm = hours >= 12; // 0 - 11 = am, 12 - 23 = pm
if (hours > 12) hours -= 12; // 13 - 23 -> 1 -> 11
return [NSString stringWithFormat:#"%d:%02d %s", hours, mins, (pm ? "pm" : "am")];
}
You call this simply as:
hoursToString(13.1) // returns 1:06 pm
No need to use NSDate et al.
HTH
Solved by doing the following:
NSDate *now = [NSDate date];
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:now];
[components setHour:0];
NSDate *today10am = [calendar dateFromComponents:components];
NSDate *newDate = [NSDate dateWithTimeInterval:roundedValue*60*60 sinceDate:today10am];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"h:mm aa"];
[lab setText:[dateFormat stringFromDate:newDate]];
Sorry Hot Licks, guess this was within my comprehension.
You can use the following -
NSNumber *time = [NSNumber numberWithDouble:([yourTime doubleValue] - 3600)];
NSTimeInterval interval = [time doubleValue];
NSDate *yourDate = [NSDate date];
yourDate = [NSDate dateWithTimeIntervalSince1970:interval];
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:#"HH:mm:ss"];
NSLog(#"result: %#", [dateFormatter stringFromDate:yourDate]);

Objective-C Xcode - if statement "Expected expression"

i must check if the interval between 2 times is > 0 then set the text of a label but i get "Expected expression" when i use the if statement..
NSDate * now = [NSDate date];
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
[outputFormatter setDateFormat:#"HH:mm:ss"];
NSString *newDateString = [outputFormatter stringFromDate:now];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"HH:mm:ss"];
NSDate *date1 = [df dateFromString:newDateString];
NSDate *date2 = [df dateFromString:#"15:00:00"];
NSTimeInterval interval = [date2 timeIntervalSinceDate:date1];
int hours = (int)interval / 3600; // integer division to get the hours part
int minutes = (interval - (hours*3600)) / 60; // interval minus hours part (in seconds) divided by 60 yields minutes
int seconds = interval - ((hours*3600)+(minutes*60)) ;
NSString *timeDiff = [NSString stringWithFormat:#"%02d | %02d | %02d", hours, minutes, seconds];
if (interval < 0)
{
self.before3.text = timeDiff;
}
The error is on if (interval < 0)
Can someone help me please?
Regards.

24 hours divided by 30 minutes apart - NSDate

I'm trying to get an NSMutableArray of NSDates each NSDate object targets the nearest rounded either HH:00 or HH:30 for the next 24 hours from now.
lets say right now its 02:31 I want an output of #[03:00,03:30,04:00,04:30...03:00(of the next day)]
if its 02:29 then I want #[02:30,03:00 and so on till the next day at 02:30].
right now I have the code below and it works almost all the time, yet rarely I get an output of all the NSDate objects that I want with a remainder of an extra minute(#[03:01,03:31:04:01...so on]).
any ideas ?
-(NSMutableArray*)TwentyFourHoursFromNowDivicedBy30Mins
{
NSMutableArray * dateArray = [NSMutableArray array];
NSCalendar * cal = [NSCalendar currentCalendar];
NSDateComponents * plusDays = [NSDateComponents new];
NSDate * now = [self changeTimeValue:[NSDate date]];
for( NSUInteger day = 0; day < 2; day++ )
{
[plusDays setDay:day];
[dateArray addObject:[cal dateByAddingComponents:plusDays toDate:now options:0]];
}
NSDate *startDate = [dateArray objectAtIndex:0];
NSDate *endDate = [dateArray objectAtIndex:1];
NSDateComponents *diff = [[NSDateComponents alloc] init];
[diff setMinute:0];
NSCalendar *calz = [NSCalendar currentCalendar];
NSDate *tmp = startDate;
NSMutableArray *dates = [NSMutableArray arrayWithObject:tmp];
while ([tmp laterDate:endDate] == endDate) {
[diff setMinute:[diff minute] + 30];
tmp = [calz dateByAddingComponents:diff toDate:startDate options:0];
[dates addObject:tmp];
}
return dates;
}
- (NSDate *)changeTimeValue:(NSDate *)dateValue{
NSDateComponents *time = [[NSCalendar currentCalendar]
components:NSHourCalendarUnit | NSMinuteCalendarUnit
fromDate:dateValue];
long val = 0;
NSDate *newDate = [[NSDate alloc] init];
NSInteger minutes = [time minute];
if(minutes > 0 && minutes < 30) {
val = 30 - minutes; NSTimeInterval aTimeInterval = [dateValue
timeIntervalSinceReferenceDate] + 60 * val + minutes;
newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
return newDate;
} else if(minutes > 30 && minutes < 60) {
val = 60 - minutes;
NSTimeInterval aTimeInterval = [dateValue timeIntervalSinceReferenceDate]
+ 60 * val;
newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval];
return newDate;
} else {
return newDate;
}
}
You're not zeroing out the seconds in your changeTimeValue, and in any case I think you've overcomplicated it. So I suspect you're subsequently seeing rounding issues. Just use NSDateComponents to do the whole job:
NSCalendar *currentCalendar = [NSCalendar currentCalendar];
NSDateComponents *dateComponents = [currentCalendar
components:NSHourCalendarUnit |
NSMinuteCalendarUnit |
NSYearCalendarUnit |
NSMonthCalendarUnit |
NSDayCalendarUnit
fromDate:dateValue];
dateComponents.minute += 15;
dateComponents.minute -= dateComponents.minute%30;
return [currentCalendar dateFromComponents:dateComponents];

How can I compare two dates, return a number of days

how can I compare two dates return number of days.
Ex: Missing X days of the Cup.
look my code.
NSDateFormatter *df = [[NSDateFormatter alloc]init];
[df setDateFormat:#"d MMMM,yyyy"];
NSDate *date1 = [df dateFromString:#"11-05-2010"];
NSDate *date2 = [df dateFromString:#"11-06-2010"];
NSTimeInterval interval = [date2 timeIntervalSinceDate:date1];
//int days = (int)interval / 30;
//int months = (interval - (months/30)) / 30;
NSString *timeDiff = [NSString stringWithFormat:#"%dMissing%d days of the Cup",date1,date2, fabs(interval)];
label.text = timeDiff; // output (Missing X days of the Cup)
From Apple's example, basically use an NSCalendar:
NSDate * date1 = <however you initialize this>;
NSDate * date2 = <...>;
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger unitFlags = NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents *components = [gregorian components:unitFlags
fromDate:date1
toDate:date2 options:0];
NSInteger months = [components month];
NSInteger days = [components day];
You can use next category:
#interface NSDate (Additions)
-(NSInteger)numberOfDaysUntilDay:(NSDate *)aDate;
-(NSInteger)numberOfHoursUntilDay:(NSDate *)aDate;
#end
#implementation NSDate (Additions)
const NSInteger secondPerMunite = 60;
const NSInteger munitePerHour = 60;
const NSInteger hourPerDay = 24;
-(NSInteger)numberOfDaysUntilDay:(NSDate *)aDate
{
NSInteger selfTimeInterval = [aDate timeIntervalSinceDate:self];
return abs(selfTimeInterval / (secondPerMunite * munitePerHour * hourPerDay));
}
-(NSInteger)numberOfHoursUntilDay:(NSDate *)aDate
{
NSInteger selfTimeInterval = [aDate timeIntervalSinceDate:self];
return abs(selfTimeInterval / (secondPerMunite * munitePerHour));
}
#end
Need to call this method and set 2 dates only which we want to calculate differently.
-(void) calculateSleepHours:(NSDate *)sleepDate :(NSDate *)wakeStr
{
if (sleepDate !=nil && wakeStr!=nil) {`enter code here`
NSDateFormatter *dateFormatter1 = [[NSDateFormatter alloc] init];
[dateFormatter1 setDateFormat:#"yyyy-MM-dd HH:mm:ssZ"];
NSDate *date1 = [ApplicationManager getInstance].sleepTime;;
NSDate *date2 = [ApplicationManager getInstance].wakeupTime;
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger unitFlags = NSMonthCalendarUnit | NSDayCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit|NSSecondCalendarUnit;
NSDateComponents *components = [gregorian components:unitFlags
fromDate:date1
toDate:date2 options:0];
NSInteger months = [components month];
NSInteger days = [components day];
NSInteger hours = [components hour];
NSInteger minute=[components minute];
NSInteger second=[components second];
DLog(#"Month %ld day %ld hour is %ld min %ld sec %ld ",(long)months,(long)days,(long)hours,(long)minute,(long)second);
sleepHours.text=[NSString stringWithFormat:#"Hour %ld Min %ld Sec %ld",(long)hours,(long)minute,(long)second];
}
}
Try this category:
#interface NSDate (DateUtils)
-(NSInteger)numberOfDaysUntilDay:(NSDate *)aDate;
#end
#implementation NSDate (DateUtils)
-(NSInteger)numberOfDaysUntilDay:(NSDate *)aDate
{
NSCalendar *calendar = [[NSCalendar alloc]
initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *components = [calendar components:NSCalendarUnitDay
fromDate:self
toDate:aDate options:kNilOptions];
return [components day];
}
#end
You can use this category by adding an import:
#import "NSDate+DateUtils.h"
And call it from your code:
NSInteger days = [myDate numberOfDaysUntilDay:someOtherDate];

Convert NSNumber (double) value into time

i try to convert a value like "898.171813964844" into 00:17:02 (hh:mm:ss).
How can this be done in objective c?
Thanks for help!
Final solution:
NSNumber *time = [NSNumber numberWithDouble:([online_time doubleValue] - 3600)];
NSTimeInterval interval = [time doubleValue];
NSDate *online = [NSDate date];
online = [NSDate dateWithTimeIntervalSince1970:interval];
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:#"HH:mm:ss"];
NSLog(#"result: %#", [dateFormatter stringFromDate:online]);
Assuming you are just interested in hours, minutes and seconds and that the input value is less or equal 86400 you could do something like this:
NSNumber *theDouble = [NSNumber numberWithDouble:898.171813964844];
int inputSeconds = [theDouble intValue];
int hours = inputSeconds / 3600;
int minutes = ( inputSeconds - hours * 3600 ) / 60;
int seconds = inputSeconds - hours * 3600 - minutes * 60;
NSString *theTime = [NSString stringWithFormat:#"%.2d:%.2d:%.2d", hours, minutes, seconds];
I know the answer has already been accepted, but here is my response using NSDateFormatter and taking into account timezone (to your timezone hours [eg. GMT+4] being unexpectedly added #Ben)
NSTimeInterval intervalValue = 898.171813964844;
NSDateFormatter *hmsFormatter = [[NSDateFormatter alloc] init];
[hmsFormatter setDateFormat:#"HH:mm:ss"];
[hmsFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSLog(#"formatted date: %#", [hmsFormatter stringFromDate:[NSDate dateWithTimeIntervalSinceReferenceDate:intervalValue]]);
[side note] #phx: assuming 898.171813964844 is in seconds, this would represent 00:14:58 not 00:17:02.
Convert your NSNumber value to a NSTimeInterval with -doubleValue
Convert your NSTimeInterval value to a NSDate with +dateWithTimeIntervalSinceNow:
Convert your NSDate to a NSString with -descriptionWithCalendarFormat:timeZone:locale: