cast message argument objective c - objective-c

I've got an NSMutableDictionary (p) - via a JSON string - that has a bunch of dates in it (seconds since the epoch). I want to convert them to NSDate. I tried the following:
NSDate *created_dt = [NSDate dateWithTimeIntervalSince1970:[p objectForKey:#"created_dt"]];
But I get "sending 'id' to parameter of incompatible type 'NSTimeInveral' (aka 'double')"
What's the syntax that I am missing?
Thanks!

dateWithTimeIntervalSince1970: expects an NSTimeInterval (which typedefed to a double). You pass it an object (the return value of objectForKey). This object is probably an NSNumber, so you can simply solve your problem like this:
NSDate *created_dt = [NSDate dateWithTimeIntervalSince1970:[[p objectForKey:#"created_dt"] doubleValue]];

Related

Why can't I store timeIntervalSince1970 return value to a pointer?

I'm a beginner (at programming) learning Objective-C. Xcode will not let me allocate a return value from an NSDate object; I am confused by this.
NSDate *now = [NSDate date];
long seconds = [now timeIntervalSince1970];
If I use a pointer to store the seconds:
long *seconds = [now timeIntervalSince1970];
I see the error:
Initializing 'long *' with an expression of incompatible type 'NSTimeInterval' (aka 'double')
Why can't I say "Give me the return value of now.timeIntervalSince1970 and stick at this address"?
Another question is, why can't I initialize an object and use it without needing a pointer? This will not work.
NSDate dateObject = [NSDate date];
I realize my question probably has a very easy answer, but the book doesn't explain any of the "why does it work this way" questions.
It's because [NSDate timeIntervalSince1970] returns the value as an NSTimeInterval which is a typedefd double, which is a primitive type, not an object type.
The value counts the number of seconds since 1-Jan-1970, and does not need to be an object.
You could store it in a pointer, but that would be silly:
NSTimeInterval *elapsed = (NSTimeInterval *)malloc(sizeof(NSTimeInterval));
*elapsed = [now timeIntervalSince1970];
...
free(elapsed);
timeIntervalSince1970 returns an NSTimeInterval which is a type def of double. In the Apple documentation you will see this defined like
objective-c
typedef double NSTimeInterval;
Swift
typealias NSTimeInterval = Double
and double is a primitive and not an object type so shouldn't be a pointer (Shouldn't is in Apple documentation). The Apple documentation also states the below
NSTimeInterval is always specified in seconds; it yields sub-millisecond precision over a range of 10,000 years.
Here is the Apple Documentation

Why does my app crash with NSInvalidArgumentException while trying to use dateWithTimeIntervalSince1970?

I'm trying to create an NSDate with dateWithTimeIntervalSince1970 but I keep getting an NSInvalidArgumentException. I can't figure out what's wrong with my syntax:
// [mutableItem valueForKey:#"date"] is a string which represents an integer of milliseconds
NSDate *dateObject = [NSDate dateWithTimeIntervalSince1970:([[mutableItem valueForKey:#"date"] longLongValue]/1000)];
Can anyone see what's wrong with this?
If you divide by 1000 you divide it with an integer. If you divide by 1000. (DOT) then it might work.
dateWithTimeIntervalSince1970: requires an NSTimeInterval which is a double.
Can you check your mutableItem value?
Here's my working example:
NSString *mutableItem = #"1344981600000";
NSDate *dateObject = [NSDate dateWithTimeIntervalSince1970:([mutableItem longLongValue]/1000)];
//dateObject = 2012-08-14 22:00:00 +0000

Objective C: Questions regarding time and array

Q1. NSDate *now = [NSDate date];
NSLog(#"Current date:%#",now);
The time shown is 4 hours ahead of the system time. I am wondering why is it so and how can I correct it?
Q2.. In C/C++, strings are treated as an array of characters. Is it the case in Objective-C also?
NSDate *now = [NSDate date];
NSLog(#"Current date:%#",now);
it's "now" not "date".
A1: NSLog(#"%#", now) is effectively the same as NSLog(#"%#", [now description]). The NSDate object doesn't care what the timezone is, so its description method will just give you the time in UTC. If you need to format with the right timezone and locale, you'll need to use an NSDateFormatter object to convert it to a nicely formatted string first.
A2: Yes and no, but mostly no. You can do this:
char *cString = "I am a C string";
to create a C string, which you can treat exactly as you would in C. That's something you very rarely see in Objective-C, though, except when it's absolutely necessary. The "normal" way to use strings is with instances of NSString or NSMutableString, which are fully-fledged objects:
NSString *normalString = #"I'm above all that."; (note the # symbol)

Create NSDate from Unix timestamp

How do I create an NSDate from a Unix timestamp?
channel.startDate = [NSDate dateWithTimeIntervalSince1970:
(NSTimeInterval)[channelJson objectForKey:#"broadcastStartedTime"]];
I get this error:
104: error: pointer value used where a
floating point value was expected
channels.startDate is an NSDate*. The value for the key "broadcastStartedTime" is a Javascript Number converted into an NSNumber or NSDecimalNumber by the SBJson parser library.
Try this instead:
NSNumber *startTime = channelJson[#"broadcastStartedTime"];
channel.startDate = [NSDate dateWithTimeIntervalSince1970:[startTime doubleValue]];
Your value is trapped in a pointer type of NSNumber. The dateWithTimeIntervalSince1970 method is expecting a primitive NSTimeInterval (which, under the covers, is a double).
Use -doubleValue:
// NSTimeInterval is just a typedef for double
NSTimeInterval interval = [[channelJson objectForKey:#"broadcastStartedTime"] doubleValue];
channel.startDate = [NSDate dateWithTimeIntervalSince1970:interval];
You need to unwrap the NSNumber:
channel.startDate = [NSDate dateWithTimeIntervalSince1970:[[channelJson objectForKey:#"broadcastStartedTime"] doubleValue]];
NSTimeInterval (which is unix timestmap) to NSDate conversion in Swift:
let timeInterval = NSDate().timeIntervalSince1970 // the the unix timestamp
NSDate(timeIntervalSince1970: timeInterval)

2 NSDates that should be equal aren't?

I'm using the JSON library from Stig Brautaset(http://code.google.com/p/json-framework) and I need to serialize an NSDate. I was considering converting it into a string before JSONifying it, however, I ran into this weird behavior:
Why aren't these NSDates considered equal?
NSDate *d = [[NSDate alloc] init];
NSDate *dd = [NSDate dateWithString:[d description]];
NSLog(#"%#", d);
NSLog(#"%#", dd);
if( [d isEqualToDate:dd] ){
NSLog(#"Yay!");
}
When you describe the original date object you lose some sub-second precision from the original object — in other words, -description shaves off fractional seconds, and returns
A string representation of the receiver in the international format YYYY-MM-DD HH:MM:SS ±HHMM, where ±HHMM represents the time zone offset in hours and minutes from GMT
When you create a new date object based on the description, you get it in whole seconds because the string is only precise to a whole second. So -isEqualToDate: returns NO because there is a difference of a fraction of a second between your two date objects, which it's sensitive to.
This method detects sub-second differences between dates. If you want to compare dates with a less fine granularity, use timeIntervalSinceDate: to compare the two dates.
So you'd do something like this instead (NSTimeInterval measures in seconds):
if ([d timeIntervalSinceDate:dd] == 0) {
NSLog(#"Yay!");
}
isEqualToDate detects subseconds differences between dates, but the description method does not include subseconds.
Because they're not equivalent:
NSDate *d = [NSDate date];
NSDate *dd = [NSDate dateWithString:[d description]];
NSLog(#"%f", [d timeIntervalSinceReferenceDate]);
NSLog(#"%f", [dd timeIntervalSinceReferenceDate]);
Produces:
2011-04-28 11:58:11.873 EmptyFoundation[508:903] 325709891.867788
2011-04-28 11:58:11.874 EmptyFoundation[508:903] 325709891.000000
In other words, the +dateWithString: method does not maintain sub-second precision.