Unable to convert original date using dateFromString - objective-c

I am trying to convert a time string using the following code
NSString *origDate = #"2012-12-06T09:27:18+08:00";
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setFormatterBehavior:NSDateFormatterBehavior10_4];
[df setDateFormat:#"yyyy-mm-dd HH:mm:ss VVVV"];
NSDate *convertedDate = [df dateFromString:origDate];
However when I print the convertedDate, it returns me null. My guess is that the Date format U am using does not match. How can I modify the code to make it work? What format can I use to match my string?
EDIT (After referring to apple's documentation)
I checked the date format documentation on apple's page and found the following 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];
The format above seems to match what I have in the original date string "2012-12-06T09:27:18+08:00". However I am still getting a null value back. Am I getting closer? How else can I update this?

Based on your original input, this format string provided to your date formatter should get the job done:
#"yyyy'-'MM'-'dd'T'HH':'mm':'ssZZZZZ"
Note: I had tested this under Mac OS X 10.8.2.

The format String will parse on iOS6 (not iOS5 -> nil) but it is useless for output, since the parsed date will loose it's timezone information.
Output will be something like "2012-12-06T17:27:18Z" in iOS6 maybe this is depending on wether the timezone is set to GMT.
my Code:
static NSDateFormatter *gXmlDateFormatter = nil;
// lazy init
+ (NSDateFormatter *)xmlDateFormatter
{
// e.g. updateDateTime="2012-09-18T11:06:19+00:00"
if (gXmlDateFormatter == nil) {
// prepare for parsinf Arinc-ISO-XML-dates input
gXmlDateFormatter = [[NSDateFormatter alloc] init];
gXmlDateFormatter = [NSTimeZone timeZoneForSecondsFromGMT:0];
gXmlDateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
gXmlDateFormatter.dateFormat = #"yyyy'-'MM'-'dd'T'HH':'mm':'ssZZZZZ"; // only parsing! in iOS 6 (iOS5 will parse nil)
// gXmlDateFormatter.dateFormat = #"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"; // all iOS but with NO colons in timeZone (add/remove)
}
NSLog(#"gXmlDateFormatter:%#",gXmlDateFormatter);
return gXmlDateFormatter;
}
// there's a problem with the above dateformater and iOS5 creating nil-results
+ (NSDate *)dateFromXMLString:(NSString *)arincDateString
{
NSString *dateString = arincDateString;
// xmlDateStrings may contain a ':' in the timezone part. iOS and Unicode DO NOT
// so always remove the xml-standard colon ':' from the timezone to make it iOS/Unicode compatible
// xml: http://www.w3schools.com/schema/schema_dtypes_date.asp
// iOS: http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns)
NSRange zRange = NSMakeRange(arincDateString.length-3, 1);
dateString = [arincDateString stringByReplacingOccurrencesOfString:#":" withString:#"" options:0 range:zRange];
NSDate *date = [self.arincDateFormatter dateFromString:dateString];
if(!date)NSLog(#"PARSING arincDateString:'%#' -> (NSDate*)%# ",arincDateString,date);
return date;
}
+ (NSString *)xmlStringFromDate:(NSDate *)date
{
if( !date ) return nil; // exit on nil date
#autoreleasepool {
NSString *dateString = [self.arincDateFormatter stringFromDate:date];
// iOS5 does not use a ':' in the timeZone part but xml needs it
// so allways add the xml-standard colon ':' into the timezone
NSMutableString *string = [NSMutableString stringWithString:dateString];
if( 22 < string.length ) { // prevent crashing
[string insertString:#":" atIndex:22];
} else {
NSLog(#"date output string too short:%d<22",string.length);
}
dateString = string;
if(!dateString)
NSLog(#"OUTPUT '%#' -> (NSString*)%#",date,dateString);
return dateString;
}
}

Related

Why is my NSDate not being formatted correctly?

I have a NSDate which is not being correctly formatted.
I have declared a UITextField in the .h :
#property (weak, nonatomic) IBOutlet UITextField *datetimeTextField;
Then I have a 3rd party UIPicker that picks a Date and inserts it in the mentioned TextField:
// Method to avoid diplaying the keyboard.
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
ActionSheetDatePicker *datePicker = [[ActionSheetDatePicker alloc]initWithTitle:#"Select Date and Time" datePickerMode:UIDatePickerModeDateAndTime selectedDate:[NSDate date] doneBlock:^(ActionSheetDatePicker *picker, id selectedDate, id origin) {
// As you can see here it's taking the correct (non-formatted) date
NSLog(#"Selected %#", selectedDate); // VALUE = Sat Nov 10 10:00:41 2018
//create a date formatter
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
//set its format as the required output format
[formatter setDateFormat:#"dd-MM-yyyy HH:mm:ss"];
//get the output date as string
NSString *selectedDateString = [formatter stringFromDate:selectedDate];
self.datetimeTextField.text = selectedDateString;
// And here I get the value I want to store in Parse stored in datetimeTextField.text
NSLog(#"Selected After reformat %#", self.datetimeTextField.text); // VALUE = 10-11-2018 00:35:06
} cancelBlock:^(ActionSheetDatePicker *picker) {
} origin:self.view];
datePicker.minuteInterval = 5;
[datePicker showActionSheetPicker];
return NO;
}
My problem starts when I have to call an IBAction to store this NSDate in my Parse Cloud (I have a Date column that would only accept NSDate.
- (IBAction)createeventAction:(id)sender{
// Here I "catch" the value previously stored from the Picker.
NSString *dateString = datetimeTextField.text; //// 07-11-2018 22:00:42 (correct format)
// Here I convert the NSString into NSDate with the same formatting
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd-MM-yyyy HH:mm:ss"];
NSDate *date = [dateFormatter dateFromString:dateString];
// But for some reason, date prints incorrectly.
NSLog(#"DATE in here ====>>> %#", date); // Sat Nov 10 10:00:41 2018
}
Problem:
I would like to convert a NSString (datetimeTextField.text) to a NSDate without losing the format.
EDIT 1:
I had consulted the accepted answer from this question How to convert NSStrings to NSDate but for some reason, it does not work for me.
EDIT 2:
To make it more clear:
Code to convert NSDate to NSString.
// We have a date (not formatted) => Sat Nov 10 10:00:41 2018
//create a date formatter
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"dd-MM-yyyy HH:mm:ss"];
NSString *selectedDateString = [formatter stringFromDate:selectedDate];
self.datetimeTextField.text = selectedDateString;
// Date formatted => 10-11-2018 00:35:06
Code to convert NSString back to NSDate:
NSString *dateString = datetimeTextField.text; // 10-11-2018 10:00:41 (correct format)
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd-MM-yyyy HH:mm:ss"];
NSDate *date = [dateFormatter dateFromString:dateString];
NSLog(#"DATE in here ====>>> %#", date); // Sat Nov 10 10:00:41 2018 (not formatted. WHY?)
Well thats the thing. I need to have a NSDate because I am storing dates.
You seem to misunderstand the difference between NSDate and what you get back from NSDateFormatter. NSDate is just a class that stores a date in no particular format -- it stores the information inside the object. If you want to display the date in a particular format, you need to create a string from the date, and you use NSDateFormatter to do convert your date into a string that expresses the date in the format you need.
If you print the date to the console using NSLog(), like:
NSLog("My date is %#", myDate);
then NSLog will just use the date's description method, which gives you a sort of default expression of the date. If you want to log the date in some specific format, you'll need to set up a date formatter with that format and then use it:
NSLog("My formatted date is %#", [myFormatter stringFromDate:myDate]);
In the end it turned out that my code was fine. Only thing is that I did not notice that the Date was declared as String in Parse instead of as Date.

"NSDate not an Objective-C object" error shows when run the application in IOS 7 in real device

NSDate object is working for iPhone, iPad when i ran the application in real devices. But when I run the application in iPad real device than it gives <not an Objective-C object> error. I tried to sort out it. but couldn't.
- (NSString*)getDateFromJSONToStringSaveFormat:(NSString *)dateString
{
NSDate *_Date = [NSDate alloc] init];
NSDate *_Date = [self getDateFromJSON:dateString];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd"];
return [dateFormatter stringFromDate:_Date];
}
- (NSDate*) getDateFromJSON:(NSString *)dateString
{
// Expect date in this format "/Date(1268123281843)/"
int startPos = [dateString rangeOfString:#"("].location+1;
int endPos = [dateString rangeOfString:#")"].location;
NSRange range = NSMakeRange(startPos,endPos-startPos);
unsigned long long milliseconds = [[dateString substringWithRange:range] longLongValue];
NSTimeInterval interval = milliseconds/1000;
return [NSDate dateWithTimeIntervalSince1970:interval];
}
because of this issue i initialize the NSDate object and saw the date value. (NSDate *_Date = [NSDate alloc] init];) in here also gives same error? why is that? anyone faced this error ??
First off you can just remove this line:
NSDate *_Date = [NSDate alloc] init];
Since the next line just redeclares it, also you in the line you should remove you are missing a [.
- (NSString*)getDateFromJSONToStringSaveFormat:(NSString *)dateString
{
// Not needed since the line after it also declares the variable.
//NSDate *_Date = [NSDate alloc] init];
NSDate *_Date = [self getDateFromJSON:dateString];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd"];
return [dateFormatter stringFromDate:_Date];
}

objective-c NSDateFormatter date from string returns null

I'm trying to convert this string #"August 8, 2013" to a NSDate but I keep getting NULL as my result:
strToConvert = #"August 8, 2013";
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MM/dd/YYYY zzz"];
NSDate* myDate = [dateFormatter dateFromString:strToConvert];
Am I formatting it incorrectly?
Edit:
I changed the method to this:
- (NSDate*) convertStringToDate : (NSString*) strToConvert {
NSError* error = nil;
NSDataDetector* detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeDate error:&error];
NSArray* arrDateMatches = [detector matchesInString:strToConvert options:0 range:NSMakeRange(0, [strToConvert length])];
for (NSTextCheckingResult* match in arrDateMatches) {
strToConvert = [self convertDateToString:match.date];
}
NSDate* myDate = [dateFormatter dateFromString:strToConvert];
return myDate;
}
and it works fine. The only issue is I am getting a implicit conversion from enumeration type 'enum NSTextCheckingType'... any idea of how to fix that warning?
The NSDateFormatter has the incorrect format. You need to match the format of the expected input:
[dateFormatter setDateFormat:#"MMMM d, yyyy"];

Detect if time format is in 12hr or 24hr format

Is there any way to detect if the current device of the app uses 12h our 24h format, so that I can use one NSDateFormatter for 12h and one for 24h depending on the users language/loaction setting? Just Like the UIDatePicker detects and shows the AM/PM picker if it is 12h format.
I figured it out, its pretty easy. I just added this code to viewDidLoad :
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setLocale:[NSLocale currentLocale]];
[formatter setDateStyle:NSDateFormatterNoStyle];
[formatter setTimeStyle:NSDateFormatterShortStyle];
NSString *dateString = [formatter stringFromDate:[NSDate date]];
NSRange amRange = [dateString rangeOfString:[formatter AMSymbol]];
NSRange pmRange = [dateString rangeOfString:[formatter PMSymbol]];
BOOL is24h = (amRange.location == NSNotFound && pmRange.location == NSNotFound);
[formatter release];
NSLog(#"%#\n",(is24h ? #"YES" : #"NO"));
And it perfectly returns YES or NO depending on the locale.
And here is a Swift 3.0 updated version
func using12hClockFormat() -> Bool {
let formatter = DateFormatter()
formatter.locale = Locale.current
formatter.dateStyle = .none
formatter.timeStyle = .short
let dateString = formatter.string(from: Date())
let amRange = dateString.range(of: formatter.amSymbol)
let pmRange = dateString.range(of: formatter.pmSymbol)
return !(pmRange == nil && amRange == nil)
}
this is swift solution that worked for me, those two above did not.
let dateString: String = DateFormatter.dateFormat(
fromTemplate: "j", options: 0,
locale: Locale.current
)!
if(dateString.contains("a")){
// 12 h format
return true
}else{
// 24 h format
return false
}
For Swift 5.3.
Tested on Xcode 12.
func is12hClockFormat() -> Bool {
let formatString = DateFormatter.dateFormat(
fromTemplate: "j",
options: 0,
locale: Locale.current
)!
return formatString.contains("a")
}
This uses a special date template string called "j". According to the ICU Spec, "j"...
requests the preferred hour format for the locale (h, H, K, or k), as determined by whether h, H, K, or k is used in the standard short time format for the locale. In the implementation of such an API, 'j' must be replaced by h, H, K, or k before beginning a match against availableFormats data. Note that use of 'j' in a skeleton passed to an API is the only way to have a skeleton request a locale's preferred time cycle type (12-hour or 24-hour).
That last sentence is important. It "is the only way to have a skeleton request a locale's preferred time cycle type". Since NSDateFormatter and NSCalendar are built on the ICU library, the same holds true here.
Collected from https://stackoverflow.com/a/11660380/3428146
Here is the Swift version:
func using12hClockFormat() -> Bool {
let formatter = NSDateFormatter()
formatter.locale = NSLocale.currentLocale()
formatter.dateStyle = NSDateFormatterStyle.NoStyle
formatter.timeStyle = NSDateFormatterStyle.ShortStyle
let dateString = formatter.stringFromDate(NSDate())
let amRange = dateString.rangeOfString(formatter.AMSymbol)
let pmRange = dateString.rangeOfString(formatter.PMSymbol)
return !(pmRange == nil && amRange == nil)
}
Objective C category NSDate+Extensions:
#import Foundation;
#interface NSDate (Extensions)
- (NSString *)getTimeString;
#end
#import "NSDate+Extensions.h"
#implementation NSDate (Extensions)
- (NSString *)getTimeString
{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
if ([self isTwelveHourDateFormat]) {
[formatter setDateFormat:#"hh:mm\ndd MMM"];
}
else {
[formatter setDateFormat:#"HH:mm\ndd MMM"];
}
return [formatter stringFromDate:self];
}
- (BOOL)isTwelveHourDateFormat
{
NSString *dateFormat = [NSDateFormatter dateFormatFromTemplate:#"j" options:0 locale:[NSLocale currentLocale]];
return [dateFormat containsString:#"a"];
}
#end

How to display date as "15th November 2010" in iPhone SDK?

HI,
I need to display date as "15th November 2010" in iPhone SDK.
How do I do that?
Thanks!
You can use a Date Formatter as explained in this post:
// Given some NSDate* date
NSDateFormatter* formatter = [[[NSDateFormatter alloc] init] autorelease];
[formatter setDateFormat:#"dd MMM yyyy"];
NSString* formattedDate = [formatter stringFromDate:date];
I believe you can simply just put "th" at the end of the dd in the format string. like this:
#"ddth MMM yyy
but I don't have my Mac in front of me to test it out. If that doesn't work you can try something like this:
[formatter setDateFormat:#"dd"];
NSString* day = [formatter stringFromDate:date];
[formatter setDateFormat:#"MMM yyyy"];
NSString* monthAndYear = [formatter stringFromDate:date];
NSString* date = [NSString stringWithFormat:#"%#th %#", day, monthAndYear];
I know I'm answering something old; but I did the following.
#implementation myClass
+ (NSString *) dayOfTheMonthToday
{
NSDateFormatter *DayFormatter=[[NSDateFormatter alloc] init];
[DayFormatter setDateFormat:#"dd"];
NSString *dayString = [DayFormatter stringFromDate:[NSDate date]];
//yes, I know I could combined these two lines - I just don't like all that nesting
NSString *dayStringwithsuffix = [myClass buildRankString:[NSNumber numberWithInt:[dayString integerValue]]];
NSLog (#"Today is the %# day of the month", dayStringwithsuffix);
}
+ (NSString *)buildRankString:(NSNumber *)rank
{
NSString *suffix = nil;
int rankInt = [rank intValue];
int ones = rankInt % 10;
int tens = floor(rankInt / 10);
tens = tens % 10;
if (tens == 1) {
suffix = #"th";
} else {
switch (ones) {
case 1 : suffix = #"st"; break;
case 2 : suffix = #"nd"; break;
case 3 : suffix = #"rd"; break;
default : suffix = #"th";
}
}
NSString *rankString = [NSString stringWithFormat:#"%#%#", rank, suffix];
return rankString;
}
#end
I grabbed the previous class method from this answer: NSNumberFormatter and 'th' 'st' 'nd' 'rd' (ordinal) number endings