iOS: Display time in 24-hour format if locale appropriate? - ios

My iOS app is going to display the current time. How do I determine whether the user's locale prefers 12-hour or 24-hour time formatting?

See the NSDateFormatter class http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSDateFormatter_Class/Reference/Reference.html
Something like:
NSDate *date = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterNoStyle];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setLocale:[NSLocale currentLocale]];
NSString *dateString = [dateFormatter stringFromDate:date];

You generally don't need to figure out what the user's locale settings are when displaying data to the user. If you use the relevant NSFormatter (NSNumberFormatter for numbers and NSDateFormatter for date and time, which is the relevant one for you in this case), then you will automatically get the output that is appropriate to the user's locale... i.e what Apple calls the "localized representation of the object"

Related

Converting calendar date to the correct date

I am working on an application that creates alerts with calendar. I can correctly set alarms on correct dates. For example, I set an alarm for 4th of May 2017 1 PM.
When, I try to get the calendar event it returns me some other date in UTC.
As you can see, it returns me 10 AM on same day with UTC. I am wondering how can I get the exact date when I try to get it from calendar.
You just need to convert UTC to your local timezone.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"]];
NSDate *date1 = [dateFormatter dateFromString:#"2017-05-04 10:00:00"];
// change to a readable time format and change to local time zone
[dateFormatter setDateFormat:#"MM/dd/yyyy hh:mm a"];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
NSString *strCurrentLocalTimezoneDate = [dateFormatter stringFromDate:date1];
Date always takes current time zone until we changed other.If we print the Date it might be showing different but actually it takes current.
// except this code you may have to set timeZone as well.
NSDateFormatter *format = [[NSDateFormatter alloc] init];
[format setDateFormat:#"MMM-dd-yyyy"];
NSDate *now = [[NSDate alloc] init];
NSString *dateString = [format stringFromDate:now];
NSLog(#"%#",dateString);

SQLite storing, retrieving and comparing a DATETIME field

I am really stuck trying to compare dates in SQLite queries in Objective C. Here's what I'm doing:
Storing the date:
This document tells me to use the dateformat specified below, but it doesn't seem right. I tried using yyyy-MM-dd hh:mm:ss without success too though.
NSDate *today = [NSDate date];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"YYYY-MM-DD HH:MM:SS"];
NSString *dateString=[dateFormat stringFromDate:today];
NSString *query = [NSString stringWithFormat: #"INSERT INTO user (edited) VALUES (\"%#\")", dateString];
Comparing the date
I am using a timestamp for this, which I convert to a datetime string
long stamp = [sessie integerForKey:#"stamp"];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"YYYY-MM-DD HH:MM:SS"];
NSString *dateString = [formatter stringFromDate:[NSDate dateWithTimeIntervalSince1970:stamp]];
sqlite3_stmt *result = [db selectQuery:[NSString stringWithFormat:#"SELECT * FROM user WHERE edited > '%#'", dateString]];
The timestamp is simply generated using [[NSDate date] timeIntervalSince1970]. The problem is that the query won't give the correct results, and I don't even know if the date is stored correctly in the first place. Any help would be greatly appreciated!
A couple of observations:
For your date string, you do definitely do not want to use YYYY-MM-DD HH:MM:SS. That will not generate a valid date string. Using yyyy-MM-dd hh:mm:ss is much closer, but not quite right, either (since you'll use 12-hour hh). Use yyyy-MM-dd HH:mm:ss instead.
This date format, though, does not capture time zone, so, if you store date strings in your SQLite database, you should use UTC (GMT) as discussed in the SQLite Date And Time Functions documentation.
NSDateFormatter * formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
formatter.timeZone = [NSTimeZone timeZoneWithName:#"UTC"];
formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
NSString *dateString = [formatter stringFromDate:today];
As shown above, you probably want to also specify the locale so that the format of the dates will not change depending upon the localization settings of the device.
Note that you might consider using timeIntervalSince1970 to store the date as a REAL value in your database (as opposed to a TEXT). This can be a little more efficient and automatically addresses the UTC issue.

Get the precise date and time value

How can we get the date / time with the following format:
YYYY-MM-DD HH:MM:ss.mmm
In fact, I have to create a trace class to trace the communication flow between iOS device and another device. I need this format to have a good time stamp.
It should be:
NSString *MyString;
NSDate *now = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd' 'HH:mm:ss.SSS"];
MyString = [dateFormatter stringFromDate:now];

Ensure AM / PM (Period) does not appear in NSDateFormat stringFromDate

The Unicode Date Format Patterns guide (here) state that appending an 'a' to the format will get the period (AM or PM for instance), e.g.,
[formatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss a"];
However I wish to ensure that the period information does not appear but I cannot find a format string to do that. The format string I am using is as follows:
[formatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss"];
unfortunately, when I use stringFromDate I get the following:
2013-01-09T11:11:00 AM
I dont wish to simply strip AM or PM from the resultant string because the period syntax may be different in differing Calendars etc, I just want to stop the period information appearing.
----8<------
Consider the following code
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setLocale:[NSLocale currentLocale]];
[formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"]];
[formatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss"];
NSString *stringDate = [formatter stringFromDate:[NSDate date]];
self.labelOutput.text = stringDate;
[formatter release];
This code will produce a string in the format I want - however I cannot use it for memory management reasons. The app I am working on is plagued by NSDateFormatter memory leaks. So we use a singleton class to provide a set number NSDateFormatters to the app which are never released and therefore we minimise how much memory is being leaked. Unfortunately these static NSDateFormatters are appending AM / PM even when I apply a date format string thus:
NSDateFormatter *formatter = [MyDateFormatter dateFormat:kFormatDateMediumStyleTimeShortStyle];
[formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"]];
[formatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss"];
According to date formatter different output on different devices running same iOS version, set the local of your NSDateFormatter to en_US_POSIX will fix this.
Additional to set Local you may wish avoid problems with time zone setting it like:
[formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"]];
It actually depends on user's settings.
Please see Fixed Formats part of Data Formatting Guide. Note this sentence:
In iOS, the user can override the default AM/PM versus 24-hour time
setting. This may cause NSDateFormatter to rewrite the format string
you set.
And at the end of the paragraph:
The representation of the time may be 13:00. In iOS, however, if the
user has switched 24-Hour Time to Off, the time may be 1:00 pm.
You need to use POSIX here a sample code
NSDateFormatter *rfc3339DateFormatter = [[NSDateFormatter alloc] init];
NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
[rfc3339DateFormatter setLocale:enUSPOSIXLocale];
[rfc3339DateFormatter setDateFormat:#"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];
[rfc3339DateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
// Convert the RFC 3339 date time string to an NSDate.
NSDate *date = [rfc3339DateFormatter dateFromString:rfc3339DateTimeString];
One option is to create your own NSFormatter. I did that on my code when I couldn't get the formatter in Xcode's Interface Builder to do what I wanted. Granted, I was only looking for hours, minutes, and seconds and not the full date.
As for the memory leaks: if you can, use ARC. If you can't, use Xcode's Static Analyzer to try and track down improper retain counts.
Here is the answer I have settled on. It's a bit simplistic but it does the job.
#interface NSDateFormatter (Utils)
- (NSString *)stringWithNoPeriodInformationFromDate:(NSDate*)date;
#end
#implementation NSDateFormatter (Utils)
- (NSString *)stringWithNoPeriodInformationFromDate:(NSDate*)date
{
NSString *stringWithPotentialPeriodInformation = [self stringFromDate:date];
NSString *stringWithNoAMInformation = [stringWithPotentialPeriodInformation stringByReplacingOccurrencesOfString:[self AMSymbol] withString:#""];
NSString *stringWithNoPeriodInformation = [stringWithNoAMInformation stringByReplacingOccurrencesOfString:[self PMSymbol] withString:#""];
return stringWithNoPeriodInformation;
}
#end

Date with local timestamp

I would like to keep track of the date with timestamp. What objective-C/cocoa class could I use to get the timestamp local to the machine's time settings?
if for example I'm in USA, timestamp should be in terms of the area where I'm at. If I'm in Europe, should be in Europe time.
Take a look at NSDate. For example,
NSDate *today = [NSDate date];
will give you the current date and time.
You can use this.
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
NSString *currentTime = [dateFormatter stringFromDate:[NSDate date]]
NSLog(#"Current Date:%#",currentTime);
I hope this is use full to you.

Resources