Filed under: Useful Code

UILabel Vertical / Bottom Align

I find it hard to believe that Apple when developing the iOS SDK, did not take into account that users may wish to align label text, either to the top or the bottom of a label. Instead they simply give the option of aligning it to the center, as shown below:

20090628-jkf727u2wsbsrgfhep3ja

This code allows you to align text either to the top or the bottom of a UILabel

I hope this helps someone else struggling with this issue, maybe it will be fixed in iOS 5.

Human Readable Dates

Humans (thats you and I) don't think mathematically. Sometimes it is necessary to present them values in a natural format. This is especially relevant to date values, if I were to say to you "My birthday is on the 24th of April" (which it actually is!), it would take you time to compute how far in the future (or the past as the case may be) this is. If I were to say to you "My birthday is in 13 days" (at the time of writing this), it would aid your comprehension of when this event occurs.

As developers we have a responsibility to the users of our products to make their life as easy as possible; however many developers insist on displaying dates and times in rigid formats. Of course, rigid formats do have their uses, if I were developing a transactional based system for use in the banking industry, and I were displaying a large list of transactions to the user, then it is necessary to display the exact date and time on which a particular transaction occurred.

However, if I am writing a comment system for a blog, then I don't need to give the same level of detail, why display the date and time an item was posted to a user and make them calculate how long ago the post was made relevant to the current date and time? This is where human readable dates come in, as humans our brains process time spans a lot better than we do dates; if I were to state "A comment was posted on my blog 18 minutes ago" the human brain can digest this information readily, as it involves no calculations. The below class allows us to process DateTime values into human readable values. I would like to state this is not my code, I downloaded it from the internet some time ago, unfortunately I can't remember where it was downloaded from and thus cannot give credit to the original author; I have simply modified the code to make use of Generic's and make it compatible with version 4 of the .NET framework.

We can now use this class in our application:

I have attached an image showing the output from this example application.

Screen_shot_2011-04-11_at_23

NSDate - Zero Out Seconds

I recently had a scenario where I was getting the current date using:

Now in many scenarios, this code will work perfectly, but the issue I had was I was performing some quite advanced calculations on the date, and the date contained a value for seconds, which threw my calculations off a little, because I hadn't factored seconds into my equations.

The following code, when passed a NSDate object will 'zero' out the second value, leaving you with an absolute value;

Useful NSDate Functions

I often find that I have to create dates based upon other dates. NSDate doesn't allow for the easy creation of dates; for example, what if you wanted to create a date which was exactly 5 minutes from now? It would require quite complex code to be wrote each time you wanted to create the date.
So I wrote this simple class which takes the some pain away from date manipulation within Objective-C.

 
// 
// DateFunctions.h 
// 
// Created by Mick Walker on 26/06/2010. 
// Copyright 2010 Mick Walker. All rights reserved. 
// 
#import <Foundation/Foundation.h> 
@interface DateFunctions : NSObject { 
} 
+ (NSDate *) dateWithDaysFromNow: (NSUInteger) days; 
+ (NSDate *) dateWithDaysBeforeNow: (NSUInteger) days; 
+ (NSDate *) dateWithHoursFromNow: (NSUInteger) dHours; 
+ (NSDate *) dateWithHoursBeforeNow: (NSUInteger) dHours; 
+ (NSDate *) dateWithMinutesFromNow: (NSUInteger) dMinutes; 
+ (NSDate *) dateWithMinutesBeforeNow: (NSUInteger) dMinutes; 
+ (NSDate *) dateTomorrow; 
+ (NSDate *) dateYesterday; 
+ (NSDate *) dateWithDaysFromDate:(NSDate *) date numberOfDays:(NSUInteger) days; 
+ (NSDate *) dateWithDaysBeforeDate:(NSDate *) date numberOfDays:(NSUInteger) days; 
+ (NSDate *) dateWithHoursFromDate:(NSDate *) date numberOfHours:(NSUInteger) hours; 
+ (NSDate *) dateWithHoursBeforeDate:(NSDate *) date numberOfHours:(NSUInteger) hours; 
+ (NSDate *) dateWithMinutesFromDate:(NSDate *) date numberOfMinutes:(NSUInteger) mins; 
+ (NSDate *) dateWithMinutesBeforeDate:(NSDate *) date numberOfMinutes:(NSUInteger) mins; 
+ (BOOL) isDateToday:(NSDate *) date; 
+ (NSInteger) numberOfDaysAway:(NSDate *) date; 
@end 
 
// 
// DateFunctions.m 
// 
// Created by Mick Walker on 26/06/2010. 
// Copyright 2010 Mick Walker. All rights reserved. 
// 
#import "DateFunctions.h" 
 
#define D_MINUTE 60 
#define D_HOUR 3600 
#define D_DAY 86400 
#define D_WEEK 604800 
#define D_YEAR 31556926 
 
