how to store time in NSDate without date? - iphone

I have a timer in my app. When I click on exit buton then timer gets stop and stores value into the string in format of 01:15:55 . I have an array to store this string object.
What I want is , now I want to display these values by comparing to each other. So I think first I have to convert the string into the NSDate but I am having only time format and do not want to store date.
How can I accomplish this task ? any suggestion ?
EDITED : code
NSInteger secondsSinceStart = (NSInteger)[[NSDate date] timeIntervalSinceDate:sDate]; // sDate = when app get started
myAppDelegate.seconds = secondsSinceStart % 60;
myAppDelegate.minutes = (secondsSinceStart / 60) % 60;
myAppDelegate.hours = secondsSinceStart / (60 * 60);
NSString *result = nil;
if (myAppDelegate.hours > 0)
{
result = [NSString stringWithFormat:#"%02d:%02d:%02d", myAppDelegate.hours, myAppDelegate.minutes, myAppDelegate.seconds];
}
else
{
result = [NSString stringWithFormat:#"%02d:%02d", myAppDelegate.minutes, myAppDelegate.seconds];
}
NSString *tempDateString = [NSString stringWithFormat:#"%d:%d:%d",[myAppDelegate hours],[myAppDelegate minutes],[mogsApp seconds]];
Now I want to convert tempDateString into the NSDate so I can compare with similar objects. Is it possible ?
Thanks...

Sounds like an NSTimeInterval might be more appropriate. This is just a floating-point value indicating a number of seconds (including fractional seconds). You can manually format a value like this into whatever string format you want with some simple division and remainder math. (NSDate will give you time intervals since a reference date or other dates if you want to use those to get the values.) You can store NSTimeIntervals as strings if necessary.

NSDateComponents is always a good choice when storing only parts of a date/time (or a timespan).
It also gives you easy access to time management methods via NSCalendar. Then (unlike using NSTimeInterval), you don't have to set up any of the math yourself, and it will all automagically localize.

Related

How can validate NSDATE

How to find one text field value is within past 60 day excluding current date.
For example if I enter value in text field is 20-July-2012 using Date Picker.Then I click submit,it'll check that specific is date is within 60 days or not. If the values are entered which is before 60 days an alert message is displayed. The values are retrieved from api.
NSDate *today = [NSDate date];
NSTimeInterval dateTime;
if ([pickerDate isEqualToDate:today]) //pickerDate is a NSDate
{
NSLog (#"Dates are equal");
}
dateTime = ([pickerDate timeIntervalSinceDate:today] / 86400);
if(dateTime < 0) //Check if visit date is a past date, dateTime returns - val
{
NSLog (#"Past Date");
}
else
{
NSLog (#"Future Date");
}
Change the value of 86400 to suit your query.In this case, it is the number of seconds we want to compare.
First, convert the text into an NSDate. Then use
timeIntervalSinceDate:[NSDate dateWithTimeIntervalSinceNow:0]
There are a couple of ways to convert text into an NSDate. You can format the text correctly and then use dateWithString or you can convert everything into numbers, multiply them out, and one of the dateWithTimeInterval methods.
If you want the user to be able to enter "July" (plain text month) then you might want to write a method that converts months into their numerical equivalents with string matching.
NSDate *lastDate; //your date I hope you have created it
NSDate *todaysDate = [NSDate date];
NSTimeInterval lastDiff = [lastDate timeIntervalSinceNow];
NSTimeInterval todaysDiff = [todaysDate timeIntervalSinceNow];
NSTimeInterval dateDiff = lastDiff - todaysDiff; // number of seconds
int days = dateDiff/(60*60*24); // 5.8 would become 5 as I'm taking int
How do you define 60 days?
You may want to use NSCalendar -dateByAddingComponents:toDate:options: to ensure your 60 days really are 60 days.
NSCalendar also provides -components:fromDate: and -dateFromComponents: which are very nice when dealing with date components.
If 60 days do not need to be true calendar days (daylight saving time switches, astronomical time corrections, stuff like that), you can just have fun with NSDate and the time interval methods alone.

finding NSDate's in an NSArray that have a time of day after a given time (e.g. 8pm)?

Is there a quick way in Objective-C of identifying NSDate's in an NSArray that have a time of day after a given time (e.g. 8pm)?
I can't quite see anyway other than manually walking through each NSDate in the array and then using NSDateComponents to break out the hour/minute/second...Not even sure if there is a simple way to get the time from an NSDate in a fashion that represents a fraction of 24hours, as this might help a little. (e.g. 6pm would be 18/24 = 0.75 in this case)
There is no need to break in NSDateComponents.
NSTimeInterval interval = [date1 timeIntervalSinceDate:date2];
if (interval > 0) {
// date2 is earlier
} else {
// date1 is earlier
}
Now you can represent your target time(8 P.M., for example) with date2 and compare all dates of array with that.
Haven't tried this myself, but I guess
- (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate
is what you're looking for.

Need advice about time comparison using NSDate

I am developing Alarm Clock.
I want to compare a time now and setTime. Is it possible to compare in minutes only.
My Problem is NSDate will compare in seconds, for example 9:38:50 is not equal to 9:38:00.
how can I compare in minutes?
First, convert them to UNIX timestamp ignoring milliseconds.
NSUInteger time1 = (NSUInteger)[date1 timeIntervalSince1970];
NSUInteger time2 = (NSUInteger)[date2 timeIntervalSince1970];
Ignore seconds.
time1 = time1 - (time1 % 60);
time2 = time2 - (time2 % 60);
Now, you can safely compare them.
if (time1 == time2) {
NSLog(#"Bingo");
}
Use NSCalendar to get the NSDateComponents you're interested in. Then it's easy to compare those.
Though it might be sufficient to check whether the current date is later than the alarm date. If it is and the alarm wasn't stopped, you should probably go off even if the computer momentarily lost power or something.

Objective C Convert int to NSString (iPhone)

I have the following code that is meant to convert milliseconds into hours, mins and seconds:
int hours = floor(rawtime / 3600000);
int mins = floor((rawtime % 3600000) / (1000 * 60));
int secs = floor(((rawtime % 3600000) % (1000 * 60)) / 1000);
NSLog(#"%d:%d:%d", hours, mins, secs);
NSString *hoursStr = [NSString stringWithFormat:#"%d", hours];
NSString *minsStr = [NSString stringWithFormat:#"%d", mins];
NSString *secsStr = [NSString stringWithFormat:#"%d", secs];
NSLog(#"%a:%a:%a", hoursStr, minsStr, secsStr);
Fairly straightforward. Rawtime is an int with value 1200. The output is like this:
0:0:1
0x1.3eaf003d9573p-962:0x1.7bd2003d3ebp-981:-0x1.26197p-698
Why is it that converting the ints to strings gives such wild numbers? I've tried using %i and %u and they made no difference. What is happening?
You have to use %# as the conversion specifier for an NSString. Change your last line to:
NSLog(#"%#:%#:%#", hoursStr, minsStr, secsStr);
%a means something totally different. From the printf() man page:
aA
The double argument is rounded and converted to hexadecimal notation in the style
[-]0xh.hhhp[+-]d
where the number of digits after the hexadecimal-point character is equal to the precision specification.
Instead of rolling your own string formatting code, you should be using an NSNumberFormatter for numbers or an NSDateFormatter for dates/times. These data formatters take care of localization of format to the user's locale and handle a variety of formats built-in.
For your use, you need to convert your millisecond time into an NSTimeInterval (typedef'd from a double):
NSTimeInterval time = rawtime/1e3;
Now you can use an NSDateFormatter to present the time:
NSDate *timeDate = [NSDate dateWithTimeIntervalSinceReferenceDate:time];
NSString *formattedTime = [NSDateFormatter localizedStringFromDate:timeDate
dateStyle:NSDateFormatterNoStyle
timeStyle:NSDateFormatterMediumStyle];
NSString *rawTime = [[formattedTime componentsSeparatedByString:#" "] objectAtIndex:0];
on OS X where the last line removes the "AM/PM". This will work for any time less than 12 hrs and will give a formatted string in the localized format for HH:MM:SS. On the iPhone, localizedStringFromDate:dateStyle:timeStyle: isn't available (yet). You can achieve the same effect with setTimeStyle:, setDateStyle: and stringFromDate: on a date formatter instance.

Memory Leaks - Formatting a String To Display Time, Each Second

Hey guys. I have a method that gets called each second which I want to use to display the time that my app has been doing it's work. Currently the class I'm using (Which I did not create) has a property named progress which stores the total number of seconds.
I have already written some code which takes these seconds and formats it into a readable string. I'm new to this, so pardon me if it's not the best code. I welcome any suggestions:
// hours, minutes, and seconds are instance variables defined as integers
int totalSeconds = (int)streamer.progress;
hours = totalSeconds / (60 * 60);
if (hours > 0)
formattedTimeString = [NSString stringWithFormat:#"%d:", hours]; // WRONG
minutes = (totalSeconds / 60) % 60;
seconds = totalSeconds % 60;
[formattedTimeString stringByAppendingFormat:#"%d:%d", minutes, seconds]; // WRONG
Basically I want it to appear as "3:35" for example to show 3 minutes, 35 seconds. I only want to show the hour section if it has been an hour, in which case it would be "2:3:35" for example (Can anyone recommend a better way to format this?).
The problem I am having is where I actually create/set the string (The lines tagged WRONG). Since this is being done every second, I would easily get a leak if I keep asking for a new string object. I figure I can solve this by releasing the foramttedTimeString at the end of the method, but is this the correct way to accomplish this? Would an NSMutableString help in any way? Is there a better, Cocoa way of doing this? I already asked in #iphonedev # freenode and they said I would have to write this method myself, but I figured I'd ask again.
To provide context: this is an internet radio streaming app (I know there are many already, but I'm just practicing). I want to be able to show the amount of time the stream has been playing for.
Sorry if this question is stupid, heh, like I said I'm new to this.
I would do it something like:
int totalSeconds = (int)streamer.progress;
hours = totalSeconds / (60 * 60);
minutes = (totalSeconds / 60) % 60;
seconds = totalSeconds % 60;
if ( hours > 0 ) {
formattedTimeString = [NSString stringWithFormat:#"%d:%02d:%02d", hours, minutes, seconds];
} else {
formattedTimeString = [NSString stringWithFormat:#"%d:%02d", minutes, seconds];
}
Now at the end, formattedTimeString is the desired time, but you do not "own" it - you must retain it, or store it in a "copy" property if you wish to keep it around.
Note that the %02d gives you a guarenteed two digits, zero filled number, which is usually what you want for numbers in parts of times.
To see how you would do it with stringByAppendingFormat, it would look something like this:
NSString* formattedTimeString = #"";
if ( hours > 0 ) {
formattedTimeString = [formattedTimeString stringByAppendingFormat:#"%d:", hours];
}
formattedTimeString = [formattedTimeString stringByAppendingFormat:#"%d:%02d", minutes, seconds];
However in this case, you'll get times like 3:4:05, rether than a more desirable 3:04:05.
Note that formattedTimeString is being overwritten each time, but that is OK bvecause you do not "own" it at any time, so you are not responsible for releasing it.
Finally, to see it with a mutable string, it might look like this:
NSMutableString* formattedTimeString = [NSMutableString string];
if ( hours > 0 ) {
[formattedTimeString appendFormat:#"%d:", hours];
}
[formattedTimeString appendFormat:#"%d:%02d", minutes, seconds];
Again, the time result is the undesirable 3:4:05, and again you do not own formattedTimeString at the end, so it must be retained or stored with a copy property to keep it around.
For knowing the deltas as time units, you can also do something like this:
// as part of init...
self.gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
// in the timer or wherever you are tracking time deltas...
static NSUInteger unitFlags =
NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents *components = [gregorian components:unitFlags
fromDate:myBaseTime
toDate:[NSDate date] options:0];
Then you can reference the parts with something like this [components minute].
Remember, you'll have to release the calendar in dealloc.
Your code looks pretty good. You're not leaking any memory because the string objects you create have a retain count of zero and will be cleaned up by the system. However, if formattedTimeString is not a local variable in your function, you need to retain it at the end to prevent this from happening! To do that, you would add [formattedTimeString retain] to the end of your code block, and then before replacing the string object you would add [formattedTimeString release].
As a general rule, functions with names containing "alloc", "copy", "create", and "new" return objects that have already been retained, (meaning their retain count is +1). It's your responsibility to call release or autorelease on these objects when you're done using them - or they will just start piling up in memory.
Functions like "stringWithFormat:", "imageNamed:", and "arrayWithCapacity:" all return objects with a retain count of zero - so you can safely discard them (as you are in the code sample). If you want to keep them around, you should call retain to make sure they are not cleaned up while you're using them.
All that said, I think the main problem is your use of stringByAppendingFormat:. Since the NSString you're using isn't mutable, that call returns a new string. You'd want to say:
formattedTimeString = [formattedTimeString stringByAppendingFormat:#"%d:%d", minutes, seconds];
Alternatively, you could use an NSMutableString. Since this is something you'll be doing over and over again, I'd recommend doing that. Technically, either way is fine though.
Hope that helps! The whole retain/release thing can get confusing. Just remember that each object has a "retainCount" and once it hits zero there's no telling what happens to the object or it's data.
Hey thanks guys I appreciate the responses.
I ended up doing this, and it works, but I would like to know if you guys see any problems with it:
int totalSeconds = (int)streamer.progress;
[formattedTimeString setString:#""];
hours = totalSeconds / (60 * 60);
if (hours > 0)
[formattedTimeString appendFormat:#"%d:", hours];
minutes = (totalSeconds / 60) % 60;
seconds = totalSeconds % 60;
[formattedTimeString appendFormat:#"%02d:%02d", minutes, seconds];
And then of course in viewDidLoad I instantiate the instance variable formattedTimeString:
formattedTimeString = [[NSMutableString alloc] initWithCapacity:8];
I did not do any retaining/releasing in the first code snippet because I didn't think it was necessary, but I could be wrong. I am, however, releasing in the dealloc method, so I should be fine there.