Why is my NSMutableString potentially insecure? I searched for this but couldn't find anything.
int hour = [number intValue] / 3600;
NSMutableString *time = [[NSMutableString alloc] initWithString:#""];
if (hour < 9) {
[time appendFormat:#"0"];
[time appendFormat:[NSMutableString stringWithFormat:#"%d:", hour]];
}
What's wrong with it? This is the first time I've seen this.
Change this:
[time appendFormat:[NSMutableString stringWithFormat:#"%d:", hour]];
To this:
[time appendFormat:#"%d:", hour];
The appendFormat method is expecting you to pass a string with format, not an NSMutableString. This screenshot shows it:
This doesn't answer the question asked here but it looks like the provided code is attempting to reinvent existing format string options.
[NSMutableString stringWithFormat:#"%02d:", hour] will print a two digit integer value with leading zeros.
Related
I am sure this question came up before I am pulling my hair out. I have two dates - one from an Object on Parse.com and the other one local. I try to determine whether the remote object has been updated so that I can trigger actions locally.
When looking at the NSDate of both objects they seem identical but a comparison reveals that the remote object is newer - when checking the time internal (since1970) it becomes obvious that there is a difference but why? When I first created the local object all I did was
localObject.updatedAt = remoteObject.updatedAt //both NSDate
But when looking closer I get this:
Local Time Interval: 1411175940.000000
Local Time: 2014-09-20 01:19:00 +0000
Remote Time Interval: 1411175940.168000
Remote Time: 2014-09-20 01:19:00 +0000
Does anyone have an idea why that is and whether I can ignore this detail? Does iOS round up or something?
Adding more code:
#property (strong, nonatomic) NSDate *date;
...
PFQuery *query = [PFObject query];
[query whereKey:#"Product" equalTo:#"123456"]
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error)
{
self.date = objects[0].updatedAt;
NSTimeInterval localTime = [self.date timeIntervalSince1970];
NSTimeInterval remoteTime = [objects[0].updatedAt timeIntervalSince1970];
NSLog(#"Local Time Interval: %f", localTime);
NSLog(#"Local Time: %#", self.date);
NSLog(#"Remote Time Interval: %f", remoteTime);
NSLog(#"Remote Time: %#", objects[0].updatedAt);
}
else
{
NSLog(#"Error with query");
}
}];
That results in the console output above - and I don't understand why these dates are different.
I cannot explain why there is a difference, but the important thing to understand is that there can be a difference and that when comparing dates you have to use a tolerance value.
The Apple Date and Time Programming Guide has an example of how to compare two dates within a given tolerance:
To compare dates, you can use the isEqualToDate:, compare:,
laterDate:, and earlierDate: methods. These methods perform exact
comparisons, which means they detect sub-second differences between
dates. You may want to compare dates with a less fine granularity. For
example, you may want to consider two dates equal if they are within a
minute of each other. If this is the case, use timeIntervalSinceDate:
to compare the two dates. The following code fragment shows how to use
timeIntervalSinceDate: to see if two dates are within one minute (60
seconds) of each other.
if (fabs([date2 timeIntervalSinceDate:date1]) < 60) ...
It's up to you decide on the tolerance value, but something like 0.5 seconds seems reasonable:
+ (BOOL)date:(NSDate *)date1
equalsDate:(NSDate *)date2
{
return fabs([date2 timeIntervalSinceDate:date1]) < 0.5;
}
Parse stores dates as iso8601 format. This makes things very complex as Apple does not manage the format well. While the idea of the standard is awesome, until everyone plays by the same rules, anarchy rules..
I convert everything inbound from parse into usable format before attempting anything on their date time values..
Drop this into a library somewhere, and save yourself tons of headaches. This took weeks of searching and scratching to overcome.
+ (NSDate *)convertParseDate:(NSDate *)sourceDate {
NSDateFormatter *dateFormatter = [NSDateFormatter new];
NSString *input = (NSString *)sourceDate;
dateFormatter.dateFormat = #"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
// Always use this locale when parsing fixed format date strings
NSLocale* posix = [[NSLocale alloc] initWithLocaleIdentifier:#"en_US_POSIX"];
dateFormatter.locale = posix;
NSDate *convertedDate = [dateFormatter dateFromString:input];
assert(convertedDate != nil);
return convertedDate;
}
I've done this hundreds of times with PHP, but now I'm learning xcode and I can't figure it out. I'm trying to display a Unix Timestamp on a tableView cell like this -> "10 minutes 24 seconds ago", "4 hours, 2 minutes ago" or "2 days 4 hours ago". Any ideas?
I ran into the same thing, heres what I came up with for unix timestamps:
-(NSString *)timeSinceNow:(float)timestamp{
NSMutableString *time = [[NSMutableString alloc]init];
NSTimeInterval ti = [[NSDate date] timeIntervalSince1970];
float diff = ti - timestamp;
//days
if (diff<60*60*24*365) {
[time appendString:[NSString stringWithFormat:#"%d day", (int)floor(diff/(60*60*24))]];
}
//hours
if (diff<60*60*24) {
[time appendString:[NSString stringWithFormat:#"%d hour", (int)floor(diff/(60*60))]];
}
//minutes
if (diff<60*60) {
[time appendString:[NSString stringWithFormat:#"%d minute", (int)floor(diff/(60))]];
}
//seconds
if (diff<60) {
[time appendString:[NSString stringWithFormat:#"%d second", (int)floor(diff)]];
}
//years
if (diff>=60*60*24*365) {
[time appendString:[NSString stringWithFormat:#"%d year", (int)floor(diff/(60*60*24*365))]];
}
//check if its not singular (plural) - add 's' if so
if (![[time substringToIndex:2] isEqualToString:#"1 "]) {
[time appendString:#"s"];
}
return time;
}
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDateFormatter_Class/Reference/Reference.html#//apple_ref/occ/instm/NSDateFormatter/setDoesRelativeDateFormatting:
this one has a simple example.
NSDate *now = [NSDate date];
should do build the difference to something and and then bind it to the cell
Try this third party library: https://github.com/billgarrison/SORelativeDateTransformer
You can install it via CocoaPods, or using the instructions in the README.
If you'd like to roll your own solution, you can get the number of seconds since the current time by using +[NSDate dateWithTimeIntervalSinceReferenceDate:], passing in a reference date of the current time, +[NSDate date]. By dividing the result using the appropriate units, you should be able to get the level of granularity you desire.
SORelativeDateTransformer takes that a step further, by allowing for localization with some clever use of -[NSBundle localizedStringForKey:value:table:].
How would I format an integer when I convert it to a string? For example:
NSString *date = [NSString stringWithFormat:
#"...somestuff... %+02d00", ...., gmtOffset];
The above does not work properly. What I want is, for example, +0200 to appear. I should think that %+02d would convert my integer 2 into "+02". But it does no happen, I get "+2". Why is this? Am I doing something wrong or is some formatting not supported?
EDIT: I finally got it. Works for both positive and negative numbers and adds the leading zeros. Hope it helps.
NSString *str = [NSString stringWithFormat:#"%+03d00", 2];
NSLog(#"%#", str);
The documentation says, that there is a + as modifier. But I don't know how to exactly place/use it.
http://pubs.opengroup.org/onlinepubs/009695399/functions/printf.html
+ The result of a signed conversion shall always begin with a sign ( '+' or '-' ). The conversion shall begin with a sign only when a negative value is converted if this flag is not specified.
Link in apple documentation:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html
Yes Adam is right:
NSString *date = [NSString stringWithFormat:
#"%+03d00",2];
NSLog(#"date %#",date);
I retrieve the NSTimeInterval as follows:
NSTimeInterval milisecondedDate = ([[NSDate date] timeIntervalSince1970] * 1000);
Which logs this:
UNIX Timestamp: "1307710190993.865967"
I only want the value before the dot to send with JSON like this:
"/Date(1307710131826+0200)/"
Any suggestions?
Thanks in advance,
Get the current timestamp in milliseconds since 1970 UNIX Timestamp.
NSTimeInterval millisecondedDate = ([[NSDate date] timeIntervalSince1970] * 1000);
Format the milliesecondedDate to a string with no decimals.
NSString* formattedMilliseconds = [NSString stringWithFormat:#"%.0f", millisecondedDate];
Set up the timestamp in DateTime .net format.
NSString *startOfDateFormat = #"/Date(";
NSString *endOfDateFormat = #"+0200)/";
NSString *dateTimeNow = [NSString stringWithFormat:#"%#%#%#",startOfDateFormat, formattedMilliseconds, endOfDateFormat];
There is probably a much better solution for doing this, but this worked for me for now.
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.