Custom UIPickerView with locale compatibility - objective-c

I am making a custom TimePicker from a UIPickerView. I have it working great except when it comes to displaying the hours. I want it to function just like the UIDatePicker so that it follows the users Locale setting. If they have French selected, the time should display in 24 hour format. If they have US it should display in 12 hour format.
I have an array hoursArray that goes from 0 - 23. I then run this code to convert it to the needed format. However it is not wanting to change to 24 hour format if that option is set in the Settings -> International section
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[NSLocale currentLocale]];//[[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"]];
[dateFormatter setDateFormat:#"H"];
NSDate *tempDate = [dateFormatter dateFromString:[hoursArray objectAtIndex:row]];
[dateFormatter setDateFormat:#"h"];
return [dateFormatter stringFromDate:tempDate];
I tried changing [dateFormatter setDateFormat:#"h"]; to [dateFormatter setDateFormat:#"H"]; since Apples doc says the users personal locale setting will override it, but this doesn't seem to be the case.
How do I get the dateFormatter to follow the users locale setting properly?

In my case, the overriding of users preferences worked fine, and that was a bad thing for me.!!! Try setting the locale of your date formatter as
[dateFormatter setLocale:[NSLocale systemLocale]];
If that didnt work, try removing the code where you set the locale because the NSDateFormatter automatically considers the user settings.

Related

UIDatePicker.date bug

I'm having a problem getting the date from UIDatePicker. I know the code of getting the date, but it just keeps on getting the CURRENT date, not the date form the picker.
- (IBAction)buttonPressed:(UIButton *)sender {
NSDateFormatter *formate = [[NSDateFormatter alloc]init];
NSDate *settedDate = self.myPickedDate.date;
[formate setDateFormat: #"dd.MMM.yyyy # HH:mm:ss"];
NSString *dateString = [formate stringFromDate:settedDate];
NSLog(#"datestring: %#", dateString);
}
I set myPicker to 15th May 2015 15:30 and Xcode logs out the current date (if it's 16:19 he will log out 22nd.Apr.2015 16:19, no matter what.
Xcode 5.1.1 on simulator iOS 7.1.2 (haven't tried on real device).
The problem is that in your viewDidLoad you are saying this:
self.myPickedDate = [[UIDatePicker alloc] init];
So, think about that code. What you are doing there is creating a new date picker, completely different from the one in your interface, and substituting it for the one in your interface, to which self.myPickedDate was previously set (because it is an outlet). So from now on, self.myPickedDate refers to a different date picker, one that is not in your interface (it is merely held in memory)! Therefore, nothing you do in the interface, such as setting the date in the date picker you see there, has any effect on self.myPickedDate.
Therefore, to solve the problem, delete that line of code.

NSDateFormatter dateFromString returns nil for parsing EXIF data

I am trying to parse data from EXIF date to NSDate. Here is a sample date string taken from an image file:
2013:10:15 19:19:31
It is in year:month:day 24hour:minute:second format. I am using the following code to parse this:
NSDateFormatter *formatter = [[NSDateFormatter alloc] initWithDateFormat:#"yyyy:MM:dd HH:mm:ss" allowNaturalLanguage:YES];
formatter.formatterBehavior = NSDateFormatterBehavior10_4;
formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
NSDate *date = [formatter dateFromString:dt];
If I don't set the formatter behavior it complains about trying a locale identifier of 10.4 on an 10.0 formatter. (I'm on Mavericks, I think it's a new issue on Mavericks) Anyway I've tried combinations of not setting locale at all, setting locale to en_US_POSIX instead of just en_US, setting a timezone for formatter, changing yyyy to YYYY in date format, and allowNaturalLanguage to NO, however, dateFromString always returns nil. My app is running on OS X Mavericks, my system's language is English, and my region is set to Turkey if it matters. I want my app to be English-only, independent of users' region (including the date formats). I've seen this question: Parsing EXIF date string to NSDate but even I try the exact steps, formatter returns nil for dateFromString. What is wrong with the date formatter?
It seems to be a problem of the initWithDateFormat initializer.
According to the documentation, it creates a formatter that uses the "OS X v10.0 formatting behavior", but I have no idea what that is. And setting the behavior to NSDateFormatterBehavior10_4 explicitly seems also not to help.
Using
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy:MM:dd HH:mm:ss"];
NSDate *date = [formatter dateFromString:#"2013:10:15 19:19:31"];
produces the expected result.

How to use the same UIDatePicker to get Date and Time in 2 UITextField by separate

I'm working in iPad Application and I have a Picker in One XIB, I wanna use the same UIDataPicker to get by separate the date in one UITextField and The Time in a different UITextField.
Example:
UItextField_1 > Here I wanna get only the date
UItextField_2 > Here I wanna get only the time
UIDatePicker > I wanna this picker (only ONE) to get both values.
Some ideas to achieve it?
Any idea is welcome, Thank you very much!
You could set up an event listener using UIControlEventValueChanged in your viewDidLoad method.
[datePicker addTarget:self action:#selector(action:forEvent:) forControlEvents:UIControlEventValueChanged];
Then in that handler you could do something like this:
- (void)action:(id)sender forEvent:(UIEvent *)event {
// Date
dateTextField1.text = [NSDateFormatter localizedStringFromDate:[datePicker date] dateStyle:kCFDateFormatterShortStyle timeStyle:kCFDateFormatterNoStyle];
// Time
dateTextField2.text = [NSDateFormatter localizedStringFromDate:[datePicker date] dateStyle:kCFDateFormatterNoStyle timeStyle:kCFDateFormatterShortStyle];
}
[Note: this is untested code. It's only meant to give you an idea of what to do]
you just have to get the date from the UIDataPicker and use NSDateFormatter to separate the values ex
-(IBAction) endDate{
//gets date only 01/01/2011
NSDateFormatter *df = [[NSDateFormatter alloc] init];
df.dateStyle = kCFDateFormatterShortStyle;
NSLog(#"%#",[df stringFromDate:endByDatePicker.date]);
//gets time h:mm
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
[outputFormatter setDateFormat:#"h:mm"];
NSLog(#"%#",[outputFormatter stringFromDate:self.endByDatePicker.date]);
}

Format of date when retrieving lastModified

I am comparing the date when a file was last modified for two files, one local and one on Amazon S3 server. I am using the AWS IOS SDK framework and can successfully request and receive response from the S3 server but I have trouble understanding the format of the returned s3 date.
On my local machine the date format for lastModified is "2011-07-21 18:43:15 -0400" while for the file residing on the S3 server it is "2011-10-15T16:25:49.000Z".
My local info is obtained using:
NSFileManager *fm = [NSFileManager defaultManager];
NSDictionary *attr = [fm attributesOfItemAtPath:filePath error:nil];
NSDate *localDate = [attr objectForKey:NSFileModificationDate];
while my S3 info is obtained using
for (S3ObjectSummary *object in [listObjectsResult objectSummaries]) {
NSDate *s3date = [object lastModified];
}
Does anyone know if I can convert the date for the S3 file to a format that I can use to compare these two dates using:
NSTimeInterval deltaSeconds = [s3Date timeIntervalSinceDate: localDate];
or am I doing something wrong here? Right now my program crashes with
[NSCFString timeIntervalSinceReferenceDate]: unrecognized selector sent to instance 0x200351360.
probably because the s3 date format is not in proper format. I am quite new to using the AWS S3 SDK so all help is greatly appreciated. If anyone also knows of some good tutorials for this framework (apart from the demo code that comes with it), that would be great. Cheers, Trond
It looks to me as [object lastModified] simply returns a NSString and not an NSDate object, as stated in the documentation.
NSDateFormatter can be used in this case to create a NSDate object from the string:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy'-'MM'-'dd'T'HH':'mm':'ss'+'mm':'ss.SSS'Z'"];
NSDate *s3date = [dateFormatter dateFromString:[object lastModified]];
[dateFormatter release];
The Date Formatting guide has lots of handy examples. You may need to tweak the format string slightly as i have not tested it.
Had some trouble with the given answer - seems that there is some sort of duplicated 'ss'+'mm' stuff in there that prevents the string from correctly translating. Additionally, because the time zone in the string is given as UTC, you have to set the time zone for the formatter. Here is the code I used (that worked for me), I turned it into a category, and default to using the previously provided string in the event the one that works for me doesn't work for you:
#interface S3ObjectSummary (lastModifiedDate)
- (NSDate *)lastModifiedDate;
#end
#implementation S3ObjectSummary (lastModifiedDate)
- (NSDate *)lastModifiedDate
{
NSString *modifiedString = [self lastModified];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; // Note, this is ARC, add autorelease if you aren't ARC
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:#"UTC"]];
[dateFormatter setDateFormat:#"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSS'Z'"];
NSDate *modifiedDate = [dateFormatter dateFromString:modifiedString];
if(!modifiedDate) // Try other format in case of fail http://stackoverflow.com/a/7799607/285694
{
[dateFormatter setDateFormat:#"yyyy'-'MM'-'dd'T'HH':'mm':'ss'+'mm':'ss.SSS'Z'"];
modifiedDate = [dateFormatter dateFromString:modifiedString];
}
return modifiedDate;
}
#end
Looks like this also works:
NSDate *summaryDate = [NSDate dateWithISO8061Format:summary.lastModified];

Fetch from Core Data sorted by formatted date

I am having trouble fetching results from Core Data that are sorted by date.
I have a DB table that contains football matches. Each match has a homeTeam, awayTeam and kickoffTime. The kickoffTime is an NSDate that stores the date and time the match will start.
I want to display the results of a query in a TableView divided into sections by the kickoff date. With the date as the section heading.
This is a little more complex than it might first appear. Due to differing time zones a match starting on one date in one part of the world is actually starting on a different date in another part of the world. So I can't simply ignore the times and store the kickoff dates in another column.
What I'm trying to do create a custom accessor that returns a formatted date, in whatever time zone the user is in, and then use this to sort and section the results. Here's my code in Match.h:
#dynamic kickoffTime;
#dynamic formattedKickoffTime;
#dynamic dateFormatter;
- (NSString *)formattedKickoffTime
{
[self willAccessValueForKey:#"kickoffTime"];
// Set the date formatter to the format we want to display the date
[dateFormatter setDateFormat:#"ccc, d MMM"];
// Format the date
NSString *myFormattedKickoffTime = [dateFormatter stringFromDate:[self kickoffTime]];
[self didAccessValueForKey:#"kickoffTime"];
// return the formatted date
return myFormattedKickoffTime;
}
- (NSDateFormatter *)dateFormatter
{
if (dateFormatter == nil)
{
dateFormatter = [[NSDateFormatter alloc] init];
}
return dateFormatter;
}
#end
However when I try to fetch and sort the data like so:
NSSortDescriptor *kickoffDescriptor = [[NSSortDescriptor alloc] initWithKey:#"formattedKickoffTime" ascending:YES];
...
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:appDelegate.managedObjectContext sectionNameKeyPath:#"formattedKickoffTime" cacheName:nil];
I get the following error message:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath formattedKickoffTime not found in entity <NSSQLEntity Match id=1>'
Would someone offer some advice please?
So I've found a way to do this. First of all I keep all the dates and calculations in the model in GMT. I add a custom accessor (kickoffDate) to my Match entity that gets the kickoffTime, sets it's time to 00:00:00 and returns this. One thing I had to do, that wasn't obvious, was set the timeZone of the date returned by the custom accessor to GMT as otherwise this was being set to the user's system timeZone.
As all the dates returned by the model are in GMT everything just seems to work as it should no matter what timeZone I set in the iPhone's Settings. I guess Core Data is smart enough to do the timeZone adjustments before it puts the matches in the sections.
I do have one question though, is [NSTimeZone timeZoneForSecondsFromGMT:0] the best way to get a 0 timeZone, by this I mean a timeZone that isn't affected by daylight saving time?
Oh and do I have to call [self willAccessValueForKey:#"kickoffTime"]; and [self didAccessValueForKey:#"kickoffTime"];? I don't really understand what these are doing!
Here's the code in Match.h:
...
#dynamic homeTeam;
#dynamic awayTeam;
#dynamic kickoffTime;
- (NSDate *)kickoffDate
{
[self willAccessValueForKey:#"kickoffTime"];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components = [cal components:(NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit) fromDate:[self primitiveValueForKey:#"kickoffTime"]];
[components setHour:0];
[components setMinute:0];
[components setSecond:0];
[components setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[self didAccessValueForKey:#"kickoffTime"];
return [cal dateFromComponents:components];
}
And then my fetch code includes the following a sort on kickoffTime and the sectionNameKeyPath is set to kickoffDate:
NSSortDescriptor *kickoffDescriptor = [[NSSortDescriptor alloc] initWithKey:#"kickoffTime" ascending:YES];
...
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:appDelegate.managedObjectContext sectionNameKeyPath:#"kickoffDate" cacheName:nil];