Convert 24h to 12h time format in Obj-C - objective-c

I currently display time in 24h format, because it's the easiest thing for me to do right now with the data I have.
I get the time in "minutes since midnight", so for example, 07:00 or 7:00 a.m is "420" and 21:30 or 9:30 p.m is "1290" and so on.
[NSString stringWithFormat:#"%02d:%02d - %02d:%02d", (open / 60), (open % 60), (close / 60), (close % 60)]
Is there a nice way to use NSDateFormatter to convert from 24h to 12h? I have tried a bunch of things, but I never end up with 100% correct formatting.
I have also tried with lots of if statements, only to end up with way too many lines of code, which should be completely unnecessary in my opinion for such a relatively "easy" job.
Also, no matter I try I also end up with wrong 12h formatting for hours without "1" in the beginning, for example "09:30 a.m.", etc. I can strip this by looking for the suffix, but again this just seems to tedious and weird.

You should really use the system's default date formatting:
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setHour:hours];
[comps setMinute:minutes];
NSDate* date = [[NSCalendar currentCalendar] dateFromComponents:comps];
NSString* dateString = [NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterNoStyle timeStyle:NSDateFormatterLongStyle];
Or if you insist you can do
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"hh:mm a"];
NSString* dateString = [dateFormatter stringFromDate:date];

