I've always had some issues getting the infamously picky NSDateFormatter from causing memory instability in my code. I must not grasp how to use it properly. I've looked at tons of sample code and modeled my method after this, but it seems memory issues still plague me. The issues I'm having is that this method is creating a zombie - not too sure how / why. Some insight would be wonderful!!
-(NSString *)getTimeZoneFormatedDate:(int)subtractMinutes TimeZoneOffset:(NSString *)timeZoneOffset
{
float timeZoneOffsetInt = [timeZoneOffset floatValue];
//Calculate the requested UTC time
NSDate *UTCDateTimeNow = [NSDate date];
NSDate *UTCDateTimePast = [UTCDateTimeNow dateByAddingTimeInterval:((subtractMinutes*60)+(timeZoneOffsetInt*60*60))];
//Round the minutes down
NSDateComponents *time = [[NSCalendar currentCalendar]
components:NSHourCalendarUnit | NSMinuteCalendarUnit
fromDate:UTCDateTimePast];
int minutes = [time minute];
float minuteUnit = floorf((float) minutes / 10);
minutes = minuteUnit * 10;
//Format the minutes string
NSString *minuteString;
minuteString = [NSString stringWithFormat:#"%d",minutes];
if ([minuteString length] < 2)
minuteString = [#"0" stringByAppendingString:minuteString];
//Format the rest of the date & time
NSTimeZone *timeZone = [NSTimeZone timeZoneWithName:#"UTC"];
NSDateFormatter *dateFormatter;
dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setTimeZone:timeZone];
[dateFormatter setDateFormat:#"yyyy-MM-dd, HH:"];
NSString *yearMonthDayHourString = [dateFormatter stringFromDate:UTCDateTimePast];
//Put the two together and return it!
return [yearMonthDayHourString stringByAppendingString:minuteString];
}
I'm implementing it like so:
NSString *timeZoneText = [self getTimeZoneFormatedDate:minuteModifier*-10 TimeZoneOffset:radarTimeZoneOffset];
If I run my project with the dateformatter commented out and my method just returning:
return #"blah blah";
No issues - everything runs bug free. So, I believe it's safe to assume the issue lies within! Thanks for the help!
I think the problem is that your "NSString *yearMonthDayHourString" is autoreleased string.
You can retain it in your implementation code something like that
self.timeZoneText = blabla if timeZoneText is property with retain
or just [timeZoneText retain]; and release later;
You can try out NSDateFormatter's getObjectValue:forString:range:error: method. Maybe returned NSError provides you a reasonable explanation why it failed.
On the other hand there might be an easier way to get the result:
NSDateFormatter* dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setDateFormat:#"dd-MMM-yyyy HH:mm:ss"];
NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[dateFormatter setLocale:usLocale];
[usLocale release];
return [dateFormatter stringFromDate:date];
Related
I accessing a web service after i parsing that that code i got AiringTime of US EST 2011-10-17T14:00:00Z remaining code i written below
NSString *string = [[dateArray objectAtIndex:0] objectForKey:#"AiringTime"];
NSArray *stringArray1 = [string componentsSeparatedByString:#"T"];
NSString *string1 = [stringArray1 objectAtIndex:1];
NSArray *stringArray2 = [string1 componentsSeparatedByString:#"Z"];
NSString *dateInString = [stringArray2 objectAtIndex:0];
nowDate =[stringArray1 objectAtIndex:0];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"hh:mm:ss"];
NSDate *dateFromString = [formatter dateFromString:dateInString];
[formatter release];
above NSDate *dateFromString given me appropriate output like 14:00 from morning to evening 6:30PM. After evening 6:30PM dateFromString gave mi nil value even though dateInString has an appropriate value?? Why? and How it happen?
I mean,
NSDate *dateFromString = [formatter dateFromString:dateInString];
this line not working, dateFromString gave me nil output.
I wasting my last 3 days evening time due to this strange problem. Please help me.
Thanks in advance.
See here, the example format is exactly the one you are dealing with.
Instead of splitting and manipulating the string yourself, simply do the following:
NSString *string = [[dateArray objectAtIndex:0] objectForKey:#"AiringTime"];
//Time in according to GMT+
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSDate *dateFromString = [formatter dateFromString:string];
[formatter release];
If you are only interested in the time then NSDate is meaningless. What do you want to do with it afterwards?
I'm trying to convert a string date (2011-06-08T08:05:00.000-08:00) into a NSDate using the following code:
NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
//Translate 2011-06-08T08:05:00.000-08:00 into 2011-06-08T08:05:00.000-0800
stringDate = [stringDate stringByReplacingOccurrencesOfString:#":" withString:#"" options:0 range:NSMakeRange([aDate length] - 5, 5)];
[dateFormatter setDateFormat:#"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSZZZ"];
NSDate *dateFromString = [dateFormatter dateFromString:stringDate];
At this point, dateFromString is 2011-06-08 16:05:00 +0000. What I actually wanted was for dateFromString to be 2011-06-08 08:05:00 -0800. What am I doing wrong?
Thanks!
So this will not have a direct answer and will assume that your string format will be the same. What we are going to extract the timezone part (last 5 characters) and then calculate how many seconds we are off from GMT. NSTimeZone has a convenience method timeZoneForSecondsFromGMT: that will help us get what we need. This is what you need to add to the code in the question.
NSString * zoneString = [stringDate substringFromIndex:([stringDate length] - 5)];
NSTimeInterval timeInterval = [[zoneString substringToIndex:3] intValue] * 3600;
timeInterval += [[zoneString substringFromIndex:3] intValue] * 60;
NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:timeInterval]];
[formatter setDateFormat:#"yyyy'-'MM'-'dd' 'HH':'mm':'ss ZZZ"];
NSLog(#"%#", [formatter stringFromDate:dateFromString]);
Hopefully this helps you. If you've found a better answer already, let us know.
Original Answer
One thing about the NSDate is that the time returned is always in GMT. You can't change that. You will have to use an NSDateFormatter to print it right. Something like this,
NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
[formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"PST"]];
[formatter setTimeStyle:NSDateFormatterFullStyle];
[formatter setDateStyle:NSDateFormatterFullStyle];
NSLog(#"%#", [formatter stringFromDate:[NSDate date]]);
So setting the timezone for the formatter that does dateForString: won't help. You will need to create a new one when you want them with a different timezone.
I'm diving into iOS development and the Objective C language and am building an alarm clock app to become familiar with the SDK and language. I have an NSString object that represents a time, with the range "1:00 am" to "12:59 am". I need to convert this NSString into two NSInteger's that contain the hour value and minute value. As I'm doing this, I'm finding the NSString manipulation that I'm doing to be extremely laborious and it just feels like sloppy code.
Is there a simple way to extract the hour and minute characters from a NSString representation of a time value and store their numerical values in two NSInteger's?
Thanks in advance for all your help! I'm gonna get back to it...
NSScanner* timeScanner=[NSScanner scannerWithString:...the time string...];
int hours,minutes;
[timeScanner scanInt:&hours];
[timeScanner scanString:#":" intoString:nil]; //jump over :
[timeScanner scanInt:&minutes];
NSLog(#"hours:%d minutes:%d",hours,minutes);
Use an NSDateFormatter to convert your string into an NSDate.
Use the [NSCalendar currentCalendar] to extract various date components (like the hour, minute, etc).
In other words:
NSDateFormatter* formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"h:m a"];
NSDate *date = [formatter dateFromString:#"12:59 pm"];
[formatter release];
NSDateComponents * components = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit | NSMinuteCalendarUnit) fromDate:date];
NSLog(#"hour: %d", [components hour]);
NSLog(#"minute: %d", [components minute]);
This is the official way, as I know it. It's not pretty:
NSDateFormatter* dateFormatter = [[[NSDateFormatter alloc]init] autorelease];
[dateFormatter setDateFormat:#"h:m a"];
NSDate *date = [dateFormatter dateFromString:#"12:34 am"];
[dateFormatter setDateFormat:#"h"];
NSString *hours = [dateFormatter stringFromDate:date];
[dateFormatter setDateFormat:#"m"];
NSString *minutes = [dateFormatter stringFromDate:date];
BUT the string fiddling way of doing it (look for :, look for space, ...), may give you more headaches on the long term.
NSString *time = #"1:00 am";
NSString *removeam = [time stringByReplacingOccurencesOfString:#" am" withString:#""];
SString *removepm = [removeam stringByReplacingOccurencesOfString:#" pm" withString:#""];
NSArray *timeArray = [removepm componentsSeparatedByString:#":"];
NSInteger *hour = [[timeArray objectAtIndex:0] intValue];
NSInteger *mins = [[timeArray objectAtIndex:1] intValue];
If you're building an alarm clock app, you probably will want to look into the NSDate and NSDateFormatter classes, instead of trying to pull all those strings apart into integer types. Also, your time range is a bit weird (maybe a typo?) - don't you want all 24 hours to be available?
get the time interval and write it as
duration.text = [NSString stringWithFormat:#"%d:%02d", (int)audioPlayer.duration / 60, (int)audioPlayer.duration % 60, nil];
First one:
+ (NSDate*)convertToUTC:(NSDate*)sourceDate
{
NSTimeZone* currentTimeZone = [NSTimeZone localTimeZone];
NSTimeZone* utcTimeZone = [NSTimeZone timeZoneWithAbbreviation:#"UTC"];
NSInteger currentGMTOffset = [currentTimeZone secondsFromGMTForDate:sourceDate];
NSInteger gmtOffset = [utcTimeZone secondsFromGMTForDate:sourceDate];
NSTimeInterval gmtInterval = gmtOffset - currentGMTOffset;
return [NSDate dateWithTimeInterval:gmtInterval sinceDate:sourceDate];
}
Yes, I know this next one is strange but my server gives me a whack date format
+(NSDate *)getDateFromString:(NSString *)dtStr
{
NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init];
NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[inputFormatter setLocale:locale];
[locale release];
[inputFormatter setDateFormat:#"MMMM, dd yyyy HH:mm:ss"];
NSDate *formatterDate = [[inputFormatter dateFromString:dtStr] copy];
[inputFormatter release];
return formatterDate;
}
The first one doesn't, but the second one does, because you created a copy and didn't autorelease it. If you don't release it later, it will be leaked.
I don't see why you're even copying the date in the second method. Just cut that out and that will fix the leak.
You really should read (or re-read) the Memory Management Programming Guide for Cocoa, as it seems you need to refine your understanding of the memory-management rules.
I have this code that simple returns Today's date as a string formatted:
+(NSString*) getTodayString_YYYY_MM_DD {
NSDate * today = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd"];
return [[formatter stringFromDate:today] autorelease];
}
With instruments I'm not getting a memory leak, but when I Analyze, XCode says:
Object sent -autorelease too many times
If I understand correctly, I have to release manually the formatter as I'm creating it using 'alloc', but I can't release here because I have to return the value, so I add the autorelease.
How I can do it better to improve it ?
thanks,
r.
You are -autoReleasing the NSString, not the formatter.
You don't need an autoRelease since -stringFromDate: is giving you an already autoReleased string.
Here is one way your code can look like:
+(NSString*) getTodayString_YYYY_MM_DD {
NSDate * today = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd"];
NSString *retString = [formatter stringFromDate:today];
[formatter release];
return retString;
}
Given that an NSDate's description is always in the format YYYY-MM-DD HH:MM:SS ±HHMM:
+ (NSString *) getTodayString_YYYY_MM_DD
{
return [[[NSDate date] description] substringToIndex:10];
}
Just throwing it out there. It's probably less efficient than the NSDateFormatter method.