loosing 1 hour after formatting a date string - ios

i am formatting a date string with the following code:
and this is the format of the date string : 2013-10-08T20:30:00+03:00
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[dateFormatter setDateFormat:#"EEEE"];
NSDateFormatter *formmatter = [[NSDateFormatter alloc] init];
formmatter.dateFormat = #"yyyy-MM-dd'T'HH:mm:SSSZZZ";
NSString *dataString = [meetingData objectForKey:#"start"];
if (![dataString isKindOfClass:[NSNull class]]) {
NSMutableString *mutableDate = [dataString mutableCopy];
[mutableDate deleteCharactersInRange:NSMakeRange(mutableDate.length - 3, 1)];
NSDate *gmtDate = [formmatter dateFromString:mutableDate];
NSDateFormatter *HHMM_Fromatter = [[NSDateFormatter alloc] init];
[HHMM_Fromatter setDateFormat:#"HH:mm"];
self.meetingTime = checkTheObject([HHMM_Fromatter stringFromDate:gmtDate]);
self.meetingDay = checkTheObject([dateFormatter stringFromDate:gmtDate]);
}
the output is forself.meetingTime : 19:30
and self.meetingDay is fine, why am i loosing 1 hour?

Your two date formatters HHMM_Fromatter and dateFormatter use different locales and thus, different time zones. You should explicitly set the timezone of both formatters to the same zone (probably [NSTimeZone localTimeZone]).
Note that the remaining parts of your date code seems fragile. You shouldn't do string calculations to remove the time zone from a string representation.
NSDate represents an absolute point in time and is not affected by time zones or locales. You should parse the string to one single NSDate and then use this date to calculate user facing string representations that take time zones into account.

Related

How to Get Date, Hour, Minute and Second in Objective-c from Timestamp "2017-04-30T14:30+00:00(GMT)"?

I'm new in iOS(Objective-c) coding and I'm stuck at timestamp.
I'm getting timestamp while JSON parsing ie.2017-04-30T14:30+00:00(GMT). How to get date, hour, minute and second from this timestamp?? I'm getting this format in GMT so, is it possible to convert it into "IST"? How?
Date Format Patterns
A date pattern is a string of characters, where specific strings of characters are replaced with date and time data from a calendar when formatting or used to generate data for a calendar when parsing. The following are the characters used in patterns to show the appropriate formats for a given locale. The following are examples:
- (NSString *)curentDateStringFromDate:(NSDate *)dateTimeInLine withFormat:(NSString *)dateFormat {
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:dateFormat];
NSString *convertedString = [formatter stringFromDate:dateTimeInLine];
return convertedString;
}
Use it like below:
NSString *dateString = [self curentDateStringFromDate:[NSDate date] withFormat:#"dd-MM-yyyy"];
NSString *timeString = [self curentDateStringFromDate:[NSDate date] withFormat:#"hh:mm:ss"];
NSString *hoursString = [self curentDateStringFromDate:[NSDate date] withFormat:#"h"];
In the Foundation framework, the class to use for this task (in either direction) is NSDateFormatter Refer here
The code below convert GMT to IST.
NSString *inDateStr = #"2000/01/02 03:04:05";
NSString *s = #"yyyy/MM/dd HH:mm:ss";
// about input date(GMT)
NSDateFormatter *inDateFormatter = [[NSDateFormatter alloc] init];
inDateFormatter.dateFormat = s;
inDateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"GMT"];
NSDate *inDate = [inDateFormatter dateFromString:inDateStr];
// about output date(IST)
NSDateFormatter *outDateFormatter = [[NSDateFormatter alloc] init];
outDateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"IST"];
outDateFormatter.dateFormat = s;
NSString *outDateStr = [outDateFormatter stringFromDate:inDate];
// final output
NSLog(#"[in]%# -> [out]%#", inDateStr, outDateStr);

NSDateFormatterLongStyle string to NSDate

I have a UIDataPicker in my viewController with default location, when my user finishes selecting the date I run this code:
NSString *dateString = [NSDateFormatter localizedStringFromDate:[self.dataPicker date]
dateStyle:NSDateFormatterLongStyle
timeStyle:NSDateFormatterNoStyle];
With that code I can storage the date in the following format:
May 31, 2016
Later in my code I need to convert this string into a real date format, for this I use the code below:
-(NSDate*)convertStringToDate:(NSString*)date{
NSString *dateString = date;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[dateFormatter setDateFormat:#"MM/dd/yyyy"];
return [dateFormatter dateFromString:dateString];
}
But this code return a null value. As the datepicker is set by default, my system can receive any date format, but in the end I want it to be converted to the format en_us.
How I can solve this problem?
Don't store the date as a string; store it as an offset, in seconds, from some reference date.
i.e:
uint64_t offset = (uint64_t)[[self.dataPicker date] timeIntervalSinceReferenceDate];
// store this 64-bit unsigned integer.
This takes less space and is quicker to convert to/from an NSDate object.
You can leave the offset as an NSTimeInterval (64-bit floating point double) if you prefer, but as you aren't storing date & time, uint64_t should do...
Use this code,
-(NSDate*)convertStringToDate:(NSString*)date{
NSString *dateString = date;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[dateFormatter setDateFormat:#"MMM d, yyyy"];
return [dateFormatter dateFromString:dateString];
}
hope its helpful
The formatting string depends on the locale you are using. From the localizedStringFromDate documentation:
Returns string representation of a given date formatted for the
current locale using the specified date and time styles.
This method uses a date formatter configured with the current default
settings. The returned string is the same as if you configured and
used a date formatter as shown in the following example:
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.formatterBehavior = NSDateFormatterBehavior10_4;
formatter.dateStyle = dateStyle; formatter.timeStyle = timeStyle;
NSString *result = [formatter stringForObjectValue:date];
Means, you should do the next:
-(NSDate*)convertStringToDate:(NSString*)dateString {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.formatterBehavior = NSDateFormatterBehavior10_4;
dateFormatter.dateStyle = NSDateFormatterLongStyle;
dateFormatter.timeStyle = NSDateFormatterNoStyle;
return [dateFormatter dateFromString:dateString];
}

NSDateFormatter Returning Unexpected Time Values

Can anyone explain to me why the following code returns inconsistent time values? I've been getting incorrect results when trying to create an NSDate object from a user specified date/time string and I've put together the following code below to illustrate the problem.
// Create two strings containing the current date and time
NSDateFormatter * dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyy-MM-dd"];
NSDateFormatter * timeFormat = [[NSDateFormatter alloc] init];
[timeFormat setDateFormat:#"HH:mm:ss a"];
timeFormat.AMSymbol = #"AM";
timeFormat.PMSymbol = #"PM";
timeFormat.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"EDT"];
NSDate * now = [[NSDate alloc] init];
NSString *theDate = [dateFormat stringFromDate:now];
NSString *theTime = [timeFormat stringFromDate:now];
NSLog(#"The current date/time is (GTM): %#", now);
NSLog(#"The current date/time is (EDT): %# %#", theDate, theTime);
// Combine the date and time strings
NSMutableString * theDateTime = [[NSMutableString alloc] init];
theDateTime = [theDateTime stringByAppendingString:theDate];
theDateTime = [theDateTime stringByAppendingString:#" "];
theDateTime = [theDateTime stringByAppendingString:theTime];
// Define the formatter to parse the combined date and time string
NSDateFormatter * dateFormatter=[[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss a"];
dateFormatter.AMSymbol = #"AM";
dateFormatter.PMSymbol = #"PM";
dateFormatter.timeZone = [NSTimeZone timeZoneWithAbbreviation:#"EDT"];
// Create an NSDate object using the combined date and time string
NSDate * theDateTimeObject=[dateFormatter dateFromString:theDateTime];
NSString * theDateTimeString=[dateFormatter stringFromDate:theDateTimeObject];
// Print the results
NSLog(#"theDateTimeObject (GMT) = %#", theDateTimeObject);
NSLog(#"theDateTimeString (EDT) = %#", theDateTimeString);
This code produces the following output:
The current date/time is (GMT): 2015-09-29 22:28:10 +0000
The current date/time is (EDT): 2015-09-29 18:28:10 PM
theDateTimeObject (GMT) = 2015-09-29 16:28:10 +0000
theDateTimeString (EDT) = 2015-09-29 12:28:10 PM
Clearly something is going wrong when the combined date and time string gets parsed by the date formatter to create the NSDate object. It seems to not understand the input time zone and returns a time in GMT that is several hours off what it should be (i.e. +4 hours). I've set the time zone to be "EDT", so not sure what else I can do to fix this problem, other than hard code an offset in the input, which I'd rather not do. Any help would be appreciated.
You are doing bad things by using both 24-hour format (HH) instead of 12-hour format (hh) and using AM/PM (a).
Change both instances of HH in your formats to hh and you should get the expected results.
You should also set the formatter's locale to the special locale en_US_POSIX to avoid issues with the device's 24-hour time setting.
Side note: Your use of NSMutableString is all wrong. Try this:
NSMutableString * theDateTime = [[NSMutableString alloc] init];
[theDateTime appendString:theDate];
[theDateTime appendString:#" "];
[theDateTime appendString:theTime];
or simply use:
NSString *theDateTime = [NSString stringWithFormat:#"%# %#", theDate, theTime];

Why is my formatter returning a nil NSDate

The following code will set date to nil.
NSString *dateString = #"2014-04-27T04:20:07.000-04:00";
NSString *UTC_FORMAT = #"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:UTC_FORMAT];
NSDate *date = [formatter dateFromString:dateString];
What am I doing wrong?
I've tried many other different variations for UTC_FORMAT, but counldn't seem to get it. I'm also a little bit confused as to when and where the single quotes go. After playing with this for a while, I'm assuming it can goes around characters that shouldn't be interpreted by the formatter, but that's a separate thing.
Related Links That Couldn't Help Me:
Apple Docs: Data Formatting Guid
SO: Why is NSDateFormatter returning nil?
Formats That I've Tried:
NSString *UTC_FORMAT = #"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'";
NSString *UTC_FORMAT = #"yyyy-MM-dd'T'HH:mm:ss-Z";
Your date looks like a quite standard JSON date format in RFC3339 format. However, there are several possibilities how these dates can be formatted. In this case, your date string contains milliseconds. Your date format doesn't, so this cannot work. The following code will check for dates without fractional seconds first, then for dates with fractional seconds. Furthermore, you are looking for a literal character Z instead of a timezone.
The "X5" is documented at
http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_Patterns
and converts time zones in quite a flexible way, including the colon in the middle. .SSSSSS will convert fractional parts of seconds up to microseconds. Should you be given nanoseconds change it to nine S characters.
And I forgot the locale information...
NSString *UTC_FORMAT = #"yyyy'-'MM'-'dd'T'HH':'mm':'ssX5";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:UTC_FORMAT];
enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
gmtTimeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
[formatter setLocale:enUSPOSIXLocale];
[formatter setTimeZone:gmtTimeZone];
NSDate *date = [formatter dateFromString:dateString];
if (date == nil)
{
NSString *UTC_FORMAT2 = #"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSSSSX5";
NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init];
[formatter2 setDateFormat:UTC_FORMAT2];
[formatter2 setLocale:enUSPOSIXLocale];
[formatter2 setTimeZone:gmtTimeZone];
date = [formatter2 dateFromString:dateString];
}
To avoid dependencies on the current locale, add :
NSString *dateString = #"2014-04-27T04:20:07.000-04:00";
NSString *UTC_FORMAT = #"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:UTC_FORMAT];
[formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"]];
NSDate *date = [formatter dateFromString:dateString];

Setting up AM/PM for my time in iOS

My original date format is : 2014-03-14T10:35:24.537
So I first separate the time and date with componentsSeparatedByString, then I save the second half (the time part) to NSString time, while eliminating the microseconds. to the format 10:35. I'm trying to get it to add PM/AM but setDateFormat:#"hh:mm a" is not doing it. What am I doing wrong?
NSArray *components = [datestr componentsSeparatedByString:#"T"];
NSString *time = components[1];
time = [time substringWithRange:NSMakeRange(0, 5)];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"hh:mm a"];
NSDate *timeFromString = [formatter dateFromString:time];
NSLog(#"%#", timeFromString);
When I log timeFromString, I get a null.
EDIT: I changed the formatter above to [formatter setDateFormat:#"hh:mm"]; and now the timeFromString logs as: 2000-01-01 18:35:00 +0000 when data coming in is 2014-03-14T10:35:28.42
A date formatter is used to convert dates to or from a string. A single date formatter cannot be used to convert between two different date formats. (At least, not without mutating the date formatter between operations.)
Use one formatter to convert the original string to a date. That formatter should not include AM/PM, since your original string doesn't.
Use a second formatter to convert the date to a new string. That formatter should include AM/PM, if you desire one.
Here 's how you should parse and convert the date:
//the date string
NSString *datestr = #"2014-03-14T10:35:24.537";
//strip the date
NSArray *components = [datestr componentsSeparatedByString:#"T"];
NSString *time = components[1];
time = [time substringWithRange:NSMakeRange(0, 5)];
//parse string to a date
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"HH:mm"];
NSDate *timeFromString = [formatter dateFromString:time];
//Desired format
NSDateFormatter *timeformat = [[NSDateFormatter alloc] init];
[timeformat setDateFormat:#"hh:mm aa"];
NSString *finalString = [timeformat stringFromDate:timeFromString];
NSLog(#"final = %#",finalString);
OUTPUT:
final = 10:35 AM

Resources