#define DATE_COMPONENTS (NSYearCalendarUnit| NSMonthCalendarUnit | NSDayCalendarUnit | NSWeekCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSWeekdayCalendarUnit | NSWeekdayOrdinalCalendarUnit) 
#define CURRENT_CALENDAR [NSCalendar currentCalendar] 
@implementation DateFunctions 
+ (NSDate *) dateWithDaysFromNow: (NSUInteger) days 
{ 
 NSTimeInterval aTimeInterval = [[NSDate date] 
 timeIntervalSinceReferenceDate] + D_DAY * days; 
 NSDate *newDate = [NSDate 
 dateWithTimeIntervalSinceReferenceDate:aTimeInterval]; 
 return newDate; 
} 
 
+ (NSDate *) dateWithDaysBeforeNow: (NSUInteger) days 
{ 
 NSTimeInterval aTimeInterval = [[NSDate date] 
 timeIntervalSinceReferenceDate] - D_DAY * days; 
 NSDate *newDate = [NSDate 
 dateWithTimeIntervalSinceReferenceDate:aTimeInterval]; 
 return newDate; 
} 
 
+ (NSDate *) dateWithHoursFromNow: (NSUInteger) dHours 
{ 
 NSTimeInterval aTimeInterval = [[NSDate date] 
 timeIntervalSinceReferenceDate] + D_HOUR * dHours; 
 NSDate *newDate = [NSDate 
 dateWithTimeIntervalSinceReferenceDate:aTimeInterval]; 
 return newDate; 
} 
 
+ (NSDate *) dateWithHoursBeforeNow: (NSUInteger) dHours 
{ 
 NSTimeInterval aTimeInterval = [[NSDate date] 
 timeIntervalSinceReferenceDate] - D_HOUR * dHours; 
 NSDate *newDate = [NSDate 
 dateWithTimeIntervalSinceReferenceDate:aTimeInterval]; 
 return newDate; 
} 
 
+ (NSDate *) dateWithMinutesFromNow: (NSUInteger) dMinutes 
{ 
 NSTimeInterval aTimeInterval = [[NSDate date] 
 timeIntervalSinceReferenceDate] + D_MINUTE * dMinutes; 
 NSDate *newDate = [NSDate 
 dateWithTimeIntervalSinceReferenceDate:aTimeInterval]; 
 return newDate; } 
 
+ (NSDate *) dateWithMinutesBeforeNow: (NSUInteger) dMinutes 
{ 
 NSTimeInterval aTimeInterval = [[NSDate date] 
 timeIntervalSinceReferenceDate] - D_MINUTE * dMinutes; 
 NSDate *newDate = [NSDate 
 dateWithTimeIntervalSinceReferenceDate:aTimeInterval]; 
 return newDate; } 
 
+ (NSDate *) dateTomorrow 
{ 
 return [self dateWithDaysFromNow:1]; 
} 
 
+ (NSDate *) dateYesterday 
{ 
 return [self dateWithDaysBeforeNow:1]; 
} 
 
+ (NSDate *) dateWithDaysFromDate:(NSDate *) date numberOfDays:(NSUInteger) days { 
 NSTimeInterval aTimeInterval = [date 
 timeIntervalSinceReferenceDate] + D_DAY * days; 
 NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval]; 
 return newDate; 
} 
 
+ (NSDate *) dateWithDaysBeforeDate:(NSDate *) date numberOfDays:(NSUInteger) days { 
 NSTimeInterval aTimeInterval = [date timeIntervalSinceReferenceDate] - D_DAY * days; 
 NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval]; 
 return newDate; 
} 
// 
+ (NSDate *) dateWithHoursFromDate:(NSDate *) date numberOfHours:(NSUInteger) hours { 
 
 NSTimeInterval aTimeInterval = [date timeIntervalSinceReferenceDate] + D_HOUR * hours; 
 NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval]; 
 return newDate; 
} 
 
+ (NSDate *) dateWithHoursBeforeDate:(NSDate *) date numberOfHours:(NSUInteger) hours { 
 NSTimeInterval aTimeInterval = [date timeIntervalSinceReferenceDate] - D_HOUR * hours; 
 NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval]; 
 return newDate; 
} 
 
+ (NSDate *) dateWithMinutesFromDate:(NSDate *) date numberOfMinutes:(NSUInteger) mins { 
 NSTimeInterval aTimeInterval = [date timeIntervalSinceReferenceDate] + D_MINUTE * mins; 
 NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval]; 
 return newDate; 
} 
+ (NSDate *) dateWithMinutesBeforeDate:(NSDate *) date numberOfMinutes:(NSUInteger) mins { 
 NSTimeInterval aTimeInterval = [date timeIntervalSinceReferenceDate] - D_MINUTE * mins; 
 NSDate *newDate = [NSDate dateWithTimeIntervalSinceReferenceDate:aTimeInterval]; 
 return newDate; 
} 
 
+ (BOOL) isDateToday:(NSDate *) date { 
 NSDateComponents *otherDay = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:date]; 
 NSDateComponents *today = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit fromDate:[NSDate date]]; 
 if([today day] == [otherDay day] && 
 [today month] == [otherDay month] && 
 [today year] == [otherDay year]) { 
 //do stuff 
 return YES; 
 } 
 return NO; 
 
} 
+ (NSInteger) numberOfDaysAway:(NSDate *) date { 
 return 1; 
} 
 
@end 

I hope this helps someone else.