├── NSDate+Helper.podspec.json ├── NSDate+Helper.h ├── README.textile └── NSDate+Helper.m /NSDate+Helper.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "NSDate+Helper", 3 | "version": "1.0.4", 4 | "summary": "A category to extend Cocoa's NSDate class with some convenience functions.", 5 | "description": "This is a category for the NSDate class that provides some convenience methods for working with NSDate objects and displaying formatted and relative strings.", 6 | "homepage": "https://github.com/billymeltdown/nsdate-helper", 7 | "social_media_url": "https://twitter.com/billymeltdown", 8 | "license": { 9 | "type": "Modified BSD License", 10 | "text": "Copyright © 2009-2016, ZETETIC LLC\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\nRedistributions in binary form must reproduce the above copyright\nnotice, this list of conditions and the following disclaimer in the\ndocumentation and/or other materials provided with the distribution.\nNeither the name of the ZETETIC LLC nor the\nnames of its contributors may be used to endorse or promote products\nderived from this software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY ZETETIC LLC ‘’AS IS’’ AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 11 | }, 12 | "authors": { 13 | "William Gray": "wgray@zetetic.net" 14 | }, 15 | "source": { 16 | "git": "https://github.com/billymeltdown/nsdate-helper.git", 17 | "tag": "1.0.4" 18 | }, 19 | "source_files": "NSDate+Helper.{h,m}", 20 | "requires_arc": false 21 | } 22 | -------------------------------------------------------------------------------- /NSDate+Helper.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+Helper.h 3 | // 4 | // Created by Billy Gray on 2/26/09. 5 | // Copyright (c) 2009, 2010, ZETETIC LLC 6 | // All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // * Redistributions of source code must retain the above copyright 11 | // notice, this list of conditions and the following disclaimer. 12 | // * Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // * Neither the name of the ZETETIC LLC nor the 16 | // names of its contributors may be used to endorse or promote products 17 | // derived from this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY 20 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | // DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY 23 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | 31 | #import 32 | 33 | @interface NSDate (Helper) 34 | 35 | + (void)initializeStatics; 36 | 37 | + (NSCalendar *)sharedCalendar; 38 | + (NSDateFormatter *)sharedDateFormatter; 39 | - (NSUInteger)daysAgo; 40 | - (NSUInteger)daysAgoAgainstMidnight; 41 | - (NSString *)stringDaysAgo; 42 | - (NSString *)stringDaysAgoAgainstMidnight:(BOOL)flag; 43 | - (NSUInteger)weekday; 44 | - (NSUInteger)weekNumber; 45 | - (NSUInteger)hour; 46 | - (NSUInteger)minute; 47 | - (NSUInteger)second; 48 | - (NSUInteger)day; 49 | - (NSUInteger)month; 50 | - (NSUInteger)year; 51 | - (long int)utcTimeStamp; //full seconds since 52 | + (NSDate *)dateFromString:(NSString *)string; 53 | + (NSDate *)dateFromString:(NSString *)string withFormat:(NSString *)format; 54 | + (NSString *)stringFromDate:(NSDate *)date withFormat:(NSString *)string; 55 | + (NSString *)stringFromDate:(NSDate *)date; 56 | + (NSString *)stringForDisplayFromDate:(NSDate *)date; 57 | + (NSString *)stringForDisplayFromDate:(NSDate *)date prefixed:(BOOL)prefixed; 58 | + (NSString *)stringForDisplayFromDate:(NSDate *)date prefixed:(BOOL)prefixed alwaysDisplayTime:(BOOL)displayTime; 59 | - (NSString *)string; 60 | - (NSString *)stringWithFormat:(NSString *)format; 61 | - (NSString *)stringWithDateStyle:(NSDateFormatterStyle)dateStyle timeStyle:(NSDateFormatterStyle)timeStyle; 62 | - (NSDate *)beginningOfWeek; 63 | - (NSDate *)beginningOfDay; 64 | - (NSDate *)endOfWeek; 65 | + (NSString *)dateFormatString; 66 | + (NSString *)timeFormatString; 67 | + (NSString *)timestampFormatString; 68 | + (NSString *)dbFormatString; 69 | 70 | + (Boolean)using12hClockFormat; 71 | @end 72 | -------------------------------------------------------------------------------- /README.textile: -------------------------------------------------------------------------------- 1 | h2. NSDate (Helper) 2 | 3 | This is a category for the @NSDate@ class that provides some convenience methods for working with @NSDate@ objects and displaying formatted and relative strings. 4 | 5 | More information can be found at my "initial blog post":http://www.zetetic.net/blog/2009/3/11/nsdate-helper.html. 6 | 7 | Anyone is welcome to use it for anything, and to change it as they see fit. If you'd like to contribute back any changes (woot!), please fork and send a pull request! 8 | 9 | h3. Usage 10 | 11 | Full documentation is now up "on the Github wiki for this project":http://wiki.github.com/billymeltdown/nsdate-helper. It's a lot better than this kinda rambling overview here. 12 | 13 | Two convenience methods make it easy for you to display some relative date information. @stringForDisplayFromDate@ gives you the kind of relative format you see in the Notes listing on the iPhone: 14 | 15 |

16 |   NSString *displayString = [NSDate stringForDisplayFromDate:date];
17 | 
18 | 19 | This produces the following kinds of output: 20 | 21 | * '3:42 AM' - if the date is after midnight today 22 | * 'Tuesday' - if the date is within the last seven days 23 | * 'Mar 1' - if the date is within the current calendar year 24 | * 'Mar 1, 2008' - else ;-) 25 | 26 |

