How can I format a date in Objective-C similar to the jquery.timeago library? - iphone

I have a feed of items displayed in table cells, part of which is a date / timestamp in the past.
In Objective-C, how can I accomplish formatting them in the same manner as the jquery.timeago plugin on the web?
That is, taking in a date and outputting things like:
'just now'
'2 minutes ago'
'24 days ago'
'a month ago'
I see there is an NSDate extension class here with methods such as dateWithDaysBeforeNow, dateWithMinutesBeforeNow, etc, but if there is a library out there that has already done this I will use it.
EDIT: Further to this, if someone composes a method (takes a date, returns a string) that accomplishes this, either with this linked extensions library or another method, I will award them the answer.
EDIT 2 Bounty goes to whoever can write the fuzzy date algorithm in Objective-C.

Create Static Class Method:
+ (NSString *)stringForTimeIntervalSinceCreated:(NSDate *)dateTime serverTime:(NSDate *)serverDateTime{
NSInteger MinInterval;
NSInteger HourInterval;
NSInteger DayInterval;
NSInteger DayModules;
NSInteger interval = abs((NSInteger)[dateTime timeIntervalSinceDate:serverDateTime]);
if(interval >= 86400)
{
DayInterval = interval/86400;
DayModules = interval%86400;
if(DayModules!=0)
{
if(DayModules>=3600){
//HourInterval=DayModules/3600;
return [NSString stringWithFormat:#"%i days", DayInterval];
}
else {
if(DayModules>=60){
//MinInterval=DayModules/60;
return [NSString stringWithFormat:#"%i days", DayInterval];
}
else {
return [NSString stringWithFormat:#"%i days", DayInterval];
}
}
}
else
{
return [NSString stringWithFormat:#"%i days", DayInterval];
}
}
else{
if(interval>=3600)
{
HourInterval= interval/3600;
return [NSString stringWithFormat:#"%i hours", HourInterval];
}
else if(interval>=60){
MinInterval = interval/60;
return [NSString stringWithFormat:#"%i minutes", MinInterval];
}
else{
return [NSString stringWithFormat:#"%i Sec", interval];
}
}
}

OK, I couldn't sleep last night -- guess I'll bite. Here's a line-for-line port of jQuery's timeAgo, with the original JavaScript source in comments for reference. Uses standard ObjC/AppKit mechanisms for user defaults and localization. Web-related stuff, like updating an existing DOM element is obviously omitted. Also omits the mechanism where you can put a function in the settings, because that's sort of JavaScript specific. Without further ado:
Header file:
//
// NSDate+JQTimeAgoAdditions.h
// JQTimeAgo
//
#import <Foundation/Foundation.h>
#interface NSDate (JQTimeAgoAdditions)
- (NSString*)timeAgo;
#end
extern NSString* const kJQTimeAgoAllowFutureKey;
extern NSString* const kJQTimeAgoStringsPrefixAgoKey;
extern NSString* const kJQTimeAgoStringsPrefixFromNowKey;
extern NSString* const kJQTimeAgoStringsSuffixAgoKey;
extern NSString* const kJQTimeAgoStringsSuffixFromNowKey;
extern NSString* const kJQTimeAgoStringsSecondsKey;
extern NSString* const kJQTimeAgoStringsMinuteKey;
extern NSString* const kJQTimeAgoStringsMinutesKey;
extern NSString* const kJQTimeAgoStringsHourKey;
extern NSString* const kJQTimeAgoStringsHoursKey;
extern NSString* const kJQTimeAgoStringsDayKey;
extern NSString* const kJQTimeAgoStringsDaysKey;
extern NSString* const kJQTimeAgoStringsMonthKey;
extern NSString* const kJQTimeAgoStringsMonthsKey;
extern NSString* const kJQTimeAgoStringsYearKey;
extern NSString* const kJQTimeAgoStringsYearsKey;
extern NSString* const kJQTimeAgoStringsNumbersKey;
And the implementation file:
//
// NSDate+JQTimeAgoAdditions.m
// JQTimeAgo
//
#import "NSDate+JQTimeAgoAdditions.h"
#implementation NSDate (JQTimeAgoAdditions)
- (NSString*)timeAgo
{
NSTimeInterval distanceMillis = -1000.0 * [self timeIntervalSinceNow];
// inWords: function(distanceMillis) {
// var $l = this.settings.strings;
NSUserDefaults* defs = [NSUserDefaults standardUserDefaults];
// var prefix = $l.prefixAgo;
NSString* prefix = [defs stringForKey: kJQTimeAgoStringsPrefixAgoKey];
// var suffix = $l.suffixAgo;
NSString* suffix = [defs stringForKey: kJQTimeAgoStringsSuffixAgoKey];
// if (this.settings.allowFuture) {
if ([defs boolForKey: kJQTimeAgoAllowFutureKey])
{
// if (distanceMillis < 0) {
if (distanceMillis < 0.0)
{
// prefix = $l.prefixFromNow;
prefix = [defs stringForKey: kJQTimeAgoStringsPrefixFromNowKey];
// suffix = $l.suffixFromNow;
suffix = [defs stringForKey: kJQTimeAgoStringsSuffixFromNowKey];
// }
}
// distanceMillis = Math.abs(distanceMillis);
distanceMillis = fabs(distanceMillis);
// }
}
//
// var seconds = distanceMillis / 1000;
const double seconds = distanceMillis / 1000.0;
// var minutes = seconds / 60;
const double minutes = seconds / 60.0;
// var hours = minutes / 60;
const double hours = minutes / 60.0;
// var days = hours / 24;
const double days = hours / 24.0;
// var years = days / 365;
const double years = days / 365.0;
//
// function substitute(stringOrFunction, number) { ... }
// Use stringWithFormat, etc.
//
// var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
NSString* words = nil;
if (seconds < 45)
words = [[defs stringForKey: kJQTimeAgoStringsSecondsKey] stringByReplacingOccurrencesOfString: #"%d" withString: [NSString stringWithFormat: #"%d", (int)round(seconds)]];
// seconds < 90 && substitute($l.minute, 1) ||
else if (seconds < 90)
words = [[defs stringForKey: kJQTimeAgoStringsMinuteKey] stringByReplacingOccurrencesOfString: #"%d" withString: [NSString stringWithFormat: #"%d", (int)1]];
// minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
else if (minutes < 45)
words = [[defs stringForKey: kJQTimeAgoStringsMinutesKey] stringByReplacingOccurrencesOfString: #"%d" withString: [NSString stringWithFormat: #"%d", (int)round(minutes)]];
// minutes < 90 && substitute($l.hour, 1) ||
else if (minutes < 90)
words = [[defs stringForKey: kJQTimeAgoStringsHourKey] stringByReplacingOccurrencesOfString: #"%d" withString: [NSString stringWithFormat: #"%d", (int)1]];
// hours < 24 && substitute($l.hours, Math.round(hours)) ||
else if (hours < 24)
words = [[defs stringForKey: kJQTimeAgoStringsHoursKey] stringByReplacingOccurrencesOfString: #"%d" withString: [NSString stringWithFormat: #"%d", (int)round(hours)]];
// hours < 48 && substitute($l.day, 1) ||
else if (hours < 48)
words = [[defs stringForKey: kJQTimeAgoStringsDayKey] stringByReplacingOccurrencesOfString: #"%d" withString: [NSString stringWithFormat: #"%d", (int)1]];
// days < 30 && substitute($l.days, Math.floor(days)) ||
else if (days < 30)
words = [[defs stringForKey: kJQTimeAgoStringsDaysKey] stringByReplacingOccurrencesOfString: #"%d" withString: [NSString stringWithFormat: #"%d", (int)floor(days)]];
// days < 60 && substitute($l.month, 1) ||
else if (days < 60)
words = [[defs stringForKey: kJQTimeAgoStringsMonthKey] stringByReplacingOccurrencesOfString: #"%d" withString: [NSString stringWithFormat: #"%d", (int)1]];
// days < 365 && substitute($l.months, Math.floor(days / 30)) ||
else if (days < 365)
words = [[defs stringForKey: kJQTimeAgoStringsMonthsKey] stringByReplacingOccurrencesOfString: #"%d" withString: [NSString stringWithFormat: #"%d", (int)floor(days/30.0)]];
// years < 2 && substitute($l.year, 1) ||
else if (years < 2)
words = [[defs stringForKey: kJQTimeAgoStringsYearKey] stringByReplacingOccurrencesOfString: #"%d" withString: [NSString stringWithFormat: #"%d", (int)1]];
// substitute($l.years, Math.floor(years));
else
words = [[defs stringForKey: kJQTimeAgoStringsYearsKey] stringByReplacingOccurrencesOfString: #"%d" withString: [NSString stringWithFormat: #"%d", (int)floor(years)]];
//
// return $.trim([prefix, words, suffix].join(" "));
NSString* retVal = [[NSString stringWithFormat: #"%# %# %#",
(prefix ? prefix : #""),
(words ? words : #""),
(suffix ? suffix : #"")] stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
return retVal;
// },
}
// Load settings
+ (void)load
{
// Frameworks are guaranteed to be loaded by now so we can use NSDictionary, etc...
// See here for details: http://www.mikeash.com/pyblog/friday-qa-2009-05-22-objective-c-class-loading-and-initialization.html
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
#autoreleasepool
{
NSDictionary* settings = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool: NO], kJQTimeAgoAllowFutureKey,
NSLocalizedStringWithDefaultValue(kJQTimeAgoStringsPrefixAgoKey, nil, [NSBundle mainBundle], #" ", #"kJQTimeAgoStringsPrefixAgoKey"), kJQTimeAgoStringsPrefixAgoKey,
NSLocalizedStringWithDefaultValue(kJQTimeAgoStringsPrefixFromNowKey, nil, [NSBundle mainBundle], #" ", #"kJQTimeAgoStringsPrefixFromNowKey"), kJQTimeAgoStringsPrefixFromNowKey,
NSLocalizedStringWithDefaultValue(kJQTimeAgoStringsSuffixAgoKey, nil, [NSBundle mainBundle], #"ago", #"kJQTimeAgoStringsSuffixAgoKey"), kJQTimeAgoStringsSuffixAgoKey,
NSLocalizedStringWithDefaultValue(kJQTimeAgoStringsSuffixFromNowKey, nil, [NSBundle mainBundle], #"from now", #"kJQTimeAgoStringsSuffixFromNowKey"), kJQTimeAgoStringsSuffixFromNowKey,
NSLocalizedStringWithDefaultValue(kJQTimeAgoStringsSecondsKey, nil, [NSBundle mainBundle], #"less than a minute", #"kJQTimeAgoStringsSecondsKey"), kJQTimeAgoStringsSecondsKey,
NSLocalizedStringWithDefaultValue(kJQTimeAgoStringsMinuteKey, nil, [NSBundle mainBundle], #"about a minute", #"kJQTimeAgoStringsMinuteKey"), kJQTimeAgoStringsMinuteKey,
NSLocalizedStringWithDefaultValue(kJQTimeAgoStringsMinutesKey, nil, [NSBundle mainBundle], #"%d minutes", #"kJQTimeAgoStringsMinutesKey"), kJQTimeAgoStringsMinutesKey,
NSLocalizedStringWithDefaultValue(kJQTimeAgoStringsHourKey, nil, [NSBundle mainBundle], #"about an hour", #"kJQTimeAgoStringsHourKey"), kJQTimeAgoStringsHourKey,
NSLocalizedStringWithDefaultValue(kJQTimeAgoStringsHoursKey, nil, [NSBundle mainBundle], #"about %d hours", #"kJQTimeAgoStringsHoursKey"), kJQTimeAgoStringsHoursKey,
NSLocalizedStringWithDefaultValue(kJQTimeAgoStringsDayKey, nil, [NSBundle mainBundle], #"about a day", #"kJQTimeAgoStringsDayKey"), kJQTimeAgoStringsDayKey,
NSLocalizedStringWithDefaultValue(kJQTimeAgoStringsDaysKey, nil, [NSBundle mainBundle], #"%d days", #"kJQTimeAgoStringsDaysKey"), kJQTimeAgoStringsDaysKey,
NSLocalizedStringWithDefaultValue(kJQTimeAgoStringsMonthKey, nil, [NSBundle mainBundle], #"about a month", #"kJQTimeAgoStringsMonthKey"), kJQTimeAgoStringsMonthKey,
NSLocalizedStringWithDefaultValue(kJQTimeAgoStringsMonthsKey, nil, [NSBundle mainBundle], #"%d months", #"kJQTimeAgoStringsMonthsKey"), kJQTimeAgoStringsMonthsKey,
NSLocalizedStringWithDefaultValue(kJQTimeAgoStringsYearKey, nil, [NSBundle mainBundle], #"about a year", #"kJQTimeAgoStringsYearKey"), kJQTimeAgoStringsYearKey,
NSLocalizedStringWithDefaultValue(kJQTimeAgoStringsYearsKey, nil, [NSBundle mainBundle], #"%d years", #"kJQTimeAgoStringsYearsKey"), kJQTimeAgoStringsYearsKey,
nil];
[[NSUserDefaults standardUserDefaults] registerDefaults: settings];
}
});
}
#end
NSString* const kJQTimeAgoAllowFutureKey = #"kJQTimeAgoAllowFutureKey";
NSString* const kJQTimeAgoStringsPrefixAgoKey = #"kJQTimeAgoStringsPrefixAgoKey";
NSString* const kJQTimeAgoStringsPrefixFromNowKey = #"kJQTimeAgoStringsPrefixFromNowKey";
NSString* const kJQTimeAgoStringsSuffixAgoKey = #"kJQTimeAgoStringsSuffixAgoKey";
NSString* const kJQTimeAgoStringsSuffixFromNowKey = #"kJQTimeAgoStringsSuffixFromNowKey";
NSString* const kJQTimeAgoStringsSecondsKey = #"kJQTimeAgoStringsSecondsKey";
NSString* const kJQTimeAgoStringsMinuteKey = #"kJQTimeAgoStringsMinuteKey";
NSString* const kJQTimeAgoStringsMinutesKey = #"kJQTimeAgoStringsMinutesKey";
NSString* const kJQTimeAgoStringsHourKey = #"kJQTimeAgoStringsHourKey";
NSString* const kJQTimeAgoStringsHoursKey = #"kJQTimeAgoStringsHoursKey";
NSString* const kJQTimeAgoStringsDayKey = #"kJQTimeAgoStringsDayKey";
NSString* const kJQTimeAgoStringsDaysKey = #"kJQTimeAgoStringsDaysKey";
NSString* const kJQTimeAgoStringsMonthKey = #"kJQTimeAgoStringsMonthKey";
NSString* const kJQTimeAgoStringsMonthsKey = #"kJQTimeAgoStringsMonthsKey";
NSString* const kJQTimeAgoStringsYearKey = #"kJQTimeAgoStringsYearKey";
NSString* const kJQTimeAgoStringsYearsKey = #"kJQTimeAgoStringsYearsKey";
NSString* const kJQTimeAgoStringsNumbersKey = #"kJQTimeAgoStringsNumbersKey";

I wrote an NSDate category that returns time deltas in a human readable format (e.g., "4 weeks, 2 days"). You can download it here and tweak it to your needs: https://github.com/chriscdn/RHTools (look for NSDate+timesince).

I know this is old but this is what I did which is fairly simple...
NSDate *placeDate = [object createdAt];
NSTimeInterval timeSince = [placeDate timeIntervalSinceNow];
NSLog(#"%f", timeSince);
if (timeSince > -60) {
cell.date.text = [NSString stringWithFormat:#"%f seconds ago", -timeSince];
}
else if (timeSince <= -60 && timeSince > -3600){
cell.date.text = [NSString stringWithFormat:#"%.0f minutes ago", -timeSince/60];
}
else if (timeSince <= -3600 && timeSince > -86400){
cell.date.text = [NSString stringWithFormat:#"%.0f hours ago", -timeSince/60/60];
}
else if (timeSince <= -86400 && timeSince > -604800){
cell.date.text = [NSString stringWithFormat:#"%.0f days ago", -timeSince/24/60/60];
}
else if (timeSince <= -604800 && timeSince > -2592000){
cell.date.text = [NSString stringWithFormat:#"%.0f weeks ago", -timeSince/7/24/60/60];
}
else if (timeSince <= -2592000 && timeSince > -31536000){
cell.date.text = [NSString stringWithFormat:#"%.0f months ago", -timeSince/30/24/60/60];
}
else {
cell.date.text = [NSString stringWithFormat:#"%.1f years ago", -timeSince/365/24/60/60];
}

You can try with NSDateFormater and write it your self.
If value is under one minute then write just now, otherwise minutes, hours, days, etc.

https://stackoverflow.com/a/8268903/1915957
↑ convert swift code.
class func stringForTimeIntervalSinceCreated(dateTime :NSDate, serverTime serverDateTime:NSDate) -> String {
var MinInterval :Int = 0
var HourInterval :Int = 0
var DayInterval :Int = 0
var DayModules :Int = 0
let interval = abs(Int(dateTime.timeIntervalSinceDate(serverDateTime)))
if (interval >= 86400) {
DayInterval = interval/86400
DayModules = interval%86400
if (DayModules != 0) {
if (DayModules>=3600) {
//HourInterval=DayModules/3600;
return String(DayInterval) + " days"
} else {
if (DayModules >= 60) {
//MinInterval=DayModules/60;
return String(DayInterval) + " days"
} else {
return String(DayInterval) + " days"
}
}
} else {
return String(DayInterval) + " days"
}
} else {
if (interval >= 3600) {
HourInterval = interval/3600
return String(HourInterval) + " hours"
} else if (interval >= 60) {
MinInterval = interval/60
return String(MinInterval) + " minutes"
} else {
return String(interval) + " Sec"
}
}
}

+ (NSString *)changeTime:(NSString *)serverDateTime{
NSInteger MinInterval;
NSInteger HourInterval;
NSInteger DayInterval;
//NSInteger DayModules;
NSTimeInterval _interval=[serverDateTime doubleValue];
NSDate *Serverdate = [NSDate dateWithTimeIntervalSince1970:_interval];
NSInteger interval = (long)((NSInteger)[[NSDate date] timeIntervalSinceDate:Serverdate]);
if(interval >= 86400)
{
DayInterval = interval/86400;// no. of days
if (DayInterval > 14){
return [NSString stringWithFormat:#"w+"];
}
if (DayInterval >= 7 && DayInterval <= 14){
int diff = (int)DayInterval / 7;
return [NSString stringWithFormat:#"%iw",diff];
}
return [NSString stringWithFormat:#"%id",(int)DayInterval];
}
else{
if(interval>=3600)
{
HourInterval= interval/3600;
return [NSString stringWithFormat:#"%lih", (long)HourInterval];
}
else if(interval>=60){
MinInterval = interval/60;
return [NSString stringWithFormat:#"%lim", (long)MinInterval];
}
else{
return [NSString stringWithFormat:#"%lis", (long)interval];
}
return #"now";
}
}

if you have a problem with date and time.
you should think to this library
https://github.com/MatthewYork/DateTools
It always help!

You can use NSDate-TimeAgo. It can be installed in your project using CocoaPods.
Add the files to your project - manually or via Cocoapods (pod 'NSDate+TimeAgo')
Import the header using #import "NSDate+TimeAgo.h"
Use the library method timeAgo.

Related

how to convert value one format into the another format?

This is my Button method. When I press the button it's value is every time increment one & display into Label. Then it's reach 6 then convert like 1.0 , 7 = 1.1, 8 = 1.2 , 12 like 2.0 like cricket over format.
How can I do that?
-(void)OneNoBTNPressedMethod
{
// LBL it's my label & display the text
NSString * overStorage = LBL.text;
// perform the addition operation
CalcOperation operation;
operation = Plus;
//add one every time when we press the button
NSString * overOneBTNStr = [NSString stringWithFormat:#"1"];
NSString *overVal = overOneBTNStr;
LBL.text= [NSString stringWithFormat:#"%qi",[overVal longLongValue]+[overStorage longLongValue]];
}
Thanx in advance..
It worked for me. Hope it works for you as well. Assuming your LBL contains "1" as initial text. hope it helps
- OneNoBTNPressedMethod {
NSString *str = LBL.text;
NSArray *arr = [str componentsSeparatedByString:#"."];
if ([arr count] == 1) {
if ([LBL.text intValue] >= 5) {
LBL.text = [NSString stringWithFormat:#"%i.%i",0,0];
} else {
LBL.text = [NSString stringWithFormat:#"%i",[LBL.text intValue] + 1];
}
} else if ([arr count] == 2) {
if ([[arr objectAtIndex:1] intValue] >= 5) {
int left = [[arr objectAtIndex:0] intValue] + 1;
LBL.text = [NSString stringWithFormat:#"%i.%i",left,0];
} else {
LBL.text = [NSString stringWithFormat:#"%i.%i",[[arr objectAtIndex:0] intValue],[[arr objectAtIndex:1] intValue] + 1];
}
}
}
Try this logic
Let `int num` is count
Then
numBeforeDecimal = num/6;
numAfterDecimal = num%6;
Concatenate both number
[NSString stringWithFormat: #"%d.%d",numBeforeDecimal,numAfterDecimal];

how to get digits of a integer from NSString?

I am having a string like NSString *str = #"123".I want to fill the digits of this string into UIPickerView.But how to get the digits from this string?I added the following code
- (void)pickerView:(UIPickerView *)pickerView didSelectRow: (NSInteger)row inComponent:(NSInteger)component
{
int number = [str intValue];
if(component == 0)
{
}
else if(component == 1)
{
}
else
{
}
}
Please see this..
NSMutableArray *arrNumbers = [[NSMutableArray] alloc] initWithCapacity:[YOURSTRING length]];
for (i=0;i<[YOURSTRING length];i++)
{
  unichaar ch = [YOURSTRING characterAtIndex:i];
  NSLog(#"Processing charachter %c",ch);
  // If you really want
  [arrNumbers addObject:(id)ch];
}
Other solutions seem to be excessive, considering NSString is already an array of characters. More lightweight solution:
NSString *str = #"123";
for (int i = 0; i < [str length]; i++) {
int digit = [str characterAtIndex:i] - '0';
// do something with your digit
}
If you have it as a string you can just do
NSArray * digitStrings = [str componentsSeparatedByString:""];
And each element in the array would be a digit as a NSString.
not tested but you can give it a try, this is supposed to scan all numeric entries of your string.
-(NSArray*)getDigitsFromString:(NSString*)str{
NSMutableString *outpuString = [NSMutableString
stringWithCapacity:str.length];
NSScanner *scanner = [NSScanner scannerWithString:str];
NSCharacterSet *numbers = [NSCharacterSet
characterSetWithCharactersInString:#"0123456789"];
while ([scanner isAtEnd] == NO) {
NSString *buffer;
if ([scanner scanCharactersFromSet:numbers intoString:&buffer]) {
[outpuString appendString:buffer];
} else {
[scanner setScanLocation:([scanner scanLocation] + 1)];
}
}
NSArray * digitStr = [outpuString componentsSeparatedByString:#""];
return digitStr;
}
NSMutableArray * digit=[[NSMutableArray alloc]init];
NSString *string = #"123456";
for (int i=0;i<[string length]; i++) {
NSString * newString = [string substringWithRange:NSMakeRange(i, 1)];
[digit addObject:newString];
}
NSLog(#"String %# ", digit)
One more answer which addresses more the idea of the original question by solving the problem of separating an int into it's digits:
NSString *numberString = #"68243";
int result[numberString.length];
NSInteger number = [numberString integerValue];
int j = numberString.length - 1;
while (j >= 0)
{
int power = pow(10, j);
int rest = (number % power);
result[j] = (number - rest)/power;
number = rest;
j--;
}

Regex to extract minute and seconds

How can I extract minutes and seconds from a NSString? Examples:
3'15" or 3' 15" (3 minutes 15 seconds)
28" (28 seconds)
2' (2 minutes)
50 (default is in seconds, 50 seconds)
and stores into two NSIntegers?
Not entirely convinced that RegEx matching is the best way to read numbers out of a string, but here is a snippet that works:
NSString *str = #"12'34\"";
NSString *minutePattern = #"[[:digit:]]+'";
NSString *secondPattern = #"[[:digit:]]+\"?";
NSRange minuteRange = [str rangeOfString: minutePattern options: NSRegularExpressionSearch];
NSRange secondStartRange;
NSString *minuteString = #"";
if ( minuteRange.location != NSNotFound)
{
minuteString = [str substringWithRange: minuteRange];
NSUInteger secondStartPt = NSMaxRange(minuteRange);
secondStartRange = NSMakeRange(secondStartPt, str.length - secondStartPt);
}
else {
secondStartRange = NSMakeRange(0, str.length);
}
NSRange secondRange = [str rangeOfString: secondPattern
options: NSRegularExpressionSearch
range: secondStartRange];
NSString *secondString = #"";
if ( secondRange.location != NSNotFound)
{
secondString = [str substringWithRange: secondRange];
}
NSInteger minutes = [minuteString integerValue];
NSInteger seconds = [secondString integerValue];
NSLog(#"Minutes: %d, seconds: %d", minutes, seconds);
Note that it will parse a string like 5'21 as 5 minutes 21 seconds, not sure if that is what you want, but that can be fixed with an extra test.
NSArray *data = #[#"3'15\"", #"3' 15\"", #"28\"", #"2'", #"50"];
NSString *pattern = #"(\\d++')|(\\d++(\"{0,1})$)";
NSRegularExpression *regExp = [NSRegularExpression regularExpressionWithPattern:pattern
options:NSRegularExpressionCaseInsensitive
error:nil];
for (NSString *string in data) {
NSInteger mi = 0;
NSInteger ss = 0;
NSArray *match = [regExp matchesInString:string options:0 range:NSMakeRange(0,string.length)];
for (NSTextCheckingResult *result in match) {
NSString *value = [string substringWithRange:result.range];
if ([value hasSuffix:#"'"]) {
mi = [value integerValue];
} else {
ss = [value integerValue];
}
}
NSLog(#"%# - %d %d",string,mi,ss);
}

NSDate - timeIntevalSinceDate -

I have 2 text fields where users can insert 2 time (ie. 12.00pm and 15.00pm) and a label that return the hours (ie 3 hours). I'm using timeIntervalSinceDate but I'm getting it in seconds (10800 sec which is equal to 3 hours). How can I get the value in hours? here the code:
-(IBAction)calcoloBlockTime{
NSString *blockOff = [NSString stringWithFormat:#"%#", [offBlock text]];
NSString *blockIn= [NSString stringWithFormat: #"%#", [inBlock text]];
NSDateFormatter *dateFormatter =[[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"HHmm"];
NSDate *dateFromString = [dateFormatter dateFromString:blockOff];
NSDate *dateFromString2 = [dateFormatter dateFromString:blockIn];
NSLog(#"Time elapsed: %f", [dateFromString2 timeIntervalSinceDate:dateFromString]);
}
thanks in advance.
If you are only interested in hours you can write:
NSInteger hours = 10800 / 3600; // You know that in an hour there is 3600 seconds
If you want minutes etc you will continue with the result of 10800 modulus 3600, which will give you the seconds which are left after dividing it by 3600.
NSInteger temp = 10800 % 3600;
NSInteger minutes = temp / 60;
And to get the seconds left after this you write:
NSInteger seconds = minutes % 60;
EDIT
myLabel.text = [NSString stringWithFormat:#"%d hours", hours];
If you want to set the hours on the label.
hours = seconds / 3600; Simple!!! And, it seems there is no way to get the hour from NSDate. You can use NSDateComponents, but they are too costly for your requirement.
I made a class method that returns a string with a formatted date of the remaining time between an NSDate and now.
+(NSString *)TimeRemainingUntilDate:(NSDate *)date {
NSTimeInterval interval = [date timeIntervalSinceNow];
NSString * timeRemaining = nil;
if (interval > 0) {
div_t d = div(interval, 86400);
int day = d.quot;
div_t h = div(d.rem, 3600);
int hour = h.quot;
div_t m = div(h.rem, 60);
int min = m.quot;
NSString * nbday = nil;
if(day > 1)
nbday = #"days";
else if(day == 1)
nbday = #"day";
else
nbday = #"";
NSString * nbhour = nil;
if(hour > 1)
nbhour = #"hours";
else if (hour == 1)
nbhour = #"hour";
else
nbhour = #"";
NSString * nbmin = nil;
if(min > 1)
nbmin = #"mins";
else
nbmin = #"min";
timeRemaining = [NSString stringWithFormat:#"%#%# %#%# %#%#",day ? [NSNumber numberWithInt:day] : #"",nbday,hour ? [NSNumber numberWithInt:hour] : #"",nbhour,min ? [NSNumber numberWithInt:min] : #"",nbmin];
}
else
timeRemaining = #"Over";
return timeRemaining;
}

How can I verify if a String has a null value?

sorry but i'm still struggling to make this code working. It works if with a 2 digits number but it crashes with a single digit number. How can I verify if the NSString *secDigit has a value or is null. I hope my question is clear. Thanks in advance.
NSString *depositOverTotalRwy = [NSString stringWithFormat:#"%#", [deposit text]];
NSArray *components = [depositOverTotalRwy
componentsSeparatedByString:#"/"];
NSString *firstThird = [components objectAtIndex:0];
char firstChar = [firstThird characterAtIndex:0];
char secChar = [firstThird characterAtIndex:1];
NSString *firstDigit = [NSString stringWithFormat:#"%c",firstChar];
NSString *secDigit = [NSString stringWithFormat:#"%c", secChar];
NSLog(#" i'm %#", firstDigit);
NSLog(#" i'm %#", secDigit);
if ([firstDigit isEqualToString: #"1"]) {
firstDigit=#"wet";
NSLog(#"wet");
}
if ([firstDigit isEqualToString: #"2"]) {
firstDigit=#"wet";
NSLog(#"snow");
}
if ([firstDigit isEqualToString: #"3"]) {
firstDigit=#"wet";
NSLog(#"ice");
}
if ([secDigit isEqualToString: #"1"]) {
secDigit=#"wet";
NSLog(#"wet");
}
if ([secDigit isEqualToString: #"2"]) {
secDigit=#"snow";
NSLog(#"snow");
}
if ([secDigit isEqualToString: #"3"]) {
secDigit=#"ice";
NSLog(#"ice");
}
thanks to all of you..... here my code (working now):
NSString *depositOverTotalRwy = [NSString stringWithFormat:#"%#", [deposit text]];
NSArray *components = [depositOverTotalRwy
componentsSeparatedByString:#"/"];
NSString *firstThird = [components objectAtIndex:0];
char firstChar = [firstThird characterAtIndex:0];
NSString *firstDigit = [NSString stringWithFormat:#"%c",firstChar];
NSLog(#" i'm %#", firstDigit);
if ([firstDigit isEqualToString: #"1"]) {
firstDigit=#"wet";
NSLog(#"wet");
}
if ([firstDigit isEqualToString: #"2"]) {
firstDigit=#"wet";
NSLog(#"snow");
}
if ([firstDigit isEqualToString: #"3"]) {
firstDigit=#"wet";
NSLog(#"ice");
}
if ([firstThird length] >1) {
char secChar = [firstThird characterAtIndex:1];
NSString *secDigit = [NSString stringWithFormat:#"%c", secChar];
if ([secDigit isEqualToString: #"1"]) {
secDigit=#"wet";
NSLog(#"wet");
}
if ([secDigit isEqualToString: #"2"]) {
secDigit=#"snow";
NSLog(#"snow");
}
if ([secDigit isEqualToString: #"3"]) {
secDigit=#"ice";
NSLog(#"ice");
}
}
I guess you code crashes in this line:
char secChar = [firstThird characterAtIndex:1];
This is because you try to access a character outside of the string bounds. You need to guard against this by checking the length of the string first:
if ([firstThird count] > 1) {
// String has 2 or more characters, do all the stuff that involves
// a second character.
char secChar = [firstThird characterAtIndex:1];
NSString *secDigit = [NSString stringWithFormat:#"%c", secChar];
if ([secDigit isEqualToString: #"1"]) {
secDigit=#"wet";
NSLog(#"wet");
}
}
But I'd also like to recommend to not use an NSString here, as you already have a char. Just do something like this:
if ([firstThird count] > 1) {
// String has 2 or more characters, do all the stuff that involves
// a second character.
char secChar = [firstThird characterAtIndex:1];
if (secChar == '1') {
secDigit=#"wet";
NSLog(#"wet");
}
}
I think this is what you are looking for:
char secChar;
if(firstThird.length > 1)
{
secChar = [firstThird characterAtIndex:1];
}
According to this
http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html
NSString "Raises an NSRangeException if index lies beyond the end of the receiver"
So, your code:
char secChar = [firstThird characterAtIndex:1];
Is the problem (you should see that in the debugger Console)
Check the length first with
if ([firstThird length] < 2) {
// handle the case where it is one digit
}
You can check number of characters in a string using NSString length. and modify your code
as
NSString *depositOverTotalRwy = [NSString stringWithFormat:#"%#", #"23"];
NSArray *components = [depositOverTotalRwy
componentsSeparatedByString:#"/"];
NSString *firstThird = [components objectAtIndex:0];
unichar firstChar;
unichar secChar;
if([firstThird length]>1){
firstChar = [firstThird characterAtIndex:0];
secChar = [firstThird characterAtIndex:1];
} else {
firstChar = [firstThird characterAtIndex:0];
secChar = 0;
}
switch (firstChar) {
case '1': /* Do your stuff*/break;
case '2': /* Do your stuff*/break;
case '3': /* Do your stuff*/break;
default:
break;
}
switch (secChar) {
case '1': /* Do your stuff*/break;
case '2': /* Do your stuff*/break;
case '3': /* Do your stuff*/break;
default:
break;
}
you can use unichar instead of char. And can perform check in switch statements.
If you use char, a casting is done from unichar to char and for some characters you may lose actual value. So it is safe to use unichar...
If you want to convert unichar to string simply code
NSString * stringChar = [NSString StringWithFormat:#"%C",unicharVariable];
Thats it ...