Open Source Objective-C Calendar Class

I always try to get you guys something for Christmas, but you're so hard to buy for. So instead, you get code. Mac OS X has solid time/date functionality, but it's spread across a number of different places. THCalendarInfo consolidates them.

Using NSDate, NSCalendarDate, CFCalendar, and so on, this class does its best to give you solutions for real-world use cases. It's particularly useful for walking hours, days, weeks, months, years, and so on. Examples speak louder than descriptions:

THCalendarInfo * calInfo = [THCalendarInfo calendarInfo];

NSLog(@"Month: %@", [calInfo monthName]);
NSLog(@"Date: %i", [calInfo dayOfMonth]);
NSLog(@"Day: %@", [calInfo dayName]);
NSLog(@"Days in Month: %i\n\n", [calInfo daysInMonth]);

[calInfo moveToPreviousDay];
NSLog(@"Date: %i", [calInfo dayOfMonth]);
NSLog(@"Day: %@\n\n", [calInfo dayName]);

[calInfo moveToNextMonth];
NSLog(@"Month: %@", [calInfo monthName]);
NSLog(@"Date: %i", [calInfo dayOfMonth]);
NSLog(@"Day: %@", [calInfo dayName]);   
NSLog(@"Days in Month: %i\n\n", [calInfo daysInMonth]);

[calInfo moveToNextYear];
NSLog(@"Month: %@", [calInfo monthName]);  
NSLog(@"Date: %i", [calInfo dayOfMonth]);
NSLog(@"Year: %i", [calInfo year]);
NSLog(@"Day: %@", [calInfo dayName]);
NSLog(@"Days in Month: %i\n\n", [calInfo daysInMonth]);

[calInfo moveToFirstDayOfMonth];
NSLog(@"Month: %@", [calInfo monthName]);  
NSLog(@"Date: %i", [calInfo dayOfMonth]);
NSLog(@"Day: %@\n\n", [calInfo dayName]);

[calInfo resetDateAndTimeToCurrent];
NSLog(@"NSDate rep: %@\n\n", [calInfo date]);

[calInfo adjustDays:81];
NSLog(@"Month: %@", [calInfo monthName]);  
NSLog(@"Date: %i\n\n", [calInfo dayOfMonth]);

[calInfo adjustDays:-81];
NSLog(@"Month: %@", [calInfo monthName]);  
NSLog(@"Date: %i\n\n", [calInfo dayOfMonth]);

// class methods
NSLog(@"+currentHour: %i", [THCalendarInfo currentHour]);
NSLog(@"+currentMinute: %i", [THCalendarInfo currentMinute]);
NSLog(@"+currentSecond: %i", [THCalendarInfo currentSecond]);


That results in this output:

Month: December
Date: 25
Day: Monday
Days in Month: 31

-moveToPreviousDay
Date: 24
Day: Sunday

-moveToNextMonth
Month: January
Date: 24
Day: Wednesday
Days in Month: 31

-moveToNextYear
Month: January
Date: 24
Year: 2008
Day: Thursday
Days in Month: 31

-moveToFirstDayOfMonth
Month: January
Date: 1
Day: Tuesday

-resetDateAndTimeToCurrent
NSDate rep: 2006-12-25 08:58:11 -0800

-adjustDays:81
Month: March
Date: 16

-adjustDays:-81
Month: December
Date: 25

+currentHour: 8
+currentMinute: 58
+currentSecond: 11


You can also also get the current date/time as CFAbsoluteTime, NSDate or NSCalendarDate. Dealing with licenses is a hassle, but this one is BSD. I hope that's okay.

Enjoy your Christmas present.
Design Element
Open Source Objective-C Calendar Class
Posted Dec 25, 2006 — 18 comments below




 

Patrick Thomson — Dec 25, 06 2869

Wow; thanks so much, Scott!
I'll see if I can work this into my application.
I hope you like your gift.

Martin — Dec 25, 06 2870

Thank you so much, Scott!

Clint — Dec 25, 06 2873

you shouldn't have! you already gave us cocoablogs this year and plus there's still lots of goodies under the cocoadevcentral tree!

Thanks for all your hard work Scott!

Rob — Dec 25, 06 2874

Nice NSLog example ...

... now I know how to make Fprint functionality in Cocoa, Thanks !

John Devor — Dec 25, 06 2876

Awesome code, Scott. Merry Christmas!

Hunter — May 06, 08 5792

a nice code!
btw,
I am looking for a way that how to set system date...
For example, now is 05/07/2008 00:49:53, I want to set datetime to 06/07/2008 00:49:53. that change date without modifing time.

first , I use the popen to run the system command "date" in my program, but it can't change date without modifing time. And it will lost the second info of time...

such as:

