How do I convert a number to hours and minutes? - iphone

I got help with correct calculation the other day but I've hit a block about how to implement it into code.
-(IBAction)done:(id)sender {
int result = (([startHours.text intValue] * 60) + [startMinutes.text intValue]) -
(([finishHours.text intValue] * 60) + [finishMinutes.text intValue]);
totalHours.text = [NSString stringWithFormat:#"%i", result / 60];
if (result < 0) {
totalHours.text = [NSString stringWithFormat:#"%d", result * -1];
}
The above is the code. However, in the text field it comes out as the total number of minutes. I want to covert it so it would show up as total hours and minutes (10.30). How would I do that in code?

If result is a time in minutes:
int minutes = result%60
int hours = (result - minutes)/60
totalHours.text = [NSString stringWithFormat:#"%d.%d", hours, minutes];

Pheelicks's answer is OK. Just two small additions: handle sign of interval before calculating parts, and use more common time format:
int result = (([startHours.text intValue] * 60) + [startMinutes.text intValue]) -
(([finishHours.text intValue] * 60) + [finishMinutes.text intValue]);
int minutes = abs(result)%60
int hours = (abs(result) - minutes)/60
totalHours.text = [NSString stringWithFormat:#"%02d:%02d", hours, minutes];

Try changing the int to a float.
-(IBAction)done:(id)sender {
float result = (([startHours.text intValue] * 60) + [startMinutes.text intValue]) -
(([finishHours.text intValue] * 60) + [finishMinutes.text intValue]);
totalHours.text = [NSString stringWithFormat:#"%2.2f", result / 60];
if (result < 0) {
totalHours.text = [NSString stringWithFormat:#"%2.2f", result * -1];
}

Related

how to convert value one format into the another format?

This is my Button method. When I press the button it's value is every time increment one & display into Label. Then it's reach 6 then convert like 1.0 , 7 = 1.1, 8 = 1.2 , 12 like 2.0 like cricket over format.
How can I do that?
-(void)OneNoBTNPressedMethod
{
// LBL it's my label & display the text
NSString * overStorage = LBL.text;
// perform the addition operation
CalcOperation operation;
operation = Plus;
//add one every time when we press the button
NSString * overOneBTNStr = [NSString stringWithFormat:#"1"];
NSString *overVal = overOneBTNStr;
LBL.text= [NSString stringWithFormat:#"%qi",[overVal longLongValue]+[overStorage longLongValue]];
}
Thanx in advance..
It worked for me. Hope it works for you as well. Assuming your LBL contains "1" as initial text. hope it helps
- OneNoBTNPressedMethod {
NSString *str = LBL.text;
NSArray *arr = [str componentsSeparatedByString:#"."];
if ([arr count] == 1) {
if ([LBL.text intValue] >= 5) {
LBL.text = [NSString stringWithFormat:#"%i.%i",0,0];
} else {
LBL.text = [NSString stringWithFormat:#"%i",[LBL.text intValue] + 1];
}
} else if ([arr count] == 2) {
if ([[arr objectAtIndex:1] intValue] >= 5) {
int left = [[arr objectAtIndex:0] intValue] + 1;
LBL.text = [NSString stringWithFormat:#"%i.%i",left,0];
} else {
LBL.text = [NSString stringWithFormat:#"%i.%i",[[arr objectAtIndex:0] intValue],[[arr objectAtIndex:1] intValue] + 1];
}
}
}
Try this logic
Let `int num` is count
Then
numBeforeDecimal = num/6;
numAfterDecimal = num%6;
Concatenate both number
[NSString stringWithFormat: #"%d.%d",numBeforeDecimal,numAfterDecimal];

NSDate - timeIntevalSinceDate -

I have 2 text fields where users can insert 2 time (ie. 12.00pm and 15.00pm) and a label that return the hours (ie 3 hours). I'm using timeIntervalSinceDate but I'm getting it in seconds (10800 sec which is equal to 3 hours). How can I get the value in hours? here the code:
-(IBAction)calcoloBlockTime{
NSString *blockOff = [NSString stringWithFormat:#"%#", [offBlock text]];
NSString *blockIn= [NSString stringWithFormat: #"%#", [inBlock text]];
NSDateFormatter *dateFormatter =[[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"HHmm"];
NSDate *dateFromString = [dateFormatter dateFromString:blockOff];
NSDate *dateFromString2 = [dateFormatter dateFromString:blockIn];
NSLog(#"Time elapsed: %f", [dateFromString2 timeIntervalSinceDate:dateFromString]);
}
thanks in advance.
If you are only interested in hours you can write:
NSInteger hours = 10800 / 3600; // You know that in an hour there is 3600 seconds
If you want minutes etc you will continue with the result of 10800 modulus 3600, which will give you the seconds which are left after dividing it by 3600.
NSInteger temp = 10800 % 3600;
NSInteger minutes = temp / 60;
And to get the seconds left after this you write:
NSInteger seconds = minutes % 60;
EDIT
myLabel.text = [NSString stringWithFormat:#"%d hours", hours];
If you want to set the hours on the label.
hours = seconds / 3600; Simple!!! And, it seems there is no way to get the hour from NSDate. You can use NSDateComponents, but they are too costly for your requirement.
I made a class method that returns a string with a formatted date of the remaining time between an NSDate and now.
+(NSString *)TimeRemainingUntilDate:(NSDate *)date {
NSTimeInterval interval = [date timeIntervalSinceNow];
NSString * timeRemaining = nil;
if (interval > 0) {
div_t d = div(interval, 86400);
int day = d.quot;
div_t h = div(d.rem, 3600);
int hour = h.quot;
div_t m = div(h.rem, 60);
int min = m.quot;
NSString * nbday = nil;
if(day > 1)
nbday = #"days";
else if(day == 1)
nbday = #"day";
else
nbday = #"";
NSString * nbhour = nil;
if(hour > 1)
nbhour = #"hours";
else if (hour == 1)
nbhour = #"hour";
else
nbhour = #"";
NSString * nbmin = nil;
if(min > 1)
nbmin = #"mins";
else
nbmin = #"min";
timeRemaining = [NSString stringWithFormat:#"%#%# %#%# %#%#",day ? [NSNumber numberWithInt:day] : #"",nbday,hour ? [NSNumber numberWithInt:hour] : #"",nbhour,min ? [NSNumber numberWithInt:min] : #"",nbmin];
}
else
timeRemaining = #"Over";
return timeRemaining;
}

Smart Formatting of time span

I need a method to format a NSTimeInterval (time span in seconds) into a string to produce something like "about 10 minutes ago", "1h, 20min", or "less than 1 minute".
-(NSString*) formattedTimeSpan:(NSTimeInterval)interval;
Target platform is iOS. Sample code is welcome.
This is a category for NSDate. It's not exactly using an NSTimeInterval, well internally :) I assume you are working with timestamps.
Header file NSDate+PrettyDate.h
#interface NSDate (PrettyDate)
- (NSString *)prettyDate;
#end
Implementation NSDate+PrettyDate.m
#implementation NSDate (PrettyDate)
- (NSString *)prettyDate
{
NSString * prettyTimestamp;
float delta = [self timeIntervalSinceNow] * -1;
if (delta < 60) {
prettyTimestamp = #"just now";
} else if (delta < 120) {
prettyTimestamp = #"one minute ago";
} else if (delta < 3600) {
prettyTimestamp = [NSString stringWithFormat:#"%d minutes ago", (int) floor(delta/60.0) ];
} else if (delta < 7200) {
prettyTimestamp = #"one hour ago";
} else if (delta < 86400) {
prettyTimestamp = [NSString stringWithFormat:#"%d hours ago", (int) floor(delta/3600.0) ];
} else if (delta < ( 86400 * 2 ) ) {
prettyTimestamp = #"one day ago";
} else if (delta < ( 86400 * 7 ) ) {
prettyTimestamp = [NSString stringWithFormat:#"%d days ago", (int) floor(delta/86400.0) ];
} else {
NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterMediumStyle];
prettyTimestamp = [NSString stringWithFormat:#"on %#", [formatter stringFromDate:self]];
[formatter release];
}
return prettyTimestamp;
}
You might want to refer to Facebook three20 framework. In their NSDateAdditions, they provided a few pretty formats for date. It might be better than you extend it.
Refer to the source at https://github.com/facebook/three20/blob/master/src/Three20Core/Sources/NSDateAdditions.m
- (NSString*)formatShortRelativeTime; will give you "<1m", "50m", "3h", "3d"
Here is one that formats the date in the style of Facebook:
https://github.com/nikilster/NSDate-Time-Ago

iPhone: NSTimer Countdown (Display Minutes:Seconds)

I have my timer code set up, and it's all kosher, but I want my label to display "Minutes : seconds" instead of just seconds.
-(void)countDown{
time -= 1;
theTimer.text = [NSString stringWithFormat:#"%i", time];
if(time == 0)
{
[countDownTimer invalidate];
}
}
I've already set "time" to 600, or 10 minutes. However, I want the display to show 10:59, 10:58, etc. until it reaches zero.
How do I do this?
Thanks!
int seconds = time % 60;
int minutes = (time - seconds) / 60;
theTimer.text = [NSString stringWithFormat:#"%d:%.2d", minutes, seconds];
By the time, I was made a little upgrade of first answer, it removed conflicts that associated from NSInteger and int:
NSInteger secondsLeft = 987;
int second = (int)secondsLeft % 60;
int minutes = ((int)secondsLeft - second) / 60;
theTimer.text = [NSString stringWithFormat:#"%02d:%02d", minutes, second]];

iPhone: Convert date string to a relative time stamp

I've got a timestamp as a string like:
Thu, 21 May 09 19:10:09 -0700
and I'd like to convert it to a relative time stamp like '20 minutes ago' or '3 days ago'.
What's the best way to do this using Objective-C for the iPhone?
-(NSString *)dateDiff:(NSString *)origDate {
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setFormatterBehavior:NSDateFormatterBehavior10_4];
[df setDateFormat:#"EEE, dd MMM yy HH:mm:ss VVVV"];
NSDate *convertedDate = [df dateFromString:origDate];
[df release];
NSDate *todayDate = [NSDate date];
double ti = [convertedDate timeIntervalSinceDate:todayDate];
ti = ti * -1;
if(ti < 1) {
return #"never";
} else if (ti < 60) {
return #"less than a minute ago";
} else if (ti < 3600) {
int diff = round(ti / 60);
return [NSString stringWithFormat:#"%d minutes ago", diff];
} else if (ti < 86400) {
int diff = round(ti / 60 / 60);
return[NSString stringWithFormat:#"%d hours ago", diff];
} else if (ti < 2629743) {
int diff = round(ti / 60 / 60 / 24);
return[NSString stringWithFormat:#"%d days ago", diff];
} else {
return #"never";
}
}
Here are methods from Cocoa to help you to get relevant info (not sure if they are all available in coca-touch).
NSDate * today = [NSDate date];
NSLog(#"today: %#", today);
NSString * str = #"Thu, 21 May 09 19:10:09 -0700";
NSDate * past = [NSDate dateWithNaturalLanguageString:str
locale:[[NSUserDefaults
standardUserDefaults] dictionaryRepresentation]];
NSLog(#"str: %#", str);
NSLog(#"past: %#", past);
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
unsigned int unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit |
NSDayCalendarUnit |
NSHourCalendarUnit | NSMinuteCalendarUnit |
NSSecondCalendarUnit;
NSDateComponents *components = [gregorian components:unitFlags
fromDate:past
toDate:today
options:0];
NSLog(#"months: %d", [components month]);
NSLog(#"days: %d", [components day]);
NSLog(#"hours: %d", [components hour]);
NSLog(#"seconds: %d", [components second]);
The NSDateComponents object seems to hold the difference in relevant units (as specified).
If you specify all units you can then use this method:
void dump(NSDateComponents * t)
{
if ([t year]) NSLog(#"%d years ago", [t year]);
else if ([t month]) NSLog(#"%d months ago", [t month]);
else if ([t day]) NSLog(#"%d days ago", [t day]);
else if ([t minute]) NSLog(#"%d minutes ago", [t minute]);
else if ([t second]) NSLog(#"%d seconds ago", [t second]);
}
If you want to calculate yourself you can have a look at:
NSDate timeIntervalSinceDate
And then use seconds in the algorithm.
Disclaimer: If this interface is getting deprecated (I haven't checked), Apple's preferred way of doing this via NSDateFormatters, as suggested in comments below, looks pretty neat as well - I'll keep my answer for historical reasons, it may still be useful for some to look at the logic used.
I can't edit yet, but I took Gilean's code and made a couple of tweaks and made it a category of NSDateFormatter.
It accepts a format string so it will work w/ arbitrary strings and I added if clauses to have singular events be grammatically correct.
Cheers,
Carl C-M
#interface NSDateFormatter (Extras)
+ (NSString *)dateDifferenceStringFromString:(NSString *)dateString
withFormat:(NSString *)dateFormat;
#end
#implementation NSDateFormatter (Extras)
+ (NSString *)dateDifferenceStringFromString:(NSString *)dateString
withFormat:(NSString *)dateFormat
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[dateFormatter setDateFormat:dateFormat];
NSDate *date = [dateFormatter dateFromString:dateString];
[dateFormatter release];
NSDate *now = [NSDate date];
double time = [date timeIntervalSinceDate:now];
time *= -1;
if(time < 1) {
return dateString;
} else if (time < 60) {
return #"less than a minute ago";
} else if (time < 3600) {
int diff = round(time / 60);
if (diff == 1)
return [NSString stringWithFormat:#"1 minute ago", diff];
return [NSString stringWithFormat:#"%d minutes ago", diff];
} else if (time < 86400) {
int diff = round(time / 60 / 60);
if (diff == 1)
return [NSString stringWithFormat:#"1 hour ago", diff];
return [NSString stringWithFormat:#"%d hours ago", diff];
} else if (time < 604800) {
int diff = round(time / 60 / 60 / 24);
if (diff == 1)
return [NSString stringWithFormat:#"yesterday", diff];
if (diff == 7)
return [NSString stringWithFormat:#"last week", diff];
return[NSString stringWithFormat:#"%d days ago", diff];
} else {
int diff = round(time / 60 / 60 / 24 / 7);
if (diff == 1)
return [NSString stringWithFormat:#"last week", diff];
return [NSString stringWithFormat:#"%d weeks ago", diff];
}
}
#end
In the interest of completeness, based on a #Gilean's answer, here's the complete code for a simple category on NSDate that mimics rails' nifty date helpers. For a refresher on categories, these are instance methods that you would call on NSDate objects. So, if I have an NSDate that represents yesterday, [myDate distanceOfTimeInWordsToNow] => "1 day".
Hope it's useful!
#interface NSDate (NSDate_Relativity)
-(NSString *)distanceOfTimeInWordsSinceDate:(NSDate *)aDate;
-(NSString *)distanceOfTimeInWordsToNow;
#end
#implementation NSDate (NSDate_Relativity)
-(NSString *)distanceOfTimeInWordsToNow {
return [self distanceOfTimeInWordsSinceDate:[NSDate date]];
}
-(NSString *)distanceOfTimeInWordsSinceDate:(NSDate *)aDate {
double interval = [self timeIntervalSinceDate:aDate];
NSString *timeUnit;
int timeValue;
if (interval < 0) {
interval = interval * -1;
}
if (interval< 60) {
return #"seconds";
} else if (interval< 3600) { // minutes
timeValue = round(interval / 60);
if (timeValue == 1) {
timeUnit = #"minute";
} else {
timeUnit = #"minutes";
}
} else if (interval< 86400) {
timeValue = round(interval / 60 / 60);
if (timeValue == 1) {
timeUnit = #"hour";
} else {
timeUnit = #"hours";
}
} else if (interval< 2629743) {
int days = round(interval / 60 / 60 / 24);
if (days < 7) {
timeValue = days;
if (timeValue == 1) {
timeUnit = #"day";
} else {
timeUnit = #"days";
}
} else if (days < 30) {
int weeks = days / 7;
timeValue = weeks;
if (timeValue == 1) {
timeUnit = #"week";
} else {
timeUnit = #"weeks";
}
} else if (days < 365) {
int months = days / 30;
timeValue = months;
if (timeValue == 1) {
timeUnit = #"month";
} else {
timeUnit = #"months";
}
} else if (days < 30000) { // this is roughly 82 years. After that, we'll say 'forever'
int years = days / 365;
timeValue = years;
if (timeValue == 1) {
timeUnit = #"year";
} else {
timeUnit = #"years";
}
} else {
return #"forever ago";
}
}
return [NSString stringWithFormat:#"%d %#", timeValue, timeUnit];
}
#end
There are already a lot of answers that come to the same solution but it can't hurt to have choices. Here's what I came up with.
- (NSString *)stringForTimeIntervalSinceCreated:(NSDate *)dateTime
{
NSDictionary *timeScale = #{#"second":#1,
#"minute":#60,
#"hour":#3600,
#"day":#86400,
#"week":#605800,
#"month":#2629743,
#"year":#31556926};
NSString *scale;
int timeAgo = 0-(int)[dateTime timeIntervalSinceNow];
if (timeAgo < 60) {
scale = #"second";
} else if (timeAgo < 3600) {
scale = #"minute";
} else if (timeAgo < 86400) {
scale = #"hour";
} else if (timeAgo < 605800) {
scale = #"day";
} else if (timeAgo < 2629743) {
scale = #"week";
} else if (timeAgo < 31556926) {
scale = #"month";
} else {
scale = #"year";
}
timeAgo = timeAgo/[[timeScale objectForKey:scale] integerValue];
NSString *s = #"";
if (timeAgo > 1) {
s = #"s";
}
return [NSString stringWithFormat:#"%d %#%# ago", timeAgo, scale, s];
}
I took Carl Coryell-Martin's code and made a simpler NSDate category that doesn't have warnings about the string formatting of the singulars, and also tidys up the week ago singular:
#interface NSDate (Extras)
- (NSString *)differenceString;
#end
#implementation NSDate (Extras)
- (NSString *)differenceString{
NSDate* date = self;
NSDate *now = [NSDate date];
double time = [date timeIntervalSinceDate:now];
time *= -1;
if (time < 60) {
int diff = round(time);
if (diff == 1)
return #"1 second ago";
return [NSString stringWithFormat:#"%d seconds ago", diff];
} else if (time < 3600) {
int diff = round(time / 60);
if (diff == 1)
return #"1 minute ago";
return [NSString stringWithFormat:#"%d minutes ago", diff];
} else if (time < 86400) {
int diff = round(time / 60 / 60);
if (diff == 1)
return #"1 hour ago";
return [NSString stringWithFormat:#"%d hours ago", diff];
} else if (time < 604800) {
int diff = round(time / 60 / 60 / 24);
if (diff == 1)
return #"yesterday";
if (diff == 7)
return #"a week ago";
return[NSString stringWithFormat:#"%d days ago", diff];
} else {
int diff = round(time / 60 / 60 / 24 / 7);
if (diff == 1)
return #"a week ago";
return [NSString stringWithFormat:#"%d weeks ago", diff];
}
}
#end
In Swift
Usage:
let time = NSDate(timeIntervalSince1970: timestamp).timeIntervalSinceNow
let relativeTimeString = NSDate.relativeTimeInString(time)
println(relativeTimeString)
Extension:
extension NSDate {
class func relativeTimeInString(value: NSTimeInterval) -> String {
func getTimeData(value: NSTimeInterval) -> (count: Int, suffix: String) {
let count = Int(floor(value))
let suffix = count != 1 ? "s" : ""
return (count: count, suffix: suffix)
}
let value = -value
switch value {
case 0...15: return "just now"
case 0..<60:
let timeData = getTimeData(value)
return "\(timeData.count) second\(timeData.suffix) ago"
case 0..<3600:
let timeData = getTimeData(value/60)
return "\(timeData.count) minute\(timeData.suffix) ago"
case 0..<86400:
let timeData = getTimeData(value/3600)
return "\(timeData.count) hour\(timeData.suffix) ago"
case 0..<604800:
let timeData = getTimeData(value/86400)
return "\(timeData.count) day\(timeData.suffix) ago"
default:
let timeData = getTimeData(value/604800)
return "\(timeData.count) week\(timeData.suffix) ago"
}
}
}
Use the NSDate class:
timeIntervalSinceDate
returns the interval in seconds.
Quick exercise to implement this in objective-c:
Get time "now" NSDate
Get the NSDate you wish to compare with
Get the interval in seconds using timeIntervalSinceDate
Then implement this pseudo code:
if (x < 60) // x seconds ago
else if( x/60 < 60) // floor(x/60) minutes ago
else if (x/(60*60) < 24) // floor(x/(60*60) hours ago
else if (x/(24*60*60) < 7) // floor(x(24*60*60) days ago
and so on...
then you need to decide whether a month is 30,31 or 28 days. Keep it simple - pick 30.
There might be a better way, but its 2am and this is the first thing that came to mind...
My solution:
- (NSString *) dateToName:(NSDate*)dt withSec:(BOOL)sec {
NSLocale *locale = [NSLocale currentLocale];
NSTimeInterval tI = [[NSDate date] timeIntervalSinceDate:dt];
if (tI < 60) {
if (sec == NO) {
return NSLocalizedString(#"Just Now", #"");
}
return [NSString stringWithFormat:
NSLocalizedString(#"%d seconds ago", #""),(int)tI];
}
if (tI < 3600) {
return [NSString stringWithFormat:
NSLocalizedString(#"%d minutes ago", #""),(int)(tI/60)];
}
if (tI < 86400) {
return [NSString stringWithFormat:
NSLocalizedString(#"%d hours ago", #""),(int)tI/3600];
}
NSDateFormatter *relativeDateFormatter = [[NSDateFormatter alloc] init];
[relativeDateFormatter setTimeStyle:NSDateFormatterNoStyle];
[relativeDateFormatter setDateStyle:NSDateFormatterMediumStyle];
[relativeDateFormatter setDoesRelativeDateFormatting:YES];
[relativeDateFormatter setLocale:locale];
NSString * relativeFormattedString =
[relativeDateFormatter stringForObjectValue:dt];
return relativeFormattedString;
}
Not sure why this isnt in cocoa-touch, i nice standard way of doing this would be great.
Set up some types to keep the data in, it will make it easier if you ever ned to localise it a bit more. (obviously expand if you need more time periods)
typedef struct DayHours {
int Days;
double Hours;
} DayHours;
+ (DayHours) getHourBasedTimeInterval:(double) hourBased withHoursPerDay:(double) hpd
{
int NumberOfDays = (int)(fabs(hourBased) / hpd);
float hoursegment = fabs(hourBased) - (NumberOfDays * hpd);
DayHours dh;
dh.Days = NumberOfDays;
dh.Hours = hoursegment;
return dh;
}
NOTE: I"m using an hour based calculation , as that is what my data is in. NSTimeInterval is second based. I also had to convert between the two.
I saw that there were several time ago functions in snippets of code on Stack Overflow and I wanted one that really gave the clearest sense of the time (since some action occurred). To me this means "time ago" style for short time intervals (5 min ago, 2 hours ago) and specific dates for longer time periods (April 15, 2011 instead of 2 years ago). Basically I thought Facebook did a really good job at this and I wanted to just go by their example (as I'm sure they out a lot of thought into this and it is very easy and clear to understand from the consumer perspective).
After a long time of googling I was pretty surprised to see that no one had implemented this as far as I could tell. Decided that I wanted it bad enough to spend the time writing and thought that I would share.
Hope you enjoy :)
Get the code here: https://github.com/nikilster/NSDate-Time-Ago