Problem with negative date on iPad and not on simulator - cocoa

I'm working on an history application so I need to cope with date before and after JC.
I'm trying to parse a string with the form "01/01/-200" but it returns a null date while it's working with "01/01/200".
Here is my code :
NSDateFormatter* dateFormatter = [[[NSDateFormatter alloc]init] autorelease];
[dateFormatter setDateFormat:#"dd/MM/y"]; // #TODO Get negative date
[dateFormatter setLenient:NO];
NSDate* date = [dateFormatter dateFromString:dateString];
return date;
I also try using with the form "01/01/200 BC" setDateFormat:#"dd/MM/y G" but I can't make it work neither.
As mvds suggests in his answer, I tried the format "01/01/200 BC" on the simulator, and it's working... the problem only occurs on my iPad (version 3.2.1)
Do you have an idea how to do this properly ?

I just tried this:
NSDateFormatter* dateFormatter = [[[NSDateFormatter alloc]init] autorelease];
[dateFormatter setDateFormat:#"dd/MM/y G"];
NSDate *date = [dateFormatter dateFromString:#"01/01/200 BC"];
NSLog(#"refdate %#",[dateFormatter stringFromDate:date]);
date = [date addTimeInterval:24*3600*365*2];
NSLog(#"2 years later %#",[dateFormatter stringFromDate:date]);
which outputs:
refdate 01/01/200 BC
2 years later 01/01/198 BC
This is on 3.2, iPad simulator, so not the most recent SDK, but iPad nonetheless. Do you get different results, running this?

I finally find the trick.
The problem is that my iPad is in French so the Era has a different format :
BC is "av. J.-C."
AD is "ap. J.-C."
So I just had to change my XML file to get the correct format when parsing.
In order to display my date in the AD-BC format, I just convert it afterward :
+ (NSString*) convertIntoBCADString:(NSString*) originalString
{
NSString* newString = [originalString stringByReplacingOccurrencesOfString:#"av. J.-C." withString:#"BC"];
return [newString stringByReplacingOccurrencesOfString:#"ap. J.-C." withString:#"AD"];
}

Related

Xcode preprocessor macro for dates

I want to "hardcode" an expiration date into my beta code. Right now I manually calculate a unix date and compare that to the current date time:
if([[NSDate date] timeIntervalSince1970]>1422748800) mustHalt = TRUE;
I'd like a way of replacing the 1422748800 with a macro that generates the equivalent number for a date 90 days in the future at compile time.
Any suggestions?
The predefined macro __DATE__ is what you need. Here is a SO question related to this. But maybe you want to use a code like this:
const int daysToExpire = 14;
NSString *compileDate = [NSString stringWithUTF8String:__DATE__];
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"MMM d yyyy"];
NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US"];
[df setLocale:usLocale];
NSDate *expireDate = [df dateFromString:compileDate];
bool isExpired = ([[NSDate date] compare:expireDate] == NSOrderedDescending); // decide for it

How to get parse objects newer then a week

I need to get objects from parse that not older then a week.
i was trying it with
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"EEEE, MMMM d yyyy"];
NSDate *date = [object createdAt];
[dateFormatter stringFromDate:date]
Your code is a long way from working and shows some basic misunderstandings. I think you really need to go and learn about Objective-C and Cocoa/UIKit before you jump into Parse. However:
Parse has an automatic column called createdAt on all objects. You should use that.
I'm not sure about your definition of "a week ago" but to get a date exactly one week ago to the second use:
NSDate* date = [NSDate dateWithTimeIntervalSinceNow:-60*60*24*7];
There are more complex ways of doing this if you mean "midnight one week ago" or something like that but I'll leave this as is for the sake of clarity.
Pass this date to a PFQuery using the built in createdAt column:
PFQuery* q = [PFQuery queryWithClassName:[MyClass parseClassName]];
[q whereKey:#"createdAt" greaterThan:date];
Then issue the find:
[q findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
// here objects will contain your PFObject subclasses from the server
}];

dateFromString STILL returns nul

I am still kinda new to Objective C. I've searched and searched, applied everything that I've found and I STILL get nul returns.
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setLocale:[NSLocale currentLocale]];
[dateFormat setDateFormat:#"dd/MM/yyyy"];
[dateFormat setFormatterBehavior:NSDateFormatterBehaviorDefault];
NSDate *date = [dateFormat dateFromString:#"08/24/2014"];
And all I get is nul. PLEASE HELP!
Your test string doesn't seem to match your format; if the format is "dd/MM/yyyy" then the string indicates a date on the 8th day of the 24th month of 2014.

Convert UTC to local time with NSDateFormatter

I am getting the following string from a server in my iOS app:
20140621-061250
How can I convert it to the local time?
How can I define my date formatter? Is this correct?
dateFormatter.dateFormat = #"YYYYMMd-HHmmss";
The question doesn't specify the nature of what you mean by converting, exactly, but the first thing you should do, regardless of the final goal, is to correctly parse the server response using a properly configured NSDateFormatter. This requires specification of the correct format string, and the time zone must be explicitly set on the formatter or it will infer it from the local time, which would be incorrect in most cases.
Specify The Format String
Let's look at the input string provided:
20140621-061250
This uses four digits for the year, two digits (with a zero-padding) for the month, and two digits (presumably, these will be zero-padded as well) for the day. This is followed by a -, then two digits to represent the hour, 2 digits for the minute, and 2 digits for the second.
Referring to the Unicode date format standards, we can derive the format string in the following way. The four digits representing the calendar year will be replaced with yyyy in the format string. Use MM for the month, and dd for the day. Next would come the literal -. For the hours, I assume that it will be in 24 hour format as otherwise this response is ambiguous, so we use HH. Minutes are then mm and seconds ss. Concatenating the format specifiers yields the following format string, which we will use in the next step:
yyyyMMdd-HHmmss
In our program, this would look like:
NSString *dateFormat = #"yyyyMMdd-HHmmss";
Configure the input date formatter
The time format above does not specify a time zone, but because you have been provided the specification for the server response that it represents the UTC time, we can code this into our application. So, we instantiate an NSDateFormatter, set the correct time zone, and set the date format:
NSTimeZone *inputTimeZone = [NSTimeZone timeZoneWithAbbreviation:#"UTC"];
NSDateFormatter *inputDateFormatter = [[NSDateFormatter alloc] init];
[inputDateFormatter setTimeZone:inputTimeZone];
[inputDateFormatter setDateFormat:dateFormat];
Convert the input string to an NSDate
For demonstration purposes, we hard-code the string you received from the server response; you would replace this definition of inputString with the one you get from the server:
NSString *inputString = #"20140621-061250";
NSDate *date = [inputDateFormatter dateFromString:inputString];
At this point, we have the necessary object to do any further conversions or calculations - an NSDate which represents the time communicated by the server. Remember, an NSDate is just a time stamp - it has no relation to a time zone whatsoever, which only plays a role when converting to and from string representations of the date, or representations of a calendrical date via NSDateComponents.
Next steps
The question doesn't clearly specify what type of conversion is needed, so we'll see an example of formatting the date to display in the same format as the server response (although, I can't think of a likely use case for this particular bit of code, to be honest). The steps are quite similar - we specify a format string, a time zone, configure a date formatter, and then generate a string (in the specified format) from the date:
NSTimeZone *outputTimeZone = [NSTimeZone localTimeZone];
NSDateFormatter *outputDateFormatter = [[NSDateFormatter alloc] init];
[outputDateFormatter setTimeZone:outputTimeZone];
[outputDateFormatter setDateFormat:dateFormat];
NSString *outputString = [outputDateFormatter stringFromDate:date];
Since I'm in UTC-06:00, printing outputString gives the following:
20140621-001250
It's likely you'll instead want to use setDateStyle: and setTimeStyle: instead of a format string if you're displaying this date to the user, or use an NSCalendar to get an NSDateComponents instance to do arithmetic or calculations on the date. An example for displaying a verbose date string to the user:
NSTimeZone *outputTimeZone = [NSTimeZone localTimeZone];
NSDateFormatter *outputDateFormatter = [[NSDateFormatter alloc] init];
[outputDateFormatter setTimeZone:outputTimeZone];
[outputDateFormatter setDateStyle:NSDateFormatterFullStyle];
[outputDateFormatter setTimeStyle:NSDateFormatterFullStyle];
NSString *outputString = [outputDateFormatter stringFromDate:date];
Printing outputString here gives us the following:
Saturday, June 21, 2014 at 12:12:50 AM Mountain Daylight Time
Note that setting the time zone appropriately will handle transitions over daylight savings time. Changing the input string to "20141121-061250" with the formatter style code above gives us the following date to display (Note that Mountain Standard Time is UTC-7):
Thursday, November 20, 2014 at 11:12:50 PM Mountain Standard Time
Summary
Any time you get date input in a string form representing a calendar date and time, your first step is to convert it using an NSDateFormatter configured for the input's format, time zone, and possibly locale and calendar, depending on the source of the input and your requirements. This will yield an NSDate which is an unambiguous representation of a moment in time. Following the creation of that NSDate, one can format it, style it, or convert it to date components as needed for your application requirements.
To get your string into a NSDate, you would use a NSDateFormatter like this:
NSString *myDateAsAStringValue = #"20140621-061250"
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"yyyyMMdd-HHmmss"];
NSDate *myDate = [df dateFromString: myDateAsAStringValue];
You may want to read this post about working with Date and Time
EDIT:
To parse it as UTC you have to add the line:
[df setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"]];
Also, when you print it with NSLog, if you are using the same NSDateFormatter, you will get the input string as output (since you apply the inverse of the parsing function).
Here is the full code, for parsing and for getting the output with a standard format:
//The input
NSString *myDateAsAStringValue = #"20140621-061250";
//create the formatter for parsing
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setTimeZone:[NSTimeZone timeZoneWithAbbreviation:#"UTC"]];
[df setDateFormat:#"yyyyMMdd-HHmmss"];
//parsing the string and converting it to NSDate
NSDate *myDate = [df dateFromString: myDateAsAStringValue];
//create the formatter for the output
NSDateFormatter *out_df = [[NSDateFormatter alloc] init];
[out_df setDateFormat:#"yyyy-MM-dd'T'HH:mm:ssz"];
//output the date
NSLog(#"the date is %#",[out_df stringFromDate:myDate]);
One possible solution in Swift using NSDate extension (maybe it could help future viewers of this question):
import UIKit
// For your personal information: NSDate() initializer
// always returns a date in UTC, no matter the time zone specified.
extension NSDate {
// Convert UTC (or GMT) to local time
func toLocalTime() -> NSDate {
let timezone: NSTimeZone = NSTimeZone.localTimeZone()
let seconds: NSTimeInterval = NSTimeInterval(timezone.secondsFromGMTForDate(self))
return NSDate(timeInterval: seconds, sinceDate: self)
}
// Convert local time to UTC (or GMT)
func toGlobalTime() -> NSDate {
let timezone: NSTimeZone = NSTimeZone.localTimeZone()
let seconds: NSTimeInterval = -NSTimeInterval(timezone.secondsFromGMTForDate(self))
return NSDate(timeInterval: seconds, sinceDate: self)
}
}

Date to String conversion (NSDateFormatter) doesn't work

I'm working on an iOS project, retrieving data from SQLite through JSON. The table has a datetime column called 'date'. When I retrieve the date in Xcode and printout the result, I see "2012-09-02T16:30:00Z". But when I try to convert it using NSDateFormatter, the result is null.
NSString *formatString = [NSDateFormatter dateFormatFromTemplate:#"EdMMM" options:0 locale:[NSLocale currentLocale]];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:formatString];
NSString *dateString = [dateFormatter stringFromDate:categoryAtIndex.date];
NSLog(#"%# => %#", categoryAtIndex.date, dateString);
The above outputs:
2012-09-02T16:30:00Z => (null)
in stead of a nicely formatted datestring.
Any thoughts?
Thanks to mask8 I found the issue was related to another part of my code. I found this post on stackoverflow to solve the way to change the format of the date that I retrieved through JSON. I also found another post on stackoverflow describing how to handle conversions from a string to NSDate and vice versa.

Resources