27 |   NSString *displayString = [NSDate stringForDisplayFromDate:date prefixed:YES];
28 | 
29 | 30 | This produces the same as above, but prefixed with 'at' or 'on' depending on the appropriate English syntax. 31 | 32 | Another set of methods provide days-ago information: 33 | 34 |

35 |   NSDate *date = [NSDate date];
36 |   [date daysAgo]; // provides an NSComponent-based NSUInteger describing days ago.
37 |   [date daysAgoAgainstMidnight]; // better version of daysAgo, works off midnight (hat-tip: "sburlot":http://github.com/sburlot)
38 |   [date stringDaysAgo]; // 'Today', 'Yesterday', or 'N days ago'.
39 | 
40 | 41 | Tired of creating and releasing date formatters? Missing things like @to_s(:db)@? Me, too. @NSDate (Helper)@ has some static methods to make going back and forth between strings and dates a little less painful, and particularly easier when working with database timestamps (a la SQLite): 42 | 43 |

44 |   NSDate *date = [NSDate dateFromString:@"2009-03-01 12:15:23"];
45 |   NSString *dbDateString = [NSDate stringFromDate:date]; // returns '2009-03-01 12:15:23'
46 | 
47 | 48 | Who needs NSDateFormatter? 49 | 50 |

51 |   NSString *otherDateString = [NSDate stringFromDate:date withFormat:@"EEEE"]; // use any format you like
52 | 
53 | 54 | h3. Installation 55 | 56 | To use it in your Cocoa project, import the header and implementation files, and then add the header to your project's _prefix.pch file so that it's available across your project: 57 | 58 |