For someone new like me I struggled with the date formatter and found that the [NSCalendar currentCalendar] will use the users preferences to set timezone. In my situation I wanted to convert a time that a server gave me so it was always wrong. I used this simple function in my case.
- (NSString *)formatTime:(NSString *)time
{
NSString *hour = [time substringWithRange:NSMakeRange(0, 2)];
NSString *minute = [time substringWithRange:NSMakeRange(2, 2)];
NSString *tail = ([hour integerValue] > 11) ? #"PM" : #"AM";
return [NSString stringWithFormat:#"%#:%# %#", hour, minute, tail];
}

You can try this.It works for me
NSDateFormatter* df = [[NSDateFormatter alloc] init];
[df setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en_US"]];
[df setTimeZone:[NSTimeZone systemTimeZone]];
[df setDateFormat:#"yyyy-mm-dd hh:mm:ss"];
NSDate* newDate = [df dateFromString:[df stringFromDate:[NSDate date]]];
[df setDateFormat:#"hh:mm a"];
newDate = [df stringFromDate:[NSDate date]];

check if your minutes are less than 720 (12 hours), if so its AM, if not its PM (so you would do hours -12 to get from military to 12h) then add the suffix as needed. Its not pretty, but its a relatively simple formatting job.

Related

Convert the exact NSString value to NSDate [duplicate]

This question already has an answer here:
returns a date an hour in the future
(1 answer)
Closed 7 years ago.
This is my code.
NSString *dateString = #"2015-06-03 02:19:37";
NSDateFormatter *formatter = [NSDateFormatter new];
[formatter setDateFormat:#"yyyy-MM-dd hh:mm:ss"];
NSLog(#"converted date = %#",[formatter dateFromString:dateString]);
The output of the code above is: "converted date = 2015-06-02 18:19:37 +0000". I know that this is because it converts the NSString with respect to GMT, but what i wanted to happen is NSDate must be 2015-06-03 02:19:37, same with dateString
I know that this is because [the NSDateFormatter] converts the NSString with respect to GMT…
No, you're wrong. NSDateFormatter defaults to using your current time zone.
What you're not understanding is that "2015-06-02 18:19:37 +0000" is the same date and time as "2015-06-03 02:19:37" (in your local time zone, which must be GMT+0800).
Also, the description that you logged is just one representation of the date. The date does not have a year, month, day-of-month, hour, minute, second, or any of that. A date object just represents a moment in time. Such moments don't have any of that and neither do NSDate objects. Only representations of moments have those things, and they are only arrived at by processing the date through a specific calendar and time zone. In any case, any given date has multiple representations. Just because the description that gets logged happens to choose a representation that you weren't expecting doesn't mean the date is wrong.
You have implicitly requested a conversion from an NSDate object to a string when you logged it. That's because logging always involves strings. The string-formatting code used by NSLog() and the %# format specifier uses the -description method. You are never going to be able to force NSDate's implementation of -description to use your time zone, so don't try.
If you really need a string representation (and you're not just debugging) and you want it in some specific time zone or otherwise want to dictate the format, don't rely on the -description method like you are. Instead, use a date formatter to convert from NSDate to an NSString explicitly, and configure the date formatter to produce the representation that you want.
But don't confuse the need to do that with the date being wrong.
What I really wanted to do is to check if the given NSDate is already past 9PM EST (-4GMT), while i'm on +8GMT timezone.
So, use NSCalendar, NSTimeZone, and NSDateComponents to construct an NSDate for 9PM EST (on the current day, I suppose you mean) and then compare the dates.
NSDate* date = /* ... */;
NSCalendar* calendar = [[NSCalendar alloc] initWithIdentifier:NSCalendarIdentifierGregorian];
calendar.timeZone = [NSTimeZone timeZoneWithName:#"America/New_York"];
NSDate* deadline = [calendar dateBySettingHour:21 minute:0 second:0 ofDate:date options:0];
if ([date compare:deadline] == NSOrderedDescending)
/* date is after deadline */;
Here I used the convenience method -dateBySettingHour:minute:second:ofDate:options: and avoided direct use of NSDateComponents. If your needs differ, you might have to convert the date to date components using the calender, modify the components, convert them back to a date, and then compare.
Use the NSDateComponents class to build the date from the information in the string. The documentation explicitly provides an example of this:
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:6];
[comps setMonth:5];
[comps setYear:2004];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:comps];
[comps release];
NSDateComponents *weekdayComponents =
[gregorian components:NSWeekdayCalendarUnit fromDate:date];
int weekday = [weekdayComponents weekday];
call this method with your string value...
- (NSDate *)dateFromString:(NSString *)date
{
static NSDateFormatter *dateFormatter;
if (!dateFormatter)
{
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"]];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
[dateFormatter setDateFormat:#"dd-MM-yyyy"];
}
NSLog(#"Date: %#",date);
return [dateFormatter dateFromString:date];
}
RESULT : Date: 2015-06-03 02:19:37
NSString *dateString = #"2015-06-03 02:19:37";
NSDateFormatter *f = [[NSDateFormatter alloc] init];
[f setDateFormat:#"yyyy-MM-dd"];
NSDate *startDate = [f dateFromString:dateString];
You will get the NSDate here(startDate).... May this help to you.....

Objective-C – NSDateFormatter dateFromString ignore time

If I'm not interested in the time can I ignore it? I.e I have a date string that looks like this #"2012-12-19T14:00:00" but I'm only interested in getting the date (2012-12-19) but if I set NSDateFormatter like [dateFormatter setDateFormat:#"yyyy-MM-dd"]; it will return me a nil NSDate.
An NSDate object will always contain a time component as well, as it is representing a point in time — from this perspective one could argue the name NSDate is misleading.
You should create a date formatter for creating dates from string, set the time to the start of the day and use a second date formatter to output the date without time component.
NSString *dateString = #"2012-12-19T14:00:00";
NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init];
[inputFormatter setDateFormat:#"yyyy-MM-dd'T'HH:mm:ss"];
NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
[outputFormatter setDateStyle:NSDateFormatterShortStyle];
[outputFormatter setTimeStyle:NSDateFormatterNoStyle];
NSDate *date = [inputFormatter dateFromString:dateString];
//this will set date's time components to 00:00
[[NSCalendar currentCalendar] rangeOfUnit:NSDayCalendarUnit
startDate:&date
interval:NULL
forDate:date];
NSString *outputString = [outputFormatter stringFromDate:date];
NSLog(#"%#", outputString);
results in
19.12.12
while the format — as it is chosen by styling — will be dependent of your environment locale
all date string returns 10 characters for the date, what i mean is the date of todayy will be 2012-11-19
you can easily substring the date and use it as you want:
Example :
NSString* newDate = #"";
newDate = [[NSDate date]substringToIndex:10];
the out put will be : 2012-11-19

NSDate won't load/display correctly

I'm not sure what's going on with this. I'm trying to load an NSString* object from a file, convert it to an NSDate* with a date formatter, and then convert the hour and minute components back to NSString so I can display a time in Interface Builder. However, instead of the time that was saved to the file, instead I end up with 19 for the hour, and 0 for the minute. (Regardless of what was put in, the program loads four different NSDates)
Here's the code for loading the date from the file (I checked with breakpoints, and the array does indeed have the correct data, so that's not the problem)
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"yyyy-MM-dd hh:mm:ss a"];
date1 = [[df dateFromString:[loadArray objectAtIndex:3]] retain];
Here's the code for displaying the date.
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *comp = [[gregorian components:NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:myDrug.date1] retain];
hourField1.text = [NSString stringWithFormat:#"%d", comp.hour];
minuteField1.text = [NSString stringWithFormat:#"%d", comp.minute];
(hourField1 and minuteField1 are the IBOutlets that receive the values, by the way)
I'm not sure where I've gone wrong here, and any help would be greatly appreciated. Thanks!
Update:
On the suggestion of some of the people here, I've NSLogged the problem, and I've found that it the date formatter that's not working. An example date is 2011-02-14 06:00:00 GMT, and the date formatter is yyyy-MM-dd hh:mm:ss a, so I'm not sure why it won't work.
If the date strings in loadArray are of the form 2011-02-14 06:00:00 GMT, then the format should be set as follows:
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"yyyy-MM-dd HH:mm:ss zzz"]; <--
date1 = [[df dateFromString:[loadArray objectAtIndex:3]] retain];
// the retain above is suspicious btw (but that's another question)
[df release]; //don't forget this
I also changed the hh to HH assuming that the hours are actually in 24-hour instead of 12-hour format. See Unicode Date Format Patterns for details.
Next, when displaying the date, if you want to show the hours and minutes in GMT instead of whatever the user's current time zone is, you'll need to set the calendar's time zone:
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSTimeZone *tz = [NSTimeZone timeZoneWithName:#"GMT"]; <--
[gregorian setTimeZone:tz]; <--
NSDateComponents *comp = [gregorian components:NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:myDrug.date1];
//do not do a retain on comp above
hourField1.text = [NSString stringWithFormat:#"%d", comp.hour];
minuteField1.text = [NSString stringWithFormat:#"%d", comp.minute];
[gregorian release]; //don't forget this

Why does time returned by [NSDate date] differ from my current time?

hi all
I am in India.And I have used the following code to get the current date.
[NSDate date]
it displaying the "2011-01-20 06:51:35 +0000" but actual time is "2011-01-20 12:21:35 +0000"
.Please tell me how to get the current date.
Thanks in advance
You need to use Date Formatter for this purpose.Below is the sample code for that.
NSDate *testDate=[NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"MM DD YY hh:mm"];//You can set your required format here
NSString *dt = [formatter stringFromDate:testDate];
[formatter release];
NSString *strDateTaken=dt;
Cheers
What does “actual time” mean? The current time in your time zone? Considering the time values given I’d guess that the first one is GMT and you want IST (+5:30). (See Time zones on Wikipeda.) Depends on what you want to do with the date – if you just want a formatted date and time in your current time zone, Aditya’s answer should work.
To Find Current date and difference between current date and Given date...its working code
NSDate *testDate=[NSDate date];
NSDateFormatter *formatterNew = [[NSDateFormatter alloc] init];
[formatterNew setDateFormat:#"dd-MM-yyyy HH:mm:ss "];
NSString *dt = [formatterNew stringFromDate:testDate];
NSString *strDateTaken=dt;
NSLog(#"Date=%#",strDateTaken);
[formatterNew release]; // This line can be removed if you are using ARC
NSDateFormatter *tempFormatter = [[[NSDateFormatter alloc]init]autorelease];
[tempFormatter setDateFormat:#"dd-MM-yyyy HH:mm:ss"];
NSDate *toDate = [tempFormatter dateFromString:strDateTaken];
NSLog(#"Current Date ==%#",toDate);
NSDateFormatter *tempFormatter1 = [[[NSDateFormatter alloc]init]autorelease];
[tempFormatter1 setDateFormat:#"dd-MM-yyyy HH:mm:ss"];
NSDate *startdate = [tempFormatter1 dateFromString:#"30-08-2011 16:25:00"];
NSLog(#"Last Date ==%#",startdate);
int i = [startdate timeIntervalSince1970];
int j = [toDate timeIntervalSince1970];
double X = j-i;
int days=(int)((double)X/(3600.0*24.00));
NSLog(#" Difference :%d",days);

Formatting seconds into hh:ii:ss

I have app that is a basic timer. It tracks the number of seconds the app has run. I want to convert it so the seconds (NSUInteger) are displayed like: 00:00:12 (hh:mm:ss). So I've read this post:
NSNumber of seconds to Hours, minutes, seconds
From which I wrote this code:
NSDate *date = [NSDate dateWithTimeIntervalSince1970:[[self meeting] elapsedSeconds]];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"hh:mm:ss"];
It works fine, but it starts out with 04:00:00. I'm not sure why. I also tried doing something like:
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:[[self meeting] elapsedSeconds] * -1];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"hh:mm:ss"];
Thinking that it would display the counter correctly, but it does a wierd 01:23:00, then just flops to 04:00:00 and stays there for the rest of the time.
MS
This is similar to a previous answer about formatting time but doesn't require a date formatter because we aren't dealing with dates any more.
If you have the number of seconds stored as an integer, you can work out the individual time components yourself:
NSUInteger h = elapsedSeconds / 3600;
NSUInteger m = (elapsedSeconds / 60) % 60;
NSUInteger s = elapsedSeconds % 60;
NSString *formattedTime = [NSString stringWithFormat:#"%u:%02u:%02u", h, m, s];
While there are easier ways of doing this (#dreamlax has a very good way), let me explain what is wrong with your example and let's get it working:
First, the reason that it is showing 04:00:00 (well, it is probably actually showing 04:00:12) is because it is converting the time from UTC/GMT to your local time. To fix this, you need to add the following line:
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
Then, it will no longer show 04:00:12 because it doesn't convert the timezone. Unfortunately, it will now show 12:00:12 instead of 00:00:12 because it is midnight. In order to fix that, have it convert the string to 24 hour time instead by using the HH formatter instead of hh:
[formatter setDateFormat:#"HH:mm:ss"];
Keep in mind that since this was designed to work with times, that it will not work for more than 24 hours (because it will "roll over" to midnight again).
The full code would be:
NSDate *date = [NSDate dateWithTimeIntervalSince1970:[[self meeting] elapsedSeconds]];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"HH:mm:ss"];
[formatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
NSLog(#"%#", [formatter stringFromDate:date]);
// Results: 00:00:12