NSString *output = [NSString string];
NSString *cmd = [NSString stringWithFormat:@"date 060700492008"];
NSLog(@"exec cmd:%@",cmd);
FILE *pipe = popen([cmd cStringUsingEncoding: NSASCIIStringEncoding], "r");
if (!pipe) return -1;
char buf[1024];
while(fgets(buf, 1024, pipe)) {
output = [output stringByAppendingFormat: @"%s", buf];
}
pclose(pipe);

Is there another way to do that?

help me T_T

Scott Stevenson — May 09, 08 5806 Scotty the Leopard

@Hunter: I am looking for a way that how to set system date

I don't know the answer to that offhand. Probably whatever works in unix in general would work for Mac OS X.

Erik Verbruggen — Jul 27, 08 6185

Thanks Scott!

Just one question: like nearly all classes I've seen, this one is missing week handling. For example, no:

- (int)weekOfYear; - (void)moveToNextWeek; - (void)moveToPreviousWeek; - (void)adjustWeeks:(int)weeks; - (int)firstDayOfWeek; - (void)setFirstDayOfWeek:(int)newFirstDay;

If you're interested, I can supply a patch, but if you have a test suite, so I can add to that too.

Cheers,
Erik.

Erik Verbruggen — Jul 27, 08 6186

Hi Scott,

Another possible improvement: why not have the dayName return the localised day name (by running the formatter on it)? Using hard-coded English names is not very useful in many locales...

Cheers,
Erik.

Scott Stevenson — Jul 30, 08 6194 Scotty the Leopard

@Erik Verbruggen: Just one question: like nearly all classes I've seen, this one is missing week handling

Hi Erik. I haven't worked on this in a while but the localized names sound cool. I have no idea how much interest there is in this code right now.

The week-based methods would probably be nice too, though that's pretty easy to do by hand using multiples of seven. I get why it's easier to read when spelled out as a method, though.

Daniel Read — Dec 28, 08 6574

Thanks Scott!

I'm new to cocoa and I'm working on integrating calendaring functions into my app so I'm studying what others have done.

This couldn't have come at a better time for me.

Daniel Read — Dec 28, 08 6575

Hi Scott,

I've gotten some warnings in the THCalendarInfo implementation file when doing a build. I hadn't changed anything in the class files. Only imported them into a basic cocoa application project.

The warnings are:
  • For all CFCalendarAddComponents calls: 'pointer targets in passing argument 4 of 'CFCalendarAddComponents' differ in signedness', and
  • For the CFCalendarComposeAbsoluteTime call: 'pointer targets in passing argument 3 of 'CFCalendarComposeAbsoluteTime' differ in signedness'.


I looked up the definition of 'signedness' on Wikipedia, which lead me to see that the fourth argument in the CFCalendarAddComponents definition is const char rather than const unsigned char, which you'd used for the format declarations. After commenting out unsigned on the relevant lines in THCalendarInfo.m the warnings for CFCalendarAddComponents calls are gone and things still work as they should.

I haven't looked at the warning for CFCalendarComposeAbsoluteTime yet but I'm wondering why I'm getting the errors as I don't imagine you would've had them when you wrote the code. I noticed the comment about the need to declare the format separately but I'm wondering why there's a disparity between your declarations for format and the definition of argument 4 in CFCalendarAddComponents.

Can you tell me more about why you used unsigned in the format declarations?

Daniel Read — Dec 28, 08 6576

Just noticed the original post is from '06. Two years have pasted and the gift keeps on giving.

Now I'm thinking there would've been several changes in Core Foundation over that period of time and that could explain the disparity I mentioned above.

dave — Dec 31, 08 6579

thanks for the example code. about to dive into learning objective c, and this is very helpful.

happy new year!

Ellery — Feb 07, 09 6608

Thanks Scott for the great code.

Question, is it possible to use this with the iPhone SDK? I'm attempting to use it and I get an error:

"Cocoa/Cocoa.h" No such file or directory

I'm new to Mac development; please forgive my ignorance.

Jonathan Sterling — Apr 11, 09 6683

Question, is it possible to use this with the iPhone SDK? I'm attempting to use it and I get an error.

As far as I know, Cocoa is not the framework used in iPhone apps. In reality, Cocoa.framework contains just one file (Cocoa.h); all Cocoa.h does is imports Foundation.h, AppKit.h, and CoreData.h. You won't be using Core Data on iPhone (unless you are using SDK 3.o); AppKit.h is replaced with UIKit.h for iPhone, and Foundation.h remains the same.

Try taking out any references to Cocoa.h and see what happens.

Michele Ruggiero — May 18, 09 6767

Hi...
I would thanks you for this object...
Michele.

Max — Aug 20, 09 6852

For a while, I used something very similar to this on my website. Yours seems better, it is really cool. Thanks!




 

Comments Temporarily Disabled

I had to temporarily disable comments due to spam. I'll re-enable them soon.





Copyright © Scott Stevenson 2004-2015