59 | #ifdef __OBJC__
60 |     #import 
61 |     #import 
62 |     #import "NSDate+Helper.h"
63 | #endif
64 | 
65 | 66 | h3. License 67 | 68 | Copyright (c) 2009, 2010, ZETETIC LLC 69 | All rights reserved. 70 | 71 | Redistribution and use in source and binary forms, with or without 72 | modification, are permitted provided that the following conditions are met: 73 | * Redistributions of source code must retain the above copyright 74 | notice, this list of conditions and the following disclaimer. 75 | * Redistributions in binary form must reproduce the above copyright 76 | notice, this list of conditions and the following disclaimer in the 77 | documentation and/or other materials provided with the distribution. 78 | * Neither the name of the ZETETIC LLC nor the 79 | names of its contributors may be used to endorse or promote products 80 | derived from this software without specific prior written permission. 81 | 82 | THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY 83 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 84 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 85 | DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY 86 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 87 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 88 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 89 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 90 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 91 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 92 | 93 | -------------------------------------------------------------------------------- /NSDate+Helper.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDate+Helper.m 3 | // 4 | // Created by Billy Gray on 2/26/09. 5 | // Copyright (c) 2009–2012, ZETETIC LLC 6 | // All rights reserved. 7 | // 8 | // Redistribution and use in source and binary forms, with or without 9 | // modification, are permitted provided that the following conditions are met: 10 | // * Redistributions of source code must retain the above copyright 11 | // notice, this list of conditions and the following disclaimer. 12 | // * Redistributions in binary form must reproduce the above copyright 13 | // notice, this list of conditions and the following disclaimer in the 14 | // documentation and/or other materials provided with the distribution. 15 | // * Neither the name of the ZETETIC LLC nor the 16 | // names of its contributors may be used to endorse or promote products 17 | // derived from this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY ZETETIC LLC ''AS IS'' AND ANY 20 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | // DISCLAIMED. IN NO EVENT SHALL ZETETIC LLC BE LIABLE FOR ANY 23 | // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 | // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | // 30 | 31 | #import "NSDate+Helper.h" 32 | 33 | static NSString *kNSDateHelperFormatFullDateWithTime = @"MMM d, yyyy h:mm a"; 34 | static NSString *kNSDateHelperFormatFullDate = @"MMM d, yyyy"; 35 | static NSString *kNSDateHelperFormatShortDateWithTime = @"MMM d h:mm a"; 36 | static NSString *kNSDateHelperFormatShortDate = @"MMM d"; 37 | static NSString *kNSDateHelperFormatWeekday = @"EEEE"; 38 | static NSString *kNSDateHelperFormatWeekdayWithTime = @"EEEE h:mm a"; 39 | static NSString *kNSDateHelperFormatTime = @"h:mm a"; 40 | static NSString *kNSDateHelperFormatTime24Hour = @"HH:mm"; 41 | static NSString *kNSDateHelperFormatTimeWithPrefix = @"'at' h:mm a"; 42 | static NSString *kNSDateHelperFormatSQLDate = @"yyyy-MM-dd"; 43 | static NSString *kNSDateHelperFormatSQLTime = @"HH:mm:ss"; 44 | static NSString *kNSDateHelperFormatSQLDateWithTime = @"yyyy-MM-dd HH:mm:ss"; 45 | 46 | @implementation NSDate (Helper) 47 | 48 | static NSCalendar *_calendar = nil; 49 | static NSDateFormatter *_displayFormatter = nil; 50 | 51 | + (Boolean)using12hClockFormat { 52 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 53 | [formatter setLocale:[NSLocale currentLocale]]; 54 | [formatter setDateStyle:NSDateFormatterNoStyle]; 55 | [formatter setTimeStyle:NSDateFormatterShortStyle]; 56 | NSString *dateString = [formatter stringFromDate:[NSDate date]]; 57 | NSRange amRange = [dateString rangeOfString:[formatter AMSymbol]]; 58 | NSRange pmRange = [dateString rangeOfString:[formatter PMSymbol]]; 59 | BOOL is24h = (amRange.location == NSNotFound && pmRange.location == NSNotFound); 60 | [formatter release]; 61 | return !is24h; 62 | } 63 | 64 | + (void)initializeStatics { 65 | static dispatch_once_t onceToken; 66 | dispatch_once(&onceToken, ^{ 67 | @autoreleasepool { 68 | if (_calendar == nil) { 69 | #if __has_feature(objc_arc) 70 | _calendar = [NSCalendar currentCalendar]; 71 | #else 72 | _calendar = [[NSCalendar currentCalendar] retain]; 73 | #endif 74 | } 75 | if (_displayFormatter == nil) { 76 | _displayFormatter = [[NSDateFormatter alloc] init]; 77 | } 78 | } 79 | }); 80 | } 81 | 82 | + (NSCalendar *)sharedCalendar { 83 | [self initializeStatics]; 84 | return _calendar; 85 | } 86 | 87 | + (NSDateFormatter *)sharedDateFormatter { 88 | [self initializeStatics]; 89 | return _displayFormatter; 90 | } 91 | 92 | /* 93 | * This guy can be a little unreliable and produce unexpected results, 94 | * you're better off using daysAgoAgainstMidnight 95 | */ 96 | - (NSUInteger)daysAgo { 97 | NSCalendar *calendar = [[self class] sharedCalendar]; 98 | NSDateComponents *components = [calendar components:(NSCalendarUnitDay) 99 | fromDate:self 100 | toDate:[NSDate date] 101 | options:0]; 102 | return [components day]; 103 | } 104 | 105 | - (NSUInteger)daysAgoAgainstMidnight { 106 | // get a midnight version of ourself: 107 | NSDateFormatter *mdf = [[self class] sharedDateFormatter]; 108 | [mdf setDateFormat:@"yyyy-MM-dd"]; 109 | NSDate *midnight = [mdf dateFromString:[mdf stringFromDate:self]]; 110 | return (int)[midnight timeIntervalSinceNow] / (60*60*24) *-1; 111 | } 112 | 113 | - (NSString *)stringDaysAgo { 114 | return [self stringDaysAgoAgainstMidnight:YES]; 115 | } 116 | 117 | - (NSString *)stringDaysAgoAgainstMidnight:(BOOL)flag { 118 | NSUInteger daysAgo = (flag) ? [self daysAgoAgainstMidnight] : [self daysAgo]; 119 | NSString *text = nil; 120 | switch (daysAgo) { 121 | case 0: 122 | text = NSLocalizedString(@"Today", nil); 123 | break; 124 | case 1: 125 | text = NSLocalizedString(@"Yesterday", nil); 126 | break; 127 | default: 128 | text = [NSString stringWithFormat:@"%d days ago", (int)daysAgo]; 129 | } 130 | return text; 131 | } 132 | 133 | - (NSUInteger)hour { 134 | NSCalendar *calendar = [[self class] sharedCalendar]; 135 | NSDateComponents *weekdayComponents = [calendar components:(NSCalendarUnitHour) fromDate:self]; 136 | return [weekdayComponents hour]; 137 | } 138 | 139 | - (NSUInteger)minute { 140 | NSCalendar *calendar = [[self class] sharedCalendar]; 141 | NSDateComponents *weekdayComponents = [calendar components:(NSCalendarUnitMinute) fromDate:self]; 142 | return [weekdayComponents minute]; 143 | } 144 | 145 | - (NSUInteger)year { 146 | NSCalendar *calendar = [[self class] sharedCalendar]; 147 | NSDateComponents *weekdayComponents = [calendar components:(NSCalendarUnitYear) fromDate:self]; 148 | return [weekdayComponents year]; 149 | } 150 | - (NSUInteger)month { 151 | NSCalendar *calendar = [[self class] sharedCalendar]; 152 | NSDateComponents *weekdayComponents = [calendar components:(NSCalendarUnitMonth) fromDate:self]; 153 | return [weekdayComponents month]; 154 | } 155 | 156 | - (NSUInteger)day { 157 | NSCalendar *calendar = [[self class] sharedCalendar]; 158 | NSDateComponents *weekdayComponents = [calendar components:(NSCalendarUnitDay) fromDate:self]; 159 | return [weekdayComponents day]; 160 | } 161 | - (NSUInteger)second { 162 | NSCalendar *calendar = [[self class] sharedCalendar]; 163 | NSDateComponents *weekdayComponents = [calendar components:(NSCalendarUnitSecond) fromDate:self]; 164 | return [weekdayComponents second]; 165 | } 166 | 167 | - (long int)utcTimeStamp{ 168 | return lround(floor([self timeIntervalSince1970])); 169 | } 170 | 171 | - (NSUInteger)weekday { 172 | NSDateComponents *weekdayComponents = [[[self class] sharedCalendar] components:(NSCalendarUnitWeekday) fromDate:self]; 173 | return [weekdayComponents weekday]; 174 | } 175 | 176 | - (NSUInteger)weekNumber { 177 | NSCalendar *calendar = [[self class] sharedCalendar]; 178 | NSDateComponents *dateComponents = [calendar components:(NSCalendarUnitWeekOfMonth) fromDate:self]; 179 | return [dateComponents weekOfMonth]; 180 | } 181 | 182 | + (NSDate *)dateFromString:(NSString *)string { 183 | return [NSDate dateFromString:string withFormat:[NSDate dbFormatString]]; 184 | } 185 | 186 | + (NSDate *)dateFromString:(NSString *)string withFormat:(NSString *)format { 187 | NSDateFormatter *formatter = [self sharedDateFormatter]; 188 | [formatter setDateFormat:format]; 189 | NSDate *date = [formatter dateFromString:string]; 190 | return date; 191 | } 192 | 193 | + (NSString *)stringFromDate:(NSDate *)date withFormat:(NSString *)format { 194 | return [date stringWithFormat:format]; 195 | } 196 | 197 | + (NSString *)stringFromDate:(NSDate *)date { 198 | return [date string]; 199 | } 200 | 201 | + (NSString *)stringForDisplayFromDate:(NSDate *)date prefixed:(BOOL)prefixed alwaysDisplayTime:(BOOL)displayTime { 202 | /* 203 | * if the date is in today, display 12-hour time with meridian, 204 | * if it is within the last 7 days, display weekday name (Friday) 205 | * if within the calendar year, display as Jan 23 206 | * else display as Nov 11, 2008 207 | */ 208 | NSDate *today = [NSDate date]; 209 | NSDateComponents *offsetComponents = [[self sharedCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) 210 | fromDate:today]; 211 | NSDate *midnight = [[self sharedCalendar] dateFromComponents:offsetComponents]; 212 | NSString *displayString = nil; 213 | // comparing against midnight 214 | NSComparisonResult midnight_result = [date compare:midnight]; 215 | if (midnight_result == NSOrderedDescending) { 216 | if (prefixed) { 217 | [[self sharedDateFormatter] setDateFormat:kNSDateHelperFormatTimeWithPrefix]; // at 11:30 am 218 | } else { 219 | if ([self using12hClockFormat]) { 220 | [[self sharedDateFormatter] setDateFormat:kNSDateHelperFormatTime]; // 11:30 am 04:30 pm 221 | } else { 222 | [[self sharedDateFormatter] setDateFormat:kNSDateHelperFormatTime24Hour]; // 16:30 223 | } 224 | 225 | } 226 | } else { 227 | // check if date is within last 7 days 228 | NSDateComponents *componentsToSubtract = [[NSDateComponents alloc] init]; 229 | [componentsToSubtract setDay:-7]; 230 | NSDate *lastweek = [[self sharedCalendar] dateByAddingComponents:componentsToSubtract toDate:today options:0]; 231 | #if !__has_feature(objc_arc) 232 | [componentsToSubtract release]; 233 | #endif 234 | NSComparisonResult lastweek_result = [date compare:lastweek]; 235 | if (lastweek_result == NSOrderedDescending) { 236 | if (displayTime) { 237 | [[self sharedDateFormatter] setDateFormat:kNSDateHelperFormatWeekdayWithTime]; 238 | } else { 239 | [[self sharedDateFormatter] setDateFormat:kNSDateHelperFormatWeekday]; // Tuesday 240 | } 241 | } else { 242 | // check if same calendar year 243 | NSInteger thisYear = [offsetComponents year]; 244 | NSDateComponents *dateComponents = [[self sharedCalendar] components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) 245 | fromDate:date]; 246 | NSInteger thatYear = [dateComponents year]; 247 | if (thatYear >= thisYear) { 248 | if (displayTime) { 249 | [[self sharedDateFormatter] setDateFormat:kNSDateHelperFormatShortDateWithTime]; 250 | } 251 | else { 252 | [[self sharedDateFormatter] setDateFormat:kNSDateHelperFormatShortDate]; 253 | } 254 | } else { 255 | if (displayTime) { 256 | [[self sharedDateFormatter] setDateFormat:kNSDateHelperFormatFullDateWithTime]; 257 | } 258 | else { 259 | [[self sharedDateFormatter] setDateFormat:kNSDateHelperFormatFullDate]; 260 | } 261 | } 262 | } 263 | if (prefixed) { 264 | NSString *dateFormat = [[self sharedDateFormatter] dateFormat]; 265 | NSString *prefix = @"'on' "; 266 | [[self sharedDateFormatter] setDateFormat:[prefix stringByAppendingString:dateFormat]]; 267 | } 268 | } 269 | // use display formatter to return formatted date string 270 | displayString = [[self sharedDateFormatter] stringFromDate:date]; 271 | return displayString; 272 | } 273 | 274 | + (NSString *)stringForDisplayFromDate:(NSDate *)date prefixed:(BOOL)prefixed { 275 | return [[self class] stringForDisplayFromDate:date prefixed:prefixed alwaysDisplayTime:NO]; 276 | } 277 | 278 | + (NSString *)stringForDisplayFromDate:(NSDate *)date { 279 | return [self stringForDisplayFromDate:date prefixed:NO]; 280 | } 281 | 282 | - (NSString *)stringWithFormat:(NSString *)format { 283 | [[self class] initializeStatics]; 284 | [[[self class] sharedDateFormatter] setDateFormat:format]; 285 | NSString *timestamp_str = [[[self class] sharedDateFormatter] stringFromDate:self]; 286 | return timestamp_str; 287 | } 288 | 289 | - (NSString *)stringWithFormatISO8601; { 290 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 291 | NSLocale *enUSPOSIXLocale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"]; 292 | [dateFormatter setLocale:enUSPOSIXLocale]; 293 | [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"]; 294 | NSString *outputString = [dateFormatter stringFromDate:self]; 295 | #if !__has_feature(objc_arc) 296 | [dateFormatter release]; 297 | #endif 298 | return outputString; 299 | } 300 | 301 | - (NSString *)string { 302 | return [self stringWithFormat:[NSDate dbFormatString]]; 303 | } 304 | 305 | - (NSString *)stringWithDateStyle:(NSDateFormatterStyle)dateStyle timeStyle:(NSDateFormatterStyle)timeStyle { 306 | [[[self class] sharedDateFormatter] setDateStyle:dateStyle]; 307 | [[[self class] sharedDateFormatter] setTimeStyle:timeStyle]; 308 | NSString *outputString = [[[self class] sharedDateFormatter] stringFromDate:self]; 309 | return outputString; 310 | } 311 | 312 | - (NSDate *)beginningOfWeek { 313 | // largely borrowed from "Date and Time Programming Guide for Cocoa" 314 | // we'll use the default calendar and hope for the best 315 | NSCalendar *calendar = [[self class] sharedCalendar]; 316 | NSDate *beginningOfWeek = nil; 317 | BOOL ok = [calendar rangeOfUnit:NSCalendarUnitWeekOfMonth startDate:&beginningOfWeek 318 | interval:NULL forDate:self]; 319 | if (ok) { 320 | return beginningOfWeek; 321 | } 322 | // couldn't calc via range, so try to grab Sunday, assuming gregorian style 323 | // Get the weekday component of the current date 324 | NSDateComponents *weekdayComponents = [calendar components:NSCalendarUnitWeekOfMonth fromDate:self]; 325 | /* 326 | Create a date components to represent the number of days to subtract from the current date. 327 | The weekday value for Sunday in the Gregorian calendar is 1, so subtract 1 from the number of days to subtract from the date in question. (If today's Sunday, subtract 0 days.) 328 | */ 329 | NSDateComponents *componentsToSubtract = [[NSDateComponents alloc] init]; 330 | [componentsToSubtract setDay: 0 - ([weekdayComponents weekday] - 1)]; 331 | beginningOfWeek = nil; 332 | beginningOfWeek = [calendar dateByAddingComponents:componentsToSubtract toDate:self options:0]; 333 | #if !__has_feature(objc_arc) 334 | [componentsToSubtract release]; 335 | #endif 336 | //normalize to midnight, extract the year, month, and day components and create a new date from those components. 337 | NSDateComponents *components = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) 338 | fromDate:beginningOfWeek]; 339 | return [calendar dateFromComponents:components]; 340 | } 341 | 342 | - (NSDate *)beginningOfDay { 343 | NSCalendar *calendar = [[self class] sharedCalendar]; 344 | // Get the weekday component of the current date 345 | NSDateComponents *components = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) 346 | fromDate:self]; 347 | return [calendar dateFromComponents:components]; 348 | } 349 | 350 | - (NSDate *)endOfWeek { 351 | NSCalendar *calendar = [[self class] sharedCalendar]; 352 | // Get the weekday component of the current date 353 | NSDateComponents *weekdayComponents = [calendar components:NSCalendarUnitWeekday fromDate:self]; 354 | NSDateComponents *componentsToAdd = [[NSDateComponents alloc] init]; 355 | // to get the end of week for a particular date, add (7 - weekday) days 356 | [componentsToAdd setDay:(7 - [weekdayComponents weekday])]; 357 | NSDate *endOfWeek = [calendar dateByAddingComponents:componentsToAdd toDate:self options:0]; 358 | #if !__has_feature(objc_arc) 359 | [componentsToAdd release]; 360 | #endif 361 | return endOfWeek; 362 | } 363 | 364 | + (NSString *)dateFormatString { 365 | return kNSDateHelperFormatSQLDate; 366 | } 367 | 368 | + (NSString *)timeFormatString { 369 | return kNSDateHelperFormatSQLTime; 370 | } 371 | 372 | + (NSString *)timestampFormatString { 373 | return kNSDateHelperFormatSQLDateWithTime; 374 | } 375 | 376 | // preserving for compatibility 377 | + (NSString *)dbFormatString { 378 | return [NSDate timestampFormatString]; 379 | } 380 | 381 | @end 382 | --------------------------------------------------------------------------------