├── .gitignore
├── Assets
└── CVCalendarKit.png
├── CVCalendarKit.podspec
├── CVCalendarKit
├── CVCalendarKitExtensions.swift
└── CVCalendarKitOperators.swift
├── CVCalendarKitDemo
└── Playground
│ └── CVCalendarKitDemo.playground
│ ├── Contents.swift
│ ├── Sources
│ ├── CVCalendarKitExtensions.swift
│ └── CVCalendarKitOperators.swift
│ ├── contents.xcplayground
│ └── playground.xcworkspace
│ └── contents.xcworkspacedata
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 |
20 | # CocoaPods
21 | #
22 | # We recommend against adding the Pods directory to your .gitignore. However
23 | # you should judge for yourself, the pros and cons are mentioned at:
24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
25 | #
26 | # Pods/
27 |
28 | # Carthage
29 | #
30 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
31 | # Carthage/Checkouts
32 |
33 | Carthage/Build
34 |
--------------------------------------------------------------------------------
/Assets/CVCalendarKit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mozharovsky/CVCalendarKit/686b3d52758a302e066ffc88647cb75aec0d142e/Assets/CVCalendarKit.png
--------------------------------------------------------------------------------
/CVCalendarKit.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "CVCalendarKit"
3 | s.version = "0.1.5"
4 | s.summary = "A wrapper around NSDate which provides a convenience way for dealing with dates and NSCalendar."
5 | s.homepage = "https://github.com/Mozharovsky/CVCalendarKit"
6 | s.license = { :type => 'MIT' }
7 | s.author = { "Eugene Mozharovsky" => "mozharovsky@live.com" }
8 | s.platform = :ios, '7.0'
9 | s.source = { :git => "https://github.com/Mozharovsky/CVCalendarKit.git", :tag => s.version.to_s }
10 | s.source_files = 'CVCalendarKit/*'
11 | s.requires_arc = true
12 | end
--------------------------------------------------------------------------------
/CVCalendarKit/CVCalendarKitExtensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CVCalendarKitExtensions.swift
3 | // CVCalendarKit
4 | //
5 | // Created by Eugene Mozharovsky on 05/05/15.
6 | // Copyright (c) 2015 Dwive. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | A wrapper around weekday raw value. The values match ones presented in NSCalendar.
13 | */
14 | public enum Weekday: Int {
15 | case Sunday = 1
16 | case Monday
17 | case Tuesday
18 | case Wednesday
19 | case Thursday
20 | case Friday
21 | case Saturday
22 |
23 | func stringValue() -> String {
24 | switch self {
25 | case .Sunday: return "Sunday".localized
26 | case .Monday: return "Monday".localized
27 | case .Tuesday: return "Tuesday".localized
28 | case .Wednesday: return "Wednesday".localized
29 | case .Thursday: return "Thursday".localized
30 | case .Friday: return "Friday".localized
31 | case .Saturday: return "Saturday".localized
32 | }
33 | }
34 | }
35 |
36 | /**
37 | Date format for string description and date construction.
38 | */
39 | public enum DateFormat: String {
40 | case YYMMDD = "yy-MM-dd"
41 | case YYYYMMDD = "yyyy-MM-dd"
42 | case YYMMMMDD = "yy-MMMM-dd"
43 | case YYMMMMDDDD = "yy-MMMM-dddd"
44 | case YYYYMMMMDD = "yyyy-MMMM-dddd"
45 |
46 | case DDMMYY = "dd-MM-yy"
47 | case DDMMYYYY = "dd-MM-yyyy"
48 | case DDMMMMYY = "dd-MMMM-yy"
49 | case DDDDMMMMYY = "dddd-MMMM-yy"
50 | case DDDDMMMMYYYY = "dddd-MMMM-yyyy"
51 | }
52 |
53 | private let YearUnit = NSCalendarUnit.Year
54 | private let MonthUnit = NSCalendarUnit.Month
55 | private let WeekUnit = NSCalendarUnit.WeekOfMonth
56 | private let WeekOfYearUnit = NSCalendarUnit.WeekOfYear
57 | private let WeekdayUnit = NSCalendarUnit.Weekday
58 | private let DayUnit = NSCalendarUnit.Day
59 | private let HourUnit = NSCalendarUnit.Hour
60 | private let MinuteUnit = NSCalendarUnit.Minute
61 | private let SecondUnit = NSCalendarUnit.Second
62 | private let AllUnits: NSCalendarUnit = [YearUnit , MonthUnit , WeekUnit , WeekOfYearUnit , WeekdayUnit , DayUnit, HourUnit, MinuteUnit, SecondUnit]
63 |
64 | public extension NSCalendar {
65 | /**
66 | Returns the NSDateComponents instance for all main units.
67 |
68 | :param: Date The date for components construction.
69 | :returns: The NSDateComponents instance for all main units.
70 | */
71 | func allComponentsFromDate(date: NSDate) -> NSDateComponents {
72 | return components(AllUnits, fromDate: date)
73 | }
74 | }
75 |
76 |
77 | public extension NSDate {
78 | private typealias DateRange = (year: Int, month: Int, day: Int)
79 |
80 | /**
81 | Calculates the date values.
82 |
83 | :returns: A tuple with date year, month and day values.
84 | */
85 | private func dateRange() -> DateRange {
86 | let calendar = NSCalendar.currentCalendar()
87 | let comps = calendar.allComponentsFromDate(self)
88 |
89 | return (comps.year, comps.month, comps.day)
90 | }
91 |
92 | /**
93 | Calculates the specific date values.
94 |
95 | :returns: A tuple with date hours and minutes.
96 | */
97 | private typealias DateSpecificRange = (hours: Int, minutes: Int)
98 | private func dateSpecificRange() -> DateSpecificRange {
99 | let calendar = NSCalendar.currentCalendar()
100 | let comps = calendar.allComponentsFromDate(self)
101 |
102 | return (comps.hour, comps.minute)
103 | }
104 |
105 | var hour: DateUnit {
106 | get {
107 | return .Hour(self, dateSpecificRange().hours)
108 | }
109 | }
110 |
111 | var minute: DateUnit {
112 | get {
113 | return .Minute(self, dateSpecificRange().minutes)
114 | }
115 | }
116 |
117 | /**
118 | Current date weekday.
119 | */
120 | var weekday: Weekday {
121 | get {
122 | return Weekday(rawValue: NSCalendar.currentCalendar().allComponentsFromDate(self).weekday)!
123 | }
124 | }
125 |
126 | /**
127 | Date year.
128 | */
129 | var year: DateUnit {
130 | get {
131 | return .Year(self, dateRange().year)
132 | }
133 | }
134 |
135 | /**
136 | Date month.
137 | */
138 | var month: DateUnit {
139 | get {
140 | return .Month(self, dateRange().month)
141 | }
142 | }
143 |
144 | /**
145 | Date day.
146 | */
147 | var day: DateUnit {
148 | get {
149 | return .Day(self, dateRange().day)
150 | }
151 | }
152 |
153 | /**
154 | Returns the first date in the current date's month.
155 |
156 | :returns: The first date in the current date's month.
157 | */
158 | func firstMonthDate() -> NSDate {
159 | return (self.day == 1)
160 | }
161 |
162 | /**
163 | Returns the last date in the current date's month.
164 |
165 | :returns: The las date in the current date's month.
166 | */
167 | func lastMonthDate() -> NSDate {
168 | return ((firstMonthDate().month + 1).day - 1)
169 | }
170 |
171 | /**
172 | Returns the first date in the current date's year.
173 |
174 | :returns: The first date in the current date's year.
175 | */
176 | func firstYearDate() -> NSDate {
177 | return ((NSDate().month == 1).day == 1)
178 | }
179 |
180 | /**
181 | Returns the last date in the current date's year.
182 |
183 | :returns: The last date in the current date's year.
184 | */
185 | func lastYearDate() -> NSDate {
186 | return (((firstYearDate().month == 12).month + 1).day - 1)
187 | }
188 |
189 | convenience init?(date: NSDate, hour: Int, minute: Int) {
190 | let calendar = NSCalendar.currentCalendar()
191 | let comps = calendar.components([.Hour , .Minute], fromDate: date)
192 | comps.hour = 0
193 | comps.minute = 0
194 |
195 | let first = calendar.dateFromComponents(comps)!
196 |
197 | let compss = calendar.components([.Hour , .Minute], fromDate: first)
198 | compss.hour = hour
199 | compss.minute = minute
200 |
201 | if let result = calendar.dateFromComponents(compss) {
202 | self.init(timeIntervalSince1970: result.timeIntervalSince1970)
203 | } else {
204 | self.init()
205 | return nil
206 | }
207 | }
208 |
209 | /**
210 | Returns a date description string with the given locale and format.
211 |
212 | - parameter locale: The locale for converting the date.
213 | - parameter format: String format for the converted date.
214 | - parameter style: String style for the converted date.
215 | - returns: A date description string with the given locale and format.
216 | */
217 | func descriptionWithLocale(locale: NSLocale? = nil, format: DateFormat = .YYMMDD, style: NSDateFormatterStyle?) -> String {
218 | let formatter = NSDateFormatter()
219 | formatter.dateFormat = format.rawValue
220 |
221 | if let formatterLocale = locale {
222 | formatter.locale = formatterLocale
223 | }
224 |
225 | if let formatterStyle = style {
226 | formatter.dateStyle = formatterStyle
227 | }
228 |
229 | return formatter.stringFromDate(self)
230 | }
231 | }
232 |
233 | public extension String {
234 | /**
235 | Returns an optional associated with date from the given string and format.
236 |
237 | - parameter format: Date format used for date conversion.
238 | - parameter style: Date style for date conversion.
239 | - returns: Either an NSDate instance or nil if a String can't be converted.
240 | */
241 | func date(format: DateFormat, style: NSDateFormatterStyle? = .LongStyle) -> NSDate? {
242 | let formatter = NSDateFormatter()
243 | formatter.dateFormat = format.rawValue
244 | if let formatterStyle = style {
245 | formatter.dateStyle = formatterStyle
246 | }
247 |
248 | return formatter.dateFromString(self)
249 | }
250 |
251 | /**
252 |
253 | */
254 | var localized: String {
255 | return NSLocalizedString(self, comment: self)
256 | }
257 | }
--------------------------------------------------------------------------------
/CVCalendarKit/CVCalendarKitOperators.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CVCalendarKitOperators.swift
3 | // CVCalendarKit
4 | //
5 | // Created by Eugene Mozharovsky on 05/05/15.
6 | // Copyright (c) 2015 Dwive. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | An operating entity containing content information regarding its
13 | owner. It's used in the date management for date construction and
14 | comparison.
15 |
16 | Each enum case is associated with a date and a value.
17 | */
18 | public enum DateUnit {
19 | case Year(NSDate, Int)
20 | case Month(NSDate, Int)
21 | case Day(NSDate, Int)
22 | case Hour(NSDate, Int)
23 | case Minute(NSDate, Int)
24 |
25 | /**
26 | :returns: An associated value with a particular case.
27 | */
28 | public func value() -> Int {
29 | switch self {
30 | case .Year(_, let x): return x
31 | case .Month(_, let x): return x
32 | case .Day(_, let x): return x
33 | case .Hour(_, let x): return x
34 | case .Minute(_, let x): return x
35 | }
36 | }
37 | }
38 |
39 | /**
40 | A structure for marking an offset for a date. Used for date contruction.
41 | */
42 | /**
43 | A structure for marking an offset for a date. Used for date contruction.
44 | */
45 | public struct Offset {
46 | var year: Int
47 | var month: Int
48 | var day: Int
49 | var hour: Int
50 | var minute: Int
51 | }
52 |
53 | // MARK: - Helper functions
54 |
55 | private typealias DateOffset = (Offset, DateOperation) -> NSDate
56 |
57 | /**
58 | Constructs a date with the offset from the source date.
59 |
60 | :param: date The given date for applying the offset.
61 |
62 | :returns: A function for getting the date from the offset and the assignment operation.
63 | */
64 | private func dateWithOffset(date: NSDate) -> DateOffset {
65 | let comps = NSCalendar.currentCalendar().allComponentsFromDate(date)
66 | return { offset, operation in
67 | comps.year = offset.year == 0 ? comps.year : operation(comps.year, offset.year)
68 | comps.month = offset.month == 0 ? comps.month : operation(comps.month, offset.month)
69 | comps.day = offset.day == 0 ? comps.day : operation(comps.day, offset.day)
70 | comps.hour = offset.hour == 0 ? comps.hour : operation(comps.hour, offset.hour)
71 | comps.minute = offset.minute == 0 ? comps.minute : operation(comps.minute, offset.minute)
72 |
73 | return NSCalendar.currentCalendar().dateFromComponents(comps)!
74 | }
75 | }
76 | private typealias DateOperation = (Int, Int) -> (Int)
77 |
78 | /**
79 | A bridge between construction function and the given options.
80 |
81 | :param: dateUnit A date unit providing the necessary data.
82 | :param: offset An offset for
83 | */
84 | private func dateUnitOffset(dateUnit: DateUnit, offset: Int, operation: DateOperation) -> NSDate {
85 | let result: NSDate
86 |
87 | switch dateUnit {
88 | case .Year(let date, _):
89 | result = dateWithOffset(date)(Offset(year: offset, month: 0, day: 0, hour: 0, minute: 0), operation)
90 | case .Month(let date, _):
91 | result = dateWithOffset(date)(Offset(year: 0, month: offset, day: 0, hour: 0, minute: 0), operation)
92 | case .Day(let date, _):
93 | result = dateWithOffset(date)(Offset(year: 0, month: 0, day: offset, hour: 0, minute: 0), operation)
94 | case .Hour(let date, _):
95 | result = dateWithOffset(date)(Offset(year: 0, month: 0, day: 0, hour: offset, minute: 0), operation)
96 | case .Minute(let date, _):
97 | result = dateWithOffset(date)(Offset(year: 0, month: 0, day: 0, hour: 0, minute: offset), operation)
98 | }
99 |
100 | return result
101 | }
102 |
103 | private typealias ComparisonOperation = (Int, Int) -> Bool
104 | private typealias ResultMerge = (Bool, Bool, Bool) -> Bool
105 | private typealias ComparisonResult = (NSDate, NSDate) -> Bool
106 |
107 | /**
108 | Compares dates via return closure.
109 |
110 | :param: operation Comparison operation.
111 | :param: resultMerge The way of merging the results.
112 | :returns: A comparison function.
113 | */
114 | private func compareWithOperation(operation: ComparisonOperation, resultMerge: ResultMerge) -> ComparisonResult {
115 | return { dateA, dateB in
116 | let resultA = operation(dateA.year.value(), dateB.year.value())
117 | let resultB = operation(dateA.month.value(), dateB.month.value())
118 | let resultC = operation(dateA.day.value(), dateB.day.value())
119 |
120 | return resultMerge(resultA, resultB, resultC)
121 | }
122 | }
123 |
124 | // MARK: - DateUnit operators overload
125 |
126 | public func + (lhs: DateUnit, rhs: Int) -> NSDate {
127 | return dateUnitOffset(lhs, offset: rhs, operation: { x, y in x + y })
128 | }
129 |
130 | public func - (lhs: DateUnit, rhs: Int) -> NSDate {
131 | return dateUnitOffset(lhs, offset: rhs, operation: { x, y in x - y })
132 | }
133 |
134 | public func * (lhs: DateUnit, rhs: Int) -> NSDate {
135 | return dateUnitOffset(lhs, offset: rhs, operation: { x, y in x * y })
136 | }
137 |
138 | public func / (lhs: DateUnit, rhs: Int) -> NSDate {
139 | return dateUnitOffset(lhs, offset: rhs, operation: { x, y in x / y })
140 | }
141 |
142 | public func == (lhs: DateUnit, rhs: Int) -> NSDate {
143 | return dateUnitOffset(lhs, offset: rhs, operation: { _, y in y })
144 | }
145 |
146 | // MARK: - NSDate operators overload
147 |
148 | public func == (lhs: NSDate, rhs: NSDate) -> Bool {
149 | return compareWithOperation({ $0 == $1 }, resultMerge: { $0 && $1 && $2 })(lhs, rhs)
150 | }
151 |
152 | public func > (lhs: NSDate, rhs: NSDate) -> Bool {
153 | return compareWithOperation({ $0 > $1 }, resultMerge: { $0 || $1 || $2 })(lhs, rhs)
154 | }
155 |
156 | public func >= (lhs: NSDate, rhs: NSDate) -> Bool {
157 | return compareWithOperation({ $0 > $1 || lhs == rhs }, resultMerge: { $0 || $1 || $2 })(lhs, rhs)
158 | }
159 |
160 | public func < (lhs: NSDate, rhs: NSDate) -> Bool {
161 | return compareWithOperation({ $0 < $1 }, resultMerge: { $0 || $1 || $2 })(lhs, rhs)
162 | }
163 |
164 | public func <= (lhs: NSDate, rhs: NSDate) -> Bool {
165 | return compareWithOperation({ $0 < $1 || lhs == rhs }, resultMerge: { $0 || $1 || $2 })(lhs, rhs)
166 | }
167 |
168 | public func != (lhs: NSDate, rhs: NSDate) -> Bool {
169 | return !(lhs == rhs)
170 | }
--------------------------------------------------------------------------------
/CVCalendarKitDemo/Playground/CVCalendarKitDemo.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import UIKit
4 |
5 | /// Current date.
6 | let today = NSDate()
7 |
8 | /// Day operations.
9 | let tomorrow = today.day + 1
10 | let yesterday = today.day - 1
11 |
12 | /// Month operations.
13 | let monthAhead = today.month + 1
14 | let monthAgo = today.month - 1
15 |
16 | /// Year operations.
17 | let yearAhead = today.year + 1
18 | let yearAgo = today.year - 1
19 |
20 | /// Multiplication and Division.
21 | let multipliedDate = today.day * 5
22 | let dividedDate = today.month / 5
23 |
24 | /// Trailing operations.
25 | let dayAheadMonthAgo = (today.day + 1).month - 1
26 | let yearAheadTwoMonthsAgoFiveDaysAhead = ((today.year + 1).month - 2).day + 5
27 |
28 | /// NSDate comparison.
29 | today == yesterday
30 | today > yesterday
31 | yesterday <= tomorrow
32 | tomorrow != today
33 |
34 | /// Convenience stuff.
35 | let firstDateInCurrentMonth = today.firstMonthDate()
36 | let lastDateInCurrentMonth = today.lastMonthDate()
37 | let firstDateInCurrentYear = today.firstYearDate()
38 | let lastDateInCurrentYear = today.lastYearDate()
39 |
40 | /// Date construction by assigning values.
41 | let customDate = ((today.day == 21).month == 5).year == 1997
42 |
43 | /// Date unit values (year, month, day).
44 | let todaysYear = today.year.value()
45 | let todaysMonth = today.month.value()
46 | let todaysDay = today.day.value()
47 |
48 | /// NSDate+Weekday.
49 | let todaysWeekday = today.weekday // Enum value.
50 | let todaysWeekdayRaw = today.weekday.rawValue // Raw value.
51 |
52 | /// Date description.
53 | let date = (NSDate().month == 5).descriptionWithLocale(nil, format: .DDMMYY, style: nil)
54 |
55 | /// Date from String (its description).
56 | if let myDate = "May 21, 1997".date(.DDMMYY, style: .MediumStyle) {
57 | myDate
58 | }
--------------------------------------------------------------------------------
/CVCalendarKitDemo/Playground/CVCalendarKitDemo.playground/Sources/CVCalendarKitExtensions.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CVCalendarKitExtensions.swift
3 | // CVCalendarKit
4 | //
5 | // Created by Eugene Mozharovsky on 05/05/15.
6 | // Copyright (c) 2015 Dwive. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | A wrapper around weekday raw value. The values match ones presented in NSCalendar.
13 | */
14 | public enum Weekday: Int {
15 | case Sunday = 1
16 | case Monday
17 | case Tuesday
18 | case Wednesday
19 | case Thursday
20 | case Friday
21 | case Saturday
22 | }
23 |
24 | /**
25 | Date format for string description and date construction.
26 | */
27 | public enum DateFormat: String {
28 | case YYMMDD = "yy-MM-dd"
29 | case YYYYMMDD = "yyyy-MM-dd"
30 | case YYMMMMDD = "yy-MMMM-dd"
31 | case YYMMMMDDDD = "yy-MMMM-dddd"
32 | case YYYYMMMMDD = "yyyy-MMMM-dddd"
33 |
34 | case DDMMYY = "dd-MM-yy"
35 | case DDMMYYYY = "dd-MM-yyyy"
36 | case DDMMMMYY = "dd-MMMM-yy"
37 | case DDDDMMMMYY = "dddd-MMMM-yy"
38 | case DDDDMMMMYYYY = "dddd-MMMM-yyyy"
39 | }
40 |
41 | private let YearUnit = NSCalendarUnit.CalendarUnitYear
42 | private let MonthUnit = NSCalendarUnit.CalendarUnitMonth
43 | private let WeekUnit = NSCalendarUnit.CalendarUnitWeekOfMonth
44 | private let WeekOfYearUnit = NSCalendarUnit.CalendarUnitWeekOfYear
45 | private let WeekdayUnit = NSCalendarUnit.CalendarUnitWeekday
46 | private let DayUnit = NSCalendarUnit.CalendarUnitDay
47 | private let HourUnit = NSCalendarUnit.CalendarUnitHour
48 | private let MinuteUnit = NSCalendarUnit.CalendarUnitMinute
49 | private let SecondUnit = NSCalendarUnit.CalendarUnitSecond
50 | private let AllUnits = YearUnit | MonthUnit | WeekUnit | WeekOfYearUnit | WeekdayUnit | DayUnit | HourUnit | MinuteUnit | DayUnit
51 |
52 | public extension NSCalendar {
53 | /**
54 | Returns the NSDateComponents instance for all main units.
55 |
56 | :param: Date The date for components construction.
57 | :returns: The NSDateComponents instance for all main units.
58 | */
59 | func allComponentsFromDate(date: NSDate) -> NSDateComponents {
60 | return components(AllUnits, fromDate: date)
61 | }
62 | }
63 |
64 |
65 | public extension NSDate {
66 | private typealias DateRange = (year: Int, month: Int, day: Int)
67 |
68 | /**
69 | Calculates the date values.
70 |
71 | :returns: A tuple with date year, month and day values.
72 | */
73 | private func dateRange() -> DateRange {
74 | let calendar = NSCalendar.currentCalendar()
75 | let comps = calendar.allComponentsFromDate(self)
76 |
77 | return (comps.year, comps.month, comps.day)
78 | }
79 |
80 | /**
81 | Current date weekday.
82 | */
83 | var weekday: Weekday {
84 | get {
85 | return Weekday(rawValue: NSCalendar.currentCalendar().allComponentsFromDate(self).weekday)!
86 | }
87 | }
88 |
89 | /**
90 | Date year.
91 | */
92 | var year: DateUnit {
93 | get {
94 | return .Year(self, dateRange().year)
95 | }
96 | }
97 |
98 | /**
99 | Date month.
100 | */
101 | var month: DateUnit {
102 | get {
103 | return .Month(self, dateRange().month)
104 | }
105 | }
106 |
107 | /**
108 | Date day.
109 | */
110 | var day: DateUnit {
111 | get {
112 | return .Day(self, dateRange().day)
113 | }
114 | }
115 |
116 | /**
117 | Returns the first date in the current date's month.
118 |
119 | :returns: The first date in the current date's month.
120 | */
121 | func firstMonthDate() -> NSDate {
122 | return (self.day == 1)
123 | }
124 |
125 | /**
126 | Returns the last date in the current date's month.
127 |
128 | :returns: The las date in the current date's month.
129 | */
130 | func lastMonthDate() -> NSDate {
131 | return ((firstMonthDate().month + 1).day - 1)
132 | }
133 |
134 | /**
135 | Returns the first date in the current date's year.
136 |
137 | :returns: The first date in the current date's year.
138 | */
139 | func firstYearDate() -> NSDate {
140 | return ((NSDate().month == 1).day == 1)
141 | }
142 |
143 | /**
144 | Returns the last date in the current date's year.
145 |
146 | :returns: The last date in the current date's year.
147 | */
148 | func lastYearDate() -> NSDate {
149 | return (((firstYearDate().month == 12).month + 1).day - 1)
150 | }
151 |
152 | /**
153 | Returns a date description string with the given locale and format.
154 |
155 | :param: locale The locale for converting the date.
156 | :param: format String format for the converted date.
157 | :param: style String style for the converted date.
158 | :returns: A date description string with the given locale and format.
159 | */
160 | func descriptionWithLocale(_ locale: NSLocale? = nil, format: DateFormat = .YYMMDD, style: NSDateFormatterStyle?) -> String {
161 | let formatter = NSDateFormatter()
162 | formatter.dateFormat = format.rawValue
163 |
164 | if let formatterLocale = locale {
165 | formatter.locale = formatterLocale
166 | }
167 |
168 | if let formatterStyle = style {
169 | formatter.dateStyle = formatterStyle
170 | }
171 |
172 | return formatter.stringFromDate(self)
173 | }
174 | }
175 |
176 | public extension String {
177 | /**
178 | Returns an optional associated with date from the given string and format.
179 |
180 | :param: format Date format used for date conversion.
181 | :param: style Date style for date conversion.
182 | :returns: Either an NSDate instance or nil if a String can't be converted.
183 | */
184 | func date(format: DateFormat, style: NSDateFormatterStyle? = .LongStyle) -> NSDate? {
185 | let formatter = NSDateFormatter()
186 | formatter.dateFormat = format.rawValue
187 | if let formatterStyle = style {
188 | formatter.dateStyle = formatterStyle
189 | }
190 |
191 | return formatter.dateFromString(self)
192 | }
193 | }
--------------------------------------------------------------------------------
/CVCalendarKitDemo/Playground/CVCalendarKitDemo.playground/Sources/CVCalendarKitOperators.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CVCalendarKitOperators.swift
3 | // CVCalendarKit
4 | //
5 | // Created by Eugene Mozharovsky on 05/05/15.
6 | // Copyright (c) 2015 Dwive. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | /**
12 | An operating entity containing content information regarding its
13 | owner. It's used in the date management for date construction and
14 | comparison.
15 |
16 | Each enum case is associated with a date and a value.
17 | */
18 | public enum DateUnit {
19 | case Year(NSDate, Int)
20 | case Month(NSDate, Int)
21 | case Day(NSDate, Int)
22 |
23 | /**
24 | :returns: An associated value with a particular case.
25 | */
26 | public func value() -> Int {
27 | switch self {
28 | case .Year(_, let x): return x
29 | case .Month(_, let x): return x
30 | case .Day(_, let x): return x
31 | }
32 | }
33 | }
34 |
35 | /**
36 | A structure for marking an offset for a date. Used for date contruction.
37 | */
38 | public struct Offset {
39 | var year: Int
40 | var month: Int
41 | var day: Int
42 | }
43 |
44 | // MARK: - Helper functions
45 |
46 | private typealias DateOffset = (Offset, DateOperation) -> NSDate
47 |
48 | /**
49 | Constructs a date with the offset from the source date.
50 |
51 | :param: date The given date for applying the offset.
52 |
53 | :returns: A function for getting the date from the offset and the assignment operation.
54 | */
55 | private func dateWithOffset(date: NSDate) -> DateOffset {
56 | let comps = NSCalendar.currentCalendar().allComponentsFromDate(date)
57 | return { offset, operation in
58 | comps.year = offset.year == 0 ? comps.year : operation(comps.year, offset.year)
59 | comps.month = offset.month == 0 ? comps.month : operation(comps.month, offset.month)
60 | comps.day = offset.day == 0 ? comps.day : operation(comps.day, offset.day)
61 |
62 | return NSCalendar.currentCalendar().dateFromComponents(comps)!
63 | }
64 | }
65 |
66 | private typealias DateOperation = (Int, Int) -> (Int)
67 |
68 | /**
69 | A bridge between construction function and the given options.
70 |
71 | :param: dateUnit A date unit providing the necessary data.
72 | :param: offset An offset for
73 | */
74 | private func dateUnitOffset(dateUnit: DateUnit, offset: Int, operation: DateOperation) -> NSDate {
75 | let result: NSDate
76 |
77 | switch dateUnit {
78 | case .Year(let date, let value):
79 | result = dateWithOffset(date)(Offset(year: offset, month: 0, day: 0), operation)
80 | case .Month(let date, let value):
81 | result = dateWithOffset(date)(Offset(year: 0, month: offset, day: 0), operation)
82 | case .Day(let date, let value):
83 | result = dateWithOffset(date)(Offset(year: 0, month: 0, day: offset), operation)
84 | }
85 |
86 | return result
87 | }
88 |
89 | private typealias ComparisonOperation = (Int, Int) -> Bool
90 | private typealias ResultMerge = (Bool, Bool, Bool) -> Bool
91 | private typealias ComparisonResult = (NSDate, NSDate) -> Bool
92 |
93 | /**
94 | Compares dates via return closure.
95 |
96 | :param: operation Comparison operation.
97 | :param: resultMerge The way of merging the results.
98 | :returns: A comparison function.
99 | */
100 | private func compareWithOperation(operation: ComparisonOperation, resultMerge: ResultMerge) -> ComparisonResult {
101 | return { dateA, dateB in
102 | let resultA = operation(dateA.year.value(), dateB.year.value())
103 | let resultB = operation(dateA.month.value(), dateB.month.value())
104 | let resultC = operation(dateA.day.value(), dateB.day.value())
105 |
106 | return resultMerge(resultA, resultB, resultC)
107 | }
108 | }
109 |
110 | // MARK: - DateUnit operators overload
111 |
112 | public func + (lhs: DateUnit, rhs: Int) -> NSDate {
113 | return dateUnitOffset(lhs, rhs, { x, y in x + y })
114 | }
115 |
116 | public func - (lhs: DateUnit, rhs: Int) -> NSDate {
117 | return dateUnitOffset(lhs, rhs, { x, y in x - y })
118 | }
119 |
120 | public func * (lhs: DateUnit, rhs: Int) -> NSDate {
121 | return dateUnitOffset(lhs, rhs, { x, y in x * y })
122 | }
123 |
124 | public func / (lhs: DateUnit, rhs: Int) -> NSDate {
125 | return dateUnitOffset(lhs, rhs, { x, y in x / y })
126 | }
127 |
128 | public func == (lhs: DateUnit, rhs: Int) -> NSDate {
129 | return dateUnitOffset(lhs, rhs, { _, y in y })
130 | }
131 |
132 | // MARK: - NSDate operators overload
133 |
134 | public func == (lhs: NSDate, rhs: NSDate) -> Bool {
135 | return compareWithOperation({ $0 == $1 }, { $0 && $1 && $2 })(lhs, rhs)
136 | }
137 |
138 | public func > (lhs: NSDate, rhs: NSDate) -> Bool {
139 | return compareWithOperation({ $0 > $1 }, { $0 || $1 || $2 })(lhs, rhs)
140 | }
141 |
142 | public func >= (lhs: NSDate, rhs: NSDate) -> Bool {
143 | return compareWithOperation({ $0 > $1 || lhs == rhs }, { $0 || $1 || $2 })(lhs, rhs)
144 | }
145 |
146 | public func < (lhs: NSDate, rhs: NSDate) -> Bool {
147 | return compareWithOperation({ $0 < $1 }, { $0 || $1 || $2 })(lhs, rhs)
148 | }
149 |
150 | public func <= (lhs: NSDate, rhs: NSDate) -> Bool {
151 | return compareWithOperation({ $0 < $1 || lhs == rhs }, { $0 || $1 || $2 })(lhs, rhs)
152 | }
153 |
154 | public func != (lhs: NSDate, rhs: NSDate) -> Bool {
155 | return !(lhs == rhs)
156 | }
--------------------------------------------------------------------------------
/CVCalendarKitDemo/Playground/CVCalendarKitDemo.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |