Swift gave to developers great opportunity to learn new stuff. It was, and I believe still is, a refreshing breeze to programmers’ life. There’s also a great reason to show off – quickly learn the newest technology and prove your skills by releasing some great project. A lot of developers did that and it’s really great. Today I would like to present my attempt to simplify operations on NSDate and its components – DateKit.
Everyone who worked with NSDateComponents knows how verbose it can be. Changing a single component involves an instance of NSCalendar, than an instance of NSDateComponents, then changing the component and finally you can get the result NSDate. It takes at least 3 lines of code that have to be written. It’s a bit disgusting. It makes mess in your code causing it hard to read and maintain in the future.
The idea behind DateKit was to encapsulate that operations in a single line of code. One line of code to modify components like seconds, minutes and hour should not be a problem. Comparing number of seconds or checking if only days of two dates are same should be very simple. I believe I achieved quite nice result. Keep on reading!
Below you can find some cheat-sheet for DateKit. Every feature is presented in playground, so you can interact with it.
You can modify one component at time:
or use chaining and change several in one line:
Compare dates using operators:
today < tomorrow // true
today <= tomorrow // true
today > tomorrow // false
today >= tomorrow // false
today == tomorrow // false
or it’s components (compares Int values, so it doesn’t check if you compare same compoments):
today.minute == tomorrow.minute
or you can compare by chosen components like this:
today.compare(toDate: tomorrow, byUnits: [.CalendarUnitMonth, .CalendarUnitYear])
compare(toDate:, byUnits: default) has default argument byUnit: which is [.CalendarUnitDay, .CalendarUnitMonth, .CalendarUnitYear] . This method returns NSComparisonResult , however you can determine bool value with shorthand methods like this:
today.compare(toDate: tomorrow, byUnits: [.CalendarUnitHour, .CalendarUnitYear]).same // false
today.compare(toDate: tomorrow, byUnits: [.CalendarUnitHour, .CalendarUnitYear]).ascending // true
today.compare(toDate: tomorrow, byUnits: [.CalendarUnitHour, .CalendarUnitYear]).descending // false
today.compare(toDate: tomorrow).notSame // true
Get date from current date by changing one component with operators:
today.minutes + 13
today.seconds - 4
today.hours + 1
today.days - 1
Here’s an example of chaining:
Functions add(Int) and substract(Int) works like +/- math operators.
I’ve added also some helpers. These are self-explaining:
Get the first and last unit in component:
today.months.first // returns same date but with January
today.months.last // returns same date but with December
today.minutes.first // returns same date but with 0 minutes
Since today it’s January this code:
will return date with last day of February – 28th. If you want to get day itself, just add day at the end of chain:
It’s pretty simple, isn’t it?
There is no surprise under the hood – every operation is being made using NSCalendar instance and NSDateComponents . To achieve chaining I’ve introduced Operation object, which keeps date and NSCalendarUnit . If you create a chain, remember to return result date by adding date word at the end.
I hope DateKit will improve your work with dates. We are open for pull request with new features as well as bug reports. Code is available on Github. Happy operating on dates!
PS: I’m planning to add some new stuff to DateKit in the future, so contact me if you have any requests!