├── Cartfile ├── Cartfile.resolved ├── Pods ├── Target Support Files │ ├── SwiftDate │ │ ├── SwiftDate-prefix.pch │ │ ├── SwiftDate.modulemap │ │ ├── SwiftDate-dummy.m │ │ ├── SwiftDate-umbrella.h │ │ ├── SwiftDate.xcconfig │ │ └── Info.plist │ └── Pods-HNCalendarView │ │ ├── Pods-HNCalendarView.modulemap │ │ ├── Pods-HNCalendarView-dummy.m │ │ ├── Pods-HNCalendarView-umbrella.h │ │ ├── Pods-HNCalendarView.debug.xcconfig │ │ ├── Pods-HNCalendarView.release.xcconfig │ │ ├── Info.plist │ │ ├── Pods-HNCalendarView-acknowledgements.markdown │ │ ├── Pods-HNCalendarView-acknowledgements.plist │ │ ├── Pods-HNCalendarView-frameworks.sh │ │ └── Pods-HNCalendarView-resources.sh ├── Manifest.lock └── SwiftDate │ ├── LICENSE │ ├── Sources │ └── SwiftDate │ │ ├── DateInRegion+Equations.swift │ │ ├── NSTimeInterval+SwiftDate.swift │ │ ├── NSDateInterval.swift │ │ ├── DateInRegion+StartEnd.swift │ │ ├── Dictionary+SwiftDate.swift │ │ ├── DateInRegion+NSDatePort.swift │ │ ├── DateInRegion+Operations.swift │ │ ├── Region.swift │ │ ├── NSCalendar+SwiftDate.swift │ │ ├── NSDateFormatter+SwiftDate.swift │ │ ├── NSDateComponents+SwiftDate.swift │ │ ├── Additions.swift │ │ ├── DateInRegion+Comparisons.swift │ │ ├── DateInRegion+Components.swift │ │ ├── DateInRegion.swift │ │ └── DateInRegion+Formatter.swift │ └── README.md ├── .gitmodules ├── Podfile.lock ├── HNCalendarView.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── HNCalendarView-OSX.xcscheme │ └── HNCalendarView.xcscheme ├── bin └── setup ├── Podfile ├── HNCalendarView.xcworkspace └── contents.xcworkspacedata ├── Source ├── Classes │ ├── Helpers │ │ └── HNCalendar.swift │ ├── Views │ │ ├── HNWeekItem.swift │ │ ├── HNMonthItem.swift │ │ ├── HNDateItem.swift │ │ └── HNDateItemView.swift │ └── HNCalendarView.swift └── Assets │ ├── HNWeekItem.xib │ ├── HNDateItem.xib │ ├── HNMonthItem.xib │ └── HNCalendarView.xib ├── HNCalendarView ├── AppDelegate.swift ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist └── ViewController.swift ├── HNCalendarView-OSX ├── HNCalendarView.h ├── HNCalendarView-OSX.h └── Info.plist ├── HNCalendarViewTests ├── Info.plist └── HNCalendarViewTests.swift ├── HNCalendarViewUITests ├── Info.plist └── HNCalendarViewUITests.swift ├── README.md ├── .gitignore └── HNCalendarView.podspec /Cartfile: -------------------------------------------------------------------------------- 1 | github "malcommac/SwiftDate" 2 | -------------------------------------------------------------------------------- /Cartfile.resolved: -------------------------------------------------------------------------------- 1 | github "malcommac/SwiftDate" "3.0.9" 2 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SwiftDate/SwiftDate-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Carthage/Checkouts/SwiftDate"] 2 | path = Carthage/Checkouts/SwiftDate 3 | url = https://github.com/malcommac/SwiftDate.git 4 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SwiftDate/SwiftDate.modulemap: -------------------------------------------------------------------------------- 1 | framework module SwiftDate { 2 | umbrella header "SwiftDate-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SwiftDate/SwiftDate-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_SwiftDate : NSObject 3 | @end 4 | @implementation PodsDummy_SwiftDate 5 | @end 6 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - SwiftDate (3.0.8) 3 | 4 | DEPENDENCIES: 5 | - SwiftDate (~> 3) 6 | 7 | SPEC CHECKSUMS: 8 | SwiftDate: 971f8b9394f664f2226b9c3ab64e801a7291c612 9 | 10 | COCOAPODS: 0.39.0 11 | -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - SwiftDate (3.0.8) 3 | 4 | DEPENDENCIES: 5 | - SwiftDate (~> 3) 6 | 7 | SPEC CHECKSUMS: 8 | SwiftDate: 971f8b9394f664f2226b9c3ab64e801a7291c612 9 | 10 | COCOAPODS: 0.39.0 11 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SwiftDate/SwiftDate-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double SwiftDateVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char SwiftDateVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-HNCalendarView/Pods-HNCalendarView.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_HNCalendarView { 2 | umbrella header "Pods-HNCalendarView-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-HNCalendarView/Pods-HNCalendarView-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_HNCalendarView : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_HNCalendarView 5 | @end 6 | -------------------------------------------------------------------------------- /HNCalendarView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-HNCalendarView/Pods-HNCalendarView-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double Pods_HNCalendarViewVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char Pods_HNCalendarViewVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | if ! command -v carthage > /dev/null; then 4 | printf 'Carthage is not installed.\n' 5 | printf 'See https://github.com/Carthage/Carthage for install instructions.\n' 6 | exit 1 7 | fi 8 | 9 | carthage update --platform OSX --use-submodules --no-use-binaries 10 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | platform :osx, '10.11' 3 | use_frameworks! 4 | 5 | target 'HNCalendarView' do 6 | pod 'SwiftDate', '~> 3' 7 | end 8 | 9 | target 'HNCalendarViewTests' do 10 | 11 | end 12 | 13 | target 'HNCalendarViewUITests' do 14 | 15 | end 16 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SwiftDate/SwiftDate.xcconfig: -------------------------------------------------------------------------------- 1 | CODE_SIGN_IDENTITY = 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/SwiftDate" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_ROOT = ${SRCROOT} 6 | SKIP_INSTALL = YES -------------------------------------------------------------------------------- /HNCalendarView.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Source/Classes/Helpers/HNCalendar.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HNCalendar.swift 3 | // HNCalendarView 4 | // 5 | // Created by Harry Ng on 9/4/2016. 6 | // Copyright © 2016 STAY REAL LIMITED. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | class HNCalendar { 12 | 13 | static let Week:[String] = NSDateFormatter().shortWeekdaySymbols as [String] 14 | static let Month:[String] = NSDateFormatter().shortMonthSymbols as [String] 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-HNCalendarView/Pods-HNCalendarView.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CODE_SIGN_IDENTITY = 2 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/SwiftDate.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "SwiftDate" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-HNCalendarView 9 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-HNCalendarView/Pods-HNCalendarView.release.xcconfig: -------------------------------------------------------------------------------- 1 | CODE_SIGN_IDENTITY = 2 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/../Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$CONFIGURATION_BUILD_DIR/SwiftDate.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "SwiftDate" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_FRAMEWORK_BUILD_PATH = $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods-HNCalendarView 9 | PODS_ROOT = ${SRCROOT}/Pods -------------------------------------------------------------------------------- /HNCalendarView/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // HNCalendarView 4 | // 5 | // Created by Harry Ng on 4/4/2016. 6 | // Copyright © 2016 STAY REAL LIMITED. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | @NSApplicationMain 12 | class AppDelegate: NSObject, NSApplicationDelegate { 13 | 14 | 15 | 16 | func applicationDidFinishLaunching(aNotification: NSNotification) { 17 | // Insert code here to initialize your application 18 | } 19 | 20 | func applicationWillTerminate(aNotification: NSNotification) { 21 | // Insert code here to tear down your application 22 | } 23 | 24 | 25 | } 26 | 27 | -------------------------------------------------------------------------------- /HNCalendarView-OSX/HNCalendarView.h: -------------------------------------------------------------------------------- 1 | // 2 | // HNCalendarView-OSX.h 3 | // HNCalendarView-OSX 4 | // 5 | // Created by Harry Ng on 5/7/2016. 6 | // Copyright © 2016 STAY REAL LIMITED. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for HNCalendarView-OSX. 12 | FOUNDATION_EXPORT double HNCalendarViewVersionNumber; 13 | 14 | //! Project version string for HNCalendarView-OSX. 15 | FOUNDATION_EXPORT const unsigned char HNCalendarViewVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Source/Classes/Views/HNWeekItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HNWeekItem.swift 3 | // HNCalendarView 4 | // 5 | // Created by Harry Ng on 8/4/2016. 6 | // Copyright © 2016 STAY REAL LIMITED. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class HNWeekItem: NSCollectionViewItem { 12 | 13 | @IBOutlet weak var weekField: NSTextField! 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | // Do view setup here. 18 | } 19 | 20 | func configure(week: String) { 21 | weekField.stringValue = week 22 | weekField.textColor = HNCalendarView.globalPreferences.calendar.textColor 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /HNCalendarView-OSX/HNCalendarView-OSX.h: -------------------------------------------------------------------------------- 1 | // 2 | // HNCalendarView-OSX.h 3 | // HNCalendarView-OSX 4 | // 5 | // Created by Harry Ng on 7/7/2016. 6 | // Copyright © 2016 STAY REAL LIMITED. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for HNCalendarView-OSX. 12 | FOUNDATION_EXPORT double HNCalendarView_OSXVersionNumber; 13 | 14 | //! Project version string for HNCalendarView-OSX. 15 | FOUNDATION_EXPORT const unsigned char HNCalendarView_OSXVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Source/Classes/Views/HNMonthItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HNMonthItem.swift 3 | // HNCalendarView 4 | // 5 | // Created by Harry Ng on 7/4/2016. 6 | // Copyright © 2016 STAY REAL LIMITED. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class HNMonthItem: NSCollectionViewItem { 12 | 13 | @IBOutlet weak var monthField: NSTextField! 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | // Do view setup here. 18 | } 19 | 20 | func configure(month: String, year: Int) { 21 | monthField.stringValue = "\(month) \(year)" 22 | monthField.textColor = HNCalendarView.globalPreferences.calendar.textColor 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /HNCalendarViewTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /HNCalendarViewUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Pods/Target Support Files/SwiftDate/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 3.0.8 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-HNCalendarView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /HNCalendarView-OSX/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSHumanReadableCopyright 24 | Copyright © 2016 STAY REAL LIMITED. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HNCalendarView [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 2 | CalendarView framework written in Swift for OS X 3 | 4 | # Usage 5 | 6 | ## Initialize the Calendar View 7 | 8 | ``` 9 | let calendarView = HNCalendarView() 10 | ``` 11 | 12 | ## Overriding Preferences 13 | 14 | ``` 15 | var preferences = HNCalendarView.Preferences() 16 | preferences.calendar.backgroundColor = NSColor.grayColor() 17 | preferences.calendar.textColor = NSColor.whiteColor() 18 | 19 | preferences.date.circleBackgroundColor = NSColor.yellowColor() 20 | preferences.date.dotColor = NSColor.greenColor() 21 | 22 | HNCalendarView.globalPreferences = preferences 23 | ``` 24 | 25 | ## Add Calendar to the view hierarchy 26 | 27 | ``` 28 | addChildViewController(calendarView) 29 | calendarView.view.frame = containerView.frame 30 | view.addSubview(calendarView.view) 31 | ``` 32 | 33 | ## Set the calendar properties 34 | 35 | ``` 36 | calendarView.counts = generateCounts() 37 | calendarView.selectedDate = NSDate() 38 | ``` 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/swift 2 | 3 | ### Swift ### 4 | # Xcode 5 | # 6 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 7 | 8 | ## Build generated 9 | build/ 10 | DerivedData 11 | 12 | ## Various settings 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | xcuserdata 22 | 23 | ## Other 24 | *.xccheckout 25 | *.moved-aside 26 | *.xcuserstate 27 | *.xcscmblueprint 28 | 29 | ## Obj-C/Swift specific 30 | *.hmap 31 | *.ipa 32 | 33 | # CocoaPods 34 | # 35 | # We recommend against adding the Pods directory to your .gitignore. However 36 | # you should judge for yourself, the pros and cons are mentioned at: 37 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 38 | # 39 | # Pods/ 40 | 41 | # Carthage 42 | # 43 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 44 | Carthage/Checkouts 45 | 46 | Carthage/Build 47 | 48 | -------------------------------------------------------------------------------- /Pods/SwiftDate/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 daniele margutti 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /HNCalendarViewTests/HNCalendarViewTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HNCalendarViewTests.swift 3 | // HNCalendarViewTests 4 | // 5 | // Created by Harry Ng on 4/4/2016. 6 | // Copyright © 2016 STAY REAL LIMITED. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import HNCalendarView 11 | 12 | class HNCalendarViewTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /HNCalendarView/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /HNCalendarView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | NSHumanReadableCopyright 28 | Copyright © 2016 STAY REAL LIMITED. All rights reserved. 29 | NSMainStoryboardFile 30 | Main 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-HNCalendarView/Pods-HNCalendarView-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## SwiftDate 5 | 6 | Copyright (c) 2015 daniele margutti 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | Generated by CocoaPods - http://cocoapods.org 27 | -------------------------------------------------------------------------------- /HNCalendarViewUITests/HNCalendarViewUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HNCalendarViewUITests.swift 3 | // HNCalendarViewUITests 4 | // 5 | // Created by Harry Ng on 4/4/2016. 6 | // Copyright © 2016 STAY REAL LIMITED. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class HNCalendarViewUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Source/Classes/Views/HNDateItem.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HNDateItem.swift 3 | // HNCalendarView 4 | // 5 | // Created by Harry Ng on 8/4/2016. 6 | // Copyright © 2016 STAY REAL LIMITED. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class HNDateItem: NSCollectionViewItem { 12 | 13 | @IBOutlet weak var itemView: HNDateItemView! 14 | 15 | var count: Int = 0 { 16 | didSet { 17 | if count <= 0 { 18 | itemView.dotLayer?.hidden = true 19 | } else { 20 | itemView.dotLayer?.hidden = false 21 | } 22 | } 23 | } 24 | 25 | override var selected: Bool { 26 | didSet { 27 | updateStyles() 28 | } 29 | } 30 | 31 | @IBOutlet weak var dateField: NSTextField! 32 | 33 | var inCurrentMonth: Bool = true { 34 | didSet { 35 | dateField.alphaValue = inCurrentMonth ? 1.0 : 0.3 36 | } 37 | } 38 | 39 | override func viewDidLoad() { 40 | super.viewDidLoad() 41 | // Do view setup here. 42 | } 43 | 44 | func configure(day: Int, inCurrentMonth: Bool) { 45 | dateField.stringValue = "\(day)" 46 | dateField.textColor = HNCalendarView.globalPreferences.calendar.textColor 47 | 48 | self.inCurrentMonth = inCurrentMonth 49 | } 50 | 51 | private func updateStyles() { 52 | 53 | itemView.circleLayer.hidden = !selected 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /Source/Classes/Views/HNDateItemView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HNDateItemView.swift 3 | // HNCalendarView 4 | // 5 | // Created by Harry Ng on 12/4/2016. 6 | // Copyright © 2016 STAY REAL LIMITED. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | @IBDesignable class HNDateItemView: NSView { 12 | 13 | var circleLayer: CALayer! 14 | var dotLayer: CALayer! 15 | 16 | override init(frame frameRect: NSRect) { 17 | super.init(frame: frameRect) 18 | commonInit() 19 | } 20 | 21 | required init?(coder: NSCoder) { 22 | super.init(coder: coder) 23 | commonInit() 24 | } 25 | 26 | func commonInit() { 27 | let preferences = HNCalendarView.globalPreferences 28 | 29 | wantsLayer = true 30 | 31 | circleLayer = CALayer() 32 | let dimension = floor(min(bounds.width, bounds.height) - 4) 33 | circleLayer.frame = NSMakeRect(2, 2, dimension, dimension) 34 | circleLayer.cornerRadius = dimension / 2 35 | circleLayer.backgroundColor = preferences.date.circleBackgroundColor.CGColor 36 | circleLayer.masksToBounds = false 37 | circleLayer.hidden = true 38 | layer?.addSublayer(circleLayer) 39 | 40 | dotLayer = CALayer() 41 | dotLayer.frame = NSMakeRect(bounds.width / 2 - 2, 4, 4, 4) 42 | dotLayer.cornerRadius = 2 43 | dotLayer.backgroundColor = preferences.date.dotColor.CGColor 44 | dotLayer.hidden = true 45 | layer?.addSublayer(dotLayer) 46 | } 47 | 48 | override func prepareForInterfaceBuilder() { 49 | layer?.backgroundColor = NSColor.darkGrayColor().CGColor 50 | circleLayer.hidden = false 51 | dotLayer.hidden = false 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /HNCalendarView/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // HNCalendarView 4 | // 5 | // Created by Harry Ng on 4/4/2016. 6 | // Copyright © 2016 STAY REAL LIMITED. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | 11 | class ViewController: NSViewController { 12 | 13 | @IBOutlet weak var containerView: NSView! 14 | let calendarView = HNCalendarView() 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | 19 | // Do any additional setup after loading the view. 20 | 21 | // Step 1 - Override Style 22 | var preferences = HNCalendarView.Preferences() 23 | preferences.calendar.backgroundColor = NSColor.grayColor() 24 | preferences.calendar.textColor = NSColor.whiteColor() 25 | 26 | preferences.date.circleBackgroundColor = NSColor.yellowColor() 27 | preferences.date.dotColor = NSColor.greenColor() 28 | 29 | HNCalendarView.globalPreferences = preferences 30 | 31 | // Step 2 - Add calendar to view hierarchy 32 | addChildViewController(calendarView) 33 | calendarView.view.frame = containerView.frame 34 | view.addSubview(calendarView.view) 35 | 36 | // Step 3 - Set properties 37 | // Set selected date 38 | calendarView.selectedDate = NSDate() 39 | // Showing dots 40 | calendarView.counts = generateCounts() 41 | } 42 | 43 | override var representedObject: AnyObject? { 44 | didSet { 45 | // Update the view, if already loaded. 46 | } 47 | } 48 | 49 | func generateCounts() -> [Int] { 50 | 51 | var counts = [Int]() 52 | for i in 0.. Bool { 41 | return left.isEqualToDate(right) 42 | } 43 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-HNCalendarView/Pods-HNCalendarView-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2015 daniele margutti <me@danielemargutti.com> 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | 37 | Title 38 | SwiftDate 39 | Type 40 | PSGroupSpecifier 41 | 42 | 43 | FooterText 44 | Generated by CocoaPods - http://cocoapods.org 45 | Title 46 | 47 | Type 48 | PSGroupSpecifier 49 | 50 | 51 | StringsTable 52 | Acknowledgements 53 | Title 54 | Acknowledgements 55 | 56 | 57 | -------------------------------------------------------------------------------- /Pods/SwiftDate/Sources/SwiftDate/NSTimeInterval+SwiftDate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftDate, an handy tool to manage date and timezones in swift 3 | // Created by: Daniele Margutti 4 | // Main contributors: Jeroen Houtzager 5 | // 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import Foundation 26 | 27 | public extension NSTimeInterval { 28 | 29 | /// Returns an NSDate object initialized relative to the current date and time 30 | /// by a given number of seconds. 31 | public var fromNow: NSDate? { 32 | return NSDate(timeIntervalSinceNow: self) 33 | } 34 | 35 | /// Returns an NSDate object initialized relative to the current date and time 36 | /// by a given number of seconds in the past 37 | public var ago: NSDate? { 38 | return NSDate(timeIntervalSinceNow: -self) 39 | } 40 | 41 | /** 42 | Convert a time interval to a formatted string representing its absolute value 43 | 44 | - parameter style: style attributes to use 45 | 46 | - returns: a formatted string or nil if formatter fails 47 | */ 48 | public func toString(style: FormatterStyle = FormatterStyle()) -> String? { 49 | let formatter: NSDateComponentsFormatter = sharedDateComponentsFormatter() 50 | return formatter.beginSessionContext({ (Void) -> (String?) in 51 | style.restoreInto(formatter) 52 | return formatter.stringFromTimeInterval(self) 53 | }) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Pods/SwiftDate/Sources/SwiftDate/NSDateInterval.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftDate, an handy tool to manage date and timezones in swift 3 | // Created by: Daniele Margutti 4 | // Main contributors: Jeroen Houtzager 5 | // 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import Foundation 26 | 27 | /// Alternative API from swift.org for avoiding AutoreleasingUnsafeMutablePointer usage in 28 | /// NSCalendar and NSFormatter 29 | /// - Experiment: This is a draft API currently under consideration for official import into 30 | /// Foundation as a suitable alternative to the AutoreleasingUnsafeMutablePointer usage case of 31 | /// returning a NSDate + NSTimeInterval or using a pair of dates representing a range 32 | /// - Note: Since this API is under consideration it may be either removed or revised in the near 33 | /// future 34 | /// 35 | public class NSDateInterval: NSObject { 36 | public internal(set) var start: NSDate 37 | public internal(set) var end: NSDate 38 | 39 | public var interval: NSTimeInterval { 40 | return end.timeIntervalSinceReferenceDate - start.timeIntervalSinceReferenceDate 41 | } 42 | 43 | public required init(start: NSDate, end: NSDate) { 44 | self.start = start 45 | self.end = end 46 | } 47 | 48 | public convenience init(start: NSDate, interval: NSTimeInterval) { 49 | self.init(start: start, end: NSDate(timeInterval: interval, sinceDate: start)) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /Source/Assets/HNWeekItem.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Source/Assets/HNDateItem.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Source/Assets/HNMonthItem.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Pods/SwiftDate/Sources/SwiftDate/DateInRegion+StartEnd.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftDate, an handy tool to manage date and timezones in swift 3 | // Created by: Daniele Margutti 4 | // Main contributors: Jeroen Houtzager 5 | // 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import Foundation 26 | 27 | // MARK: - start of and end of operations 28 | 29 | public extension DateInRegion { 30 | 31 | /// Takes a date unit and returns a date at the start of that unit. 32 | /// E.g. DateInRegion().startOf(.Year) would return last New Year at midnight. 33 | /// 34 | /// - Parameters: 35 | /// - unit: calendrical unit. 36 | /// 37 | /// - Returns: a date at the start of the unit 38 | /// 39 | /// - note: This value is interpreted in the context of the calendar with which it is used 40 | /// 41 | public func startOf(unit: NSCalendarUnit) -> DateInRegion { 42 | let absoluteTime = calendar.rangeOfUnit(unit, forDate: self.absoluteTime)!.start 43 | return DateInRegion(absoluteTime: absoluteTime, region: self.region) 44 | } 45 | 46 | /// Takes a date unit and returns a date at the end of that unit. 47 | /// E.g. DateInRegion().endOf(.Year) would return 31 December of this year at 23:59:59.999. 48 | /// That is, if a Georgian calendar is used. 49 | /// 50 | /// - Parameters: 51 | /// - unit: calendrical unit. 52 | /// 53 | /// - Returns: a date at the end of the unit 54 | /// 55 | /// - note: This value is interpreted in the context of the calendar with which it is used 56 | /// 57 | public func endOf(unit: NSCalendarUnit) -> DateInRegion { 58 | // RangeOfUnit returns the start of the next unit; we will subtract one thousandth of a 59 | // second 60 | let startOfNextUnit = calendar.rangeOfUnit(unit, forDate: self.absoluteTime)!.end 61 | let endOfThisUnit = NSDate(timeInterval: -0.001, sinceDate: startOfNextUnit) 62 | return DateInRegion(absoluteTime: endOfThisUnit, region: self.region) 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /HNCalendarView.xcodeproj/xcshareddata/xcschemes/HNCalendarView-OSX.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | >>>>>> carthage 24 | BlueprintName = "HNCalendarView-OSX" 25 | ReferencedContainer = "container:HNCalendarView.xcodeproj"> 26 | 27 | 28 | 29 | 30 | 35 | 36 | 37 | 38 | 39 | 40 | 50 | 51 | >>>>>> carthage 60 | BlueprintName = "HNCalendarView-OSX" 61 | ReferencedContainer = "container:HNCalendarView.xcodeproj"> 62 | 63 | 64 | 65 | 66 | 67 | 73 | 74 | >>>>>> carthage 83 | BlueprintName = "HNCalendarView-OSX" 84 | ReferencedContainer = "container:HNCalendarView.xcodeproj"> 85 | 86 | 87 | 88 | 90 | 91 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-HNCalendarView/Pods-HNCalendarView-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | 86 | if [[ "$CONFIGURATION" == "Debug" ]]; then 87 | install_framework "Pods-HNCalendarView/SwiftDate.framework" 88 | fi 89 | if [[ "$CONFIGURATION" == "Release" ]]; then 90 | install_framework "Pods-HNCalendarView/SwiftDate.framework" 91 | fi 92 | -------------------------------------------------------------------------------- /Pods/SwiftDate/Sources/SwiftDate/Dictionary+SwiftDate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftDate, an handy tool to manage date and timezones in swift 3 | // Created by: Daniele Margutti 4 | // Main contributors: Jeroen Houtzager 5 | // 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import Foundation 26 | 27 | // MARK: - Generate a Date from a Dictionary of NSCalendarUnit:Value 28 | 29 | @available(*, deprecated=3.0.5, message="Use NSDateComponents instead") 30 | public typealias DateComponentDictionary = [ NSCalendarUnit: AnyObject ] 31 | 32 | // MARK: - Extension: NSCalendarUnit - 33 | 34 | protocol CalendarAsDictionaryKey: Hashable {} 35 | 36 | extension NSCalendarUnit: CalendarAsDictionaryKey { 37 | public var hashValue: Int { 38 | get { 39 | return Int(self.rawValue) 40 | } 41 | } 42 | } 43 | 44 | extension Dictionary where Value: AnyObject, Key: CalendarAsDictionaryKey { 45 | 46 | func components() -> NSDateComponents { 47 | let components = NSDateComponents() 48 | for (key, value) in self { 49 | if let value = value as? Int { 50 | if let key = key as? NSCalendarUnit { 51 | components.setValue(value, forComponent: key) 52 | } 53 | } else if let value = value as? NSCalendar { 54 | components.calendar = value 55 | } else if let value = value as? NSTimeZone { 56 | components.timeZone = value 57 | } 58 | } 59 | return components 60 | } 61 | 62 | /** 63 | Convert a dictionary of in a DateInRegion. Both timeZone and calendar 64 | must be specified into the dictionary. You can also specify a locale; if nil UTCRegion()'s 65 | locale will be used instead. 66 | 67 | - returns: DateInRegion if date components are complete, nil if cannot be used to generate a 68 | valid date 69 | */ 70 | func dateInRegion() -> DateInRegion? { 71 | return DateInRegion(self.components()) 72 | } 73 | 74 | func dateRegion() -> Region? { 75 | let components = self.components() 76 | 77 | let calendar = components.calendar ?? NSCalendar.currentCalendar() 78 | let timeZone = components.timeZone ?? NSTimeZone.defaultTimeZone() 79 | let locale = calendar.locale ?? NSLocale.currentLocale() 80 | 81 | return Region(calendar: calendar, timeZone: timeZone, locale: locale) 82 | } 83 | 84 | /** 85 | Convert a dictionary of in absolute time NSDate instance. Both timeZone 86 | and calendar must be specified into the dictionary. You can also specify a locale; if nil 87 | default locale will be used instead. 88 | 89 | - returns: absolute time NSDate object, nil if dictionary values cannot be used to generate a 90 | valid date 91 | */ 92 | func absoluteTime() -> NSDate? { 93 | let date = self.dateInRegion() 94 | return date?.absoluteTime 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /Pods/SwiftDate/README.md: -------------------------------------------------------------------------------- 1 | ![SwiftDate](https://raw.githubusercontent.com/malcommac/SwiftDate/master/swiftdate-logo.png) 2 | 3 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![CI Status](https://travis-ci.org/malcommac/SwiftDate.svg)](https://travis-ci.org/malcommac/SwiftDate) [![Version](https://img.shields.io/cocoapods/v/SwiftDate.svg?style=flat)](http://cocoadocs.org/docsets/SwiftDate) [![License](https://img.shields.io/cocoapods/l/SwiftDate.svg?style=flat)](http://cocoadocs.org/docsets/SwiftDate) [![Platform](https://img.shields.io/cocoapods/p/SwiftDate.svg?style=flat)](http://cocoadocs.org/docsets/SwiftDate) 4 | 5 | Welcome to SwiftDate 3 a Date Management Library for Apple's platforms: the goal of this project is to allow developers to manage easily dates operation and timezones conversions in Swift. SwiftDate allows you to: 6 | - [x] Perform **calculations with dates**: `aDate + 2.weeks + 1.hours` or `(1.years - 2.hours + 16.minutes).fromNow()` 7 | - [x] **Compare dates** with math operators `<,>,==,<=,>=`. For example you can do `aDate1 >= aDate2` or `aDate1.inTimeRange("15:20","20:20")` 8 | - [x] **Easily get time components**. E.g. `aDateInRegion.day` or `hour, minutes etc.` 9 | - [x] Easy/optimized way **to get and transform a date from and to strings** (with **relative date supports*** like '2 hours, 5 minutes' etc.) 10 | - [x] **Easy conversions to and from timezone, locale and calendar**. Use helper class `DateInRegion` and perform conversions with components and operations! 11 | - [x] Many shortcuts to get intervals and common dates (`isYesterday,isTomorrow...`) 12 | - [x] Compatible with Swift 2.0+ and iOS/Mac/WatchOS/tvOS platforms 13 | - [x] _... many many other shiny things!_ 14 | 15 | ## What is `NSDate` really? 16 | `NSDate` is the central class of the date/time handling in Foundation framework. It encapsulates a moment in time that is internally stored as the number of seconds since Jan 1, 2001 at 00:00 UTC. It is [universal](http://en.wikipedia.org/wiki/Coordinated_Universal_Time) as such that it is the same moment everywhere around the world and beyond (we do not have [star date](https://en.wikipedia.org/wiki/Stardate) yet ;-) ). We call it 'absolute time'. 17 | 18 | See absolute time as the moment that someone in the USA has a telephone conversation with someone in Dubai. Both have that conversation at the same moment (absolute time) but the local time will be different due to time zones, different calendars, different alphabets and/or different date notation methods. You need helper classes like `NSCalendar` to represent an `NSDate` object and perform calculations on it. 19 | 20 | This important concept is the root of several problems for programmers when dealing with time conversions across time zones, calendars and locales in Cocoa. Here SwiftDate comes to the rescue. 21 | 22 | # It is time for SwiftDate 23 | 24 | SwiftDate introduces the concepts of `DateRegion` and `DateInRegion`. The former contains everything to represent a moment in time in the calendar, time zone and locale of the region specified. The latter is a combination of an absolute time (`NSDate`) with a `DateRegion` object. See it as an object that encapsulates a moment in time in a certain region. 25 | 26 | In SwiftDate you can work with date components both for `DateInRegion` and `NSDate`. 27 | When you work with `NSDate` you are working with an absolute time and components are evaluated against your local region. When you work with the `DateInRegion` class then all methods and properties are represented with a region that you can specify. 28 | 29 | 30 | # Reference documentation 31 | - [User guide](./Documentation/UserGuide.md) 32 | - [Installation guide](./Documentation/Installation.md) 33 | - [Upgrade guide](./Documentation/UpgradeGuide.md) 34 | - [Design guide](./Documentation/Design.md) 35 | - [Change history](./CHANGELOG.md) 36 | 37 | 38 | # Author 39 | This library was created by [Daniele Margutti](https://github.com/malcommac) with contribution of [Jeroen Houtzager](https://github.com/Hout). Any help is welcome; feel free to post your issue or pull request, in the spirit of open source software. 40 | 41 | # Older Versions 42 | SwiftDate 1.2 branch last revision is available [here](https://github.com/malcommac/SwiftDate/releases/tag/1.2). This version is unsupported. 43 | -------------------------------------------------------------------------------- /Source/Assets/HNCalendarView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 44 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /Pods/SwiftDate/Sources/SwiftDate/DateInRegion+NSDatePort.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftDate, an handy tool to manage date and timezones in swift 3 | // Created by: Daniele Margutti 4 | // Main contributors: Jeroen Houtzager 5 | // 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import Foundation 26 | 27 | extension DateInRegion { 28 | 29 | // swiftlint:disable line_length 30 | 31 | /// Time interval since the reference date at 1 January 2001 32 | /// 33 | /// - Returns: the number of seconds as an NSTimeInterval. 34 | /// 35 | /// - SeeAlso: [timeIntervalSinceReferenceDate](https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/#//apple_ref/occ/instp/NSDate/timeIntervalSinceReferenceDate) 36 | /// 37 | public var timeIntervalSinceReferenceDate: NSTimeInterval { 38 | return absoluteTime.timeIntervalSinceReferenceDate 39 | } 40 | 41 | /// Creates and returns a DateInRegion object representing a date in the distant past (in terms 42 | /// of centuries). 43 | /// 44 | /// - Returns: A ``DateInRegion`` object representing a date in the distant past (in terms of 45 | /// centuries). 46 | /// 47 | public static func distantFuture() -> DateInRegion { 48 | return DateInRegion(absoluteTime: NSDate.distantFuture()) 49 | } 50 | 51 | /// Creates and returns a DateInRegion object representing a date in the distant future (in 52 | /// terms of centuries). 53 | /// 54 | /// - Returns: A ``DateInRegion`` object representing a date in the distant future (in terms of 55 | /// centuries). 56 | /// 57 | public static func distantPast() -> DateInRegion { 58 | return DateInRegion(absoluteTime: NSDate.distantPast()) 59 | } 60 | 61 | /// Returns a DateInRegion object representing a date that is the earliest from a given range 62 | /// of dates. 63 | /// The dates are compared in absolute time, i.e. time zones, locales and calendars have no 64 | /// effect on the comparison. 65 | /// 66 | /// - Parameters: 67 | /// - dates: a number of dates to be evaluated 68 | /// 69 | /// - Returns: a ``DateInRegion`` object representing a date that is the earliest from a given 70 | /// range of dates. 71 | /// 72 | public static func earliestDate(dates: DateInRegion ...) -> DateInRegion { 73 | var currentMinimum = DateInRegion.distantFuture() 74 | for thisDate in dates { 75 | if currentMinimum > thisDate { 76 | currentMinimum = thisDate 77 | } 78 | } 79 | return currentMinimum 80 | } 81 | 82 | /// Returns a DateInRegion object representing a date that is the latest from a given range of 83 | /// dates. The dates are compared in absolute time, i.e. time zones, locales and calendars have 84 | /// no effect on the comparison. 85 | /// 86 | /// - Parameters: 87 | /// - dates: a number of dates to be evaluated 88 | /// 89 | /// - Returns: a ``DateInRegion`` object representing a date that is the latest from a given 90 | /// range of dates. 91 | /// 92 | public static func latestDate(dates: DateInRegion ...) -> DateInRegion { 93 | var currentMaximum = DateInRegion.distantPast() 94 | for thisDate in dates { 95 | if currentMaximum < thisDate { 96 | currentMaximum = thisDate 97 | } 98 | } 99 | return currentMaximum 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /HNCalendarView.xcodeproj/xcshareddata/xcschemes/HNCalendarView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-HNCalendarView/Pods-HNCalendarView-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | realpath() { 12 | DIRECTORY="$(cd "${1%/*}" && pwd)" 13 | FILENAME="${1##*/}" 14 | echo "$DIRECTORY/$FILENAME" 15 | } 16 | 17 | install_resource() 18 | { 19 | case $1 in 20 | *.storyboard) 21 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 22 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .storyboard`.storyboardc" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 23 | ;; 24 | *.xib) 25 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib ${PODS_ROOT}/$1 --sdk ${SDKROOT}" 26 | ibtool --reference-external-strings-file --errors --warnings --notices --output-format human-readable-text --compile "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$1\" .xib`.nib" "${PODS_ROOT}/$1" --sdk "${SDKROOT}" 27 | ;; 28 | *.framework) 29 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 30 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 31 | echo "rsync -av ${PODS_ROOT}/$1 ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 32 | rsync -av "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 33 | ;; 34 | *.xcdatamodel) 35 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1"`.mom\"" 36 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodel`.mom" 37 | ;; 38 | *.xcdatamodeld) 39 | echo "xcrun momc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd\"" 40 | xcrun momc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcdatamodeld`.momd" 41 | ;; 42 | *.xcmappingmodel) 43 | echo "xcrun mapc \"${PODS_ROOT}/$1\" \"${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm\"" 44 | xcrun mapc "${PODS_ROOT}/$1" "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$1" .xcmappingmodel`.cdm" 45 | ;; 46 | *.xcassets) 47 | ABSOLUTE_XCASSET_FILE=$(realpath "${PODS_ROOT}/$1") 48 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 49 | ;; 50 | /*) 51 | echo "$1" 52 | echo "$1" >> "$RESOURCES_TO_COPY" 53 | ;; 54 | *) 55 | echo "${PODS_ROOT}/$1" 56 | echo "${PODS_ROOT}/$1" >> "$RESOURCES_TO_COPY" 57 | ;; 58 | esac 59 | } 60 | 61 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 62 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 63 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 64 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 65 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 66 | fi 67 | rm -f "$RESOURCES_TO_COPY" 68 | 69 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 70 | then 71 | case "${TARGETED_DEVICE_FAMILY}" in 72 | 1,2) 73 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 74 | ;; 75 | 1) 76 | TARGET_DEVICE_ARGS="--target-device iphone" 77 | ;; 78 | 2) 79 | TARGET_DEVICE_ARGS="--target-device ipad" 80 | ;; 81 | *) 82 | TARGET_DEVICE_ARGS="--target-device mac" 83 | ;; 84 | esac 85 | 86 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 87 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 88 | while read line; do 89 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 90 | XCASSET_FILES+=("$line") 91 | fi 92 | done <<<"$OTHER_XCASSETS" 93 | 94 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${IPHONEOS_DEPLOYMENT_TARGET}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 95 | fi 96 | -------------------------------------------------------------------------------- /HNCalendarView.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint HNCalendarView.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | 11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 12 | # 13 | # These will help people to find your library, and whilst it 14 | # can feel like a chore to fill in it's definitely to your advantage. The 15 | # summary should be tweet-length, and the description more in depth. 16 | # 17 | 18 | s.name = "HNCalendarView" 19 | s.version = "0.0.0" 20 | s.summary = "CalendarView framework written in Swift for OS X" 21 | 22 | # This description is used to generate tags and improve search results. 23 | # * Think: What does it do? Why did you write it? What is the focus? 24 | # * Try to keep it short, snappy and to the point. 25 | # * Write the description between the DESC delimiters below. 26 | # * Finally, don't worry about the indent, CocoaPods strips it! 27 | s.description = <<-DESC 28 | DESC 29 | 30 | s.homepage = "https://github.com/harryworld/HNCalendarView" 31 | # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" 32 | 33 | 34 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 35 | # 36 | # Licensing your code is important. See http://choosealicense.com for more info. 37 | # CocoaPods will detect a license file if there is a named LICENSE* 38 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. 39 | # 40 | 41 | s.license = "MIT (example)" 42 | # s.license = { :type => "MIT", :file => "FILE_LICENSE" } 43 | 44 | 45 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 46 | # 47 | # Specify the authors of the library, with email addresses. Email addresses 48 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also 49 | # accepts just a name if you'd rather not provide an email address. 50 | # 51 | # Specify a social_media_url where others can refer to, for example a twitter 52 | # profile URL. 53 | # 54 | 55 | s.author = { "Harry Ng" => "harryworld@gmail.com" } 56 | # Or just: s.author = "Harry Ng" 57 | # s.authors = { "Harry Ng" => "email@address.com" } 58 | s.social_media_url = "http://twitter.com/harryworld" 59 | 60 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 61 | # 62 | # If this Pod runs only on iOS or OS X, then specify the platform and 63 | # the deployment target. You can optionally include the target after the platform. 64 | # 65 | 66 | s.platform = :osx, "10.11" 67 | # s.platform = :ios, "5.0" 68 | 69 | # When using multiple platforms 70 | # s.ios.deployment_target = "5.0" 71 | # s.osx.deployment_target = "10.7" 72 | # s.watchos.deployment_target = "2.0" 73 | # s.tvos.deployment_target = "9.0" 74 | 75 | 76 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 77 | # 78 | # Specify the location from where the source should be retrieved. 79 | # Supports git, hg, bzr, svn and HTTP. 80 | # 81 | 82 | s.source = { :git => "https://github.com/harryworld/HNCalendarView.git" } 83 | 84 | 85 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 86 | # 87 | # CocoaPods is smart about how it includes source code. For source files 88 | # giving a folder will include any swift, h, m, mm, c & cpp files. 89 | # For header files it will include any header in the folder. 90 | # Not including the public_header_files will make all headers public. 91 | # 92 | 93 | s.source_files = "Source/Classes/**/*" 94 | # s.exclude_files = "Classes/Exclude" 95 | 96 | # s.public_header_files = "Classes/**/*.h" 97 | 98 | 99 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 100 | # 101 | # A list of resources included with the Pod. These are copied into the 102 | # target bundle with a build phase script. Anything else will be cleaned. 103 | # You can preserve files from being cleaned, please don't preserve 104 | # non-essential files like tests, examples and documentation. 105 | # 106 | 107 | # s.resource = "icon.png" 108 | s.resources = "Source/Assets/**/*" 109 | 110 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave" 111 | 112 | 113 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 114 | # 115 | # Link your library with frameworks, or libraries. Libraries do not include 116 | # the lib prefix of their name. 117 | # 118 | 119 | # s.framework = "SomeFramework" 120 | # s.frameworks = "SomeFramework", "AnotherFramework" 121 | 122 | # s.library = "iconv" 123 | # s.libraries = "iconv", "xml2" 124 | 125 | 126 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 127 | # 128 | # If your library depends on compiler flags you can set them in the xcconfig hash 129 | # where they will only apply to your library. If you depend on other Podspecs 130 | # you can include multiple dependencies to ensure it works. 131 | 132 | # s.requires_arc = true 133 | 134 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } 135 | s.dependency "SwiftDate", "~> 3" 136 | 137 | end 138 | -------------------------------------------------------------------------------- /Pods/SwiftDate/Sources/SwiftDate/DateInRegion+Operations.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftDate, an handy tool to manage date and timezones in swift 3 | // Created by: Daniele Margutti 4 | // Main contributors: Jeroen Houtzager 5 | // 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import Foundation 26 | 27 | // MARK: - Operators 28 | 29 | public extension DateInRegion { 30 | 31 | /// Returns, as an NSDateComponents object using specified components, the difference between 32 | /// the receiver and the supplied date. 33 | /// 34 | /// - Parameters: 35 | /// - toDate: a date to calculate against 36 | /// - unitFlags: Specifies the components for the returned NSDateComponents object 37 | /// 38 | /// - Returns: An NSDateComponents object whose components are specified by unitFlags and 39 | /// calculated from the difference between the resultDate and startDate. 40 | /// 41 | /// - note: This value is calculated in the context of the calendar of the receiver 42 | /// 43 | public func difference(toDate: DateInRegion, unitFlags: NSCalendarUnit) -> NSDateComponents? { 44 | return calendar.components(unitFlags, fromDate: self.absoluteTime, 45 | toDate: toDate.absoluteTime, options: NSCalendarOptions(rawValue: 0)) 46 | } 47 | 48 | public func add(years years: Int? = nil, months: Int? = nil, weeks: Int? = nil, 49 | days: Int? = nil, hours: Int? = nil, minutes: Int? = nil, seconds: Int? = nil, 50 | nanoseconds: Int? = nil) -> DateInRegion { 51 | 52 | let components = NSDateComponents() 53 | 54 | components.year = years ?? NSDateComponentUndefined 55 | components.month = months ?? NSDateComponentUndefined 56 | components.weekOfYear = weeks ?? NSDateComponentUndefined 57 | components.day = days ?? NSDateComponentUndefined 58 | components.hour = hours ?? NSDateComponentUndefined 59 | components.minute = minutes ?? NSDateComponentUndefined 60 | components.second = seconds ?? NSDateComponentUndefined 61 | components.nanosecond = nanoseconds ?? NSDateComponentUndefined 62 | 63 | let newDate = self.add(components) 64 | return newDate 65 | } 66 | 67 | public func add(components: NSDateComponents) -> DateInRegion { 68 | let absoluteTime = region.calendar.dateByAddingComponents(components, 69 | toDate: self.absoluteTime, options: NSCalendarOptions(rawValue: 0))! 70 | return DateInRegion(absoluteTime: absoluteTime, region: self.region) 71 | } 72 | 73 | public func add(components dict: [NSCalendarUnit : AnyObject]) -> DateInRegion { 74 | let components = dict.components() 75 | return self.add(components) 76 | } 77 | } 78 | 79 | /// Returns a new DateInRegion object representing a new time calculated by subtracting given right 80 | /// hand components from the left hand date. 81 | /// 82 | /// - Parameters: 83 | /// - lhs: the date to subtract components from 84 | /// - rhs: the components to subtract from the date 85 | /// 86 | /// - Returns: A new DateInRegion object representing the time calculated by subtracting from date 87 | /// the calendrical components specified by components. 88 | /// 89 | /// - note: This value is calculated in the context of the calendar of the date 90 | /// 91 | public func - (lhs: DateInRegion, rhs: NSDateComponents) -> DateInRegion { 92 | return lhs + (-rhs) 93 | } 94 | 95 | /// Returns a new DateInRegion object representing a new time calculated by adding given right hand 96 | /// components to the left hand date. 97 | /// 98 | /// - Parameters: 99 | /// - lhs: the date to add the components to 100 | /// - rhs: the components to add to the date 101 | /// 102 | /// - Returns: A new DateInRegion object representing the time calculated by adding to date the 103 | /// calendrical components specified by components. 104 | /// 105 | /// - note: This value is calculated in the context of the calendar of the date 106 | /// 107 | public func + (lhs: DateInRegion, rhs: NSDateComponents) -> DateInRegion { 108 | return lhs.add(rhs) 109 | } 110 | 111 | 112 | /// Returns a new NSDateComponents object representing the negative values of components that are 113 | /// submitted 114 | /// 115 | /// - Parameters: 116 | /// - dateComponents: the components to process 117 | /// 118 | /// - Returns: A new NSDateComponents object representing the negative values of components that 119 | /// are submitted 120 | /// 121 | public prefix func - (dateComponents: NSDateComponents) -> NSDateComponents { 122 | let result = NSDateComponents() 123 | for unit in DateInRegion.componentFlagSet { 124 | let value = dateComponents.valueForComponent(unit) 125 | if value != Int(NSDateComponentUndefined) { 126 | result.setValue(-value, forComponent: unit) 127 | } 128 | } 129 | return result 130 | } 131 | -------------------------------------------------------------------------------- /Source/Classes/HNCalendarView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HNCalendarView.swift 3 | // HNCalendarView 4 | // 5 | // Created by Harry Ng on 5/4/2016. 6 | // Copyright © 2016 STAY REAL LIMITED. All rights reserved. 7 | // 8 | 9 | import Cocoa 10 | import SwiftDate 11 | 12 | public class HNCalendarView: NSViewController { 13 | 14 | public struct Preferences { 15 | 16 | public struct Calendar { 17 | public var backgroundColor = NSColor.clearColor() 18 | public var textColor = NSColor.blackColor() 19 | } 20 | 21 | public struct Date { 22 | public var circleBackgroundColor = NSColor.redColor() 23 | public var dotColor = NSColor.blueColor() 24 | } 25 | 26 | public var calendar = Calendar() 27 | public var date = Date() 28 | 29 | public init() {} 30 | 31 | } 32 | 33 | public static var globalPreferences = Preferences() 34 | 35 | // Today 36 | let date = NSDate() 37 | // Selected Date 38 | public var selectedDate: NSDate = NSDate() { 39 | didSet { 40 | selectSelectedDateItem() 41 | } 42 | } 43 | 44 | public var counts: [Int]? 45 | 46 | @IBOutlet weak var collectionView: NSCollectionView! 47 | 48 | enum Section: Int { 49 | case Month = 0, Week, Date 50 | } 51 | 52 | public init() { 53 | super.init(nibName: "HNCalendarView", bundle: NSBundle(forClass: HNCalendarView.self))! 54 | } 55 | 56 | required public init?(coder: NSCoder) { 57 | fatalError("init(coder:) has not been implemented") 58 | } 59 | 60 | override public func viewDidLoad() { 61 | super.viewDidLoad() 62 | // Do view setup here. 63 | 64 | collectionView.backgroundColors = [HNCalendarView.globalPreferences.calendar.backgroundColor] 65 | } 66 | 67 | override public func viewDidAppear() { 68 | 69 | } 70 | 71 | private func selectSelectedDateItem() { 72 | if let selectedIndexPath = indexPathForDate(selectedDate) { 73 | collectionView?.selectItemsAtIndexPaths([selectedIndexPath], scrollPosition: .None) 74 | } 75 | } 76 | 77 | func indexPathForDate(selectedDate: NSDate) -> NSIndexPath? { 78 | 79 | if date.month == selectedDate.month { 80 | let item = date.startOf(.Month).weekday + selectedDate.day - 2 81 | return NSIndexPath(forItem: item, inSection: Section.Date.rawValue) 82 | } 83 | return nil 84 | } 85 | 86 | } 87 | 88 | extension HNCalendarView: NSCollectionViewDataSource { 89 | 90 | public func numberOfSectionsInCollectionView(collectionView: NSCollectionView) -> Int { 91 | return 3 92 | } 93 | 94 | public func collectionView(collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int { 95 | 96 | switch Section(rawValue: section)! { 97 | case .Month: 98 | return 1 99 | case .Week: 100 | return 7 101 | case .Date: 102 | return 7 * 6 103 | } 104 | } 105 | 106 | public func collectionView(collectionView: NSCollectionView, itemForRepresentedObjectAtIndexPath indexPath: NSIndexPath) -> NSCollectionViewItem { 107 | 108 | var item: NSCollectionViewItem 109 | 110 | switch Section(rawValue: indexPath.section)! { 111 | case .Month: 112 | item = collectionView.makeItemWithIdentifier("HNMonthItem", forIndexPath: indexPath) 113 | 114 | if let item = item as? HNMonthItem { 115 | item.configure(HNCalendar.Month[date.month - 1], year: date.year) 116 | } 117 | case .Week: 118 | item = collectionView.makeItemWithIdentifier("HNWeekItem", forIndexPath: indexPath) 119 | 120 | if let item = item as? HNWeekItem { 121 | item.configure(HNCalendar.Week[indexPath.item]) 122 | } 123 | case .Date: 124 | 125 | let (day, inMonth) = dayInMonthForItem(indexPath.item) 126 | 127 | item = collectionView.makeItemWithIdentifier("HNDateItem", forIndexPath: indexPath) 128 | 129 | if let item = item as? HNDateItem { 130 | item.configure(day, inCurrentMonth: inMonth) 131 | 132 | if let counts = counts where inMonth { 133 | item.count = counts[day - 1] 134 | } else { 135 | item.count = 0 136 | } 137 | } 138 | } 139 | 140 | return item 141 | } 142 | 143 | // MARK: - Private 144 | 145 | private func dayInMonthForItem(item: Int) -> (Int, Bool) { 146 | 147 | var day: Int 148 | var inMonth = false 149 | 150 | if item < date.startOf(.Month).weekday - 1 { 151 | day = dayForItem(item) + 1.months.fromDate(date).monthDays 152 | } else if item - date.startOf(.Month).weekday < date.monthDays - 1 { 153 | day = dayForItem(item) 154 | inMonth = true 155 | } else { 156 | day = dayForItem(item) - date.monthDays 157 | } 158 | 159 | return (day, inMonth) 160 | } 161 | 162 | private func dayForItem(item: Int) -> Int { 163 | return item - date.startOf(.Month).weekday + 2 164 | } 165 | 166 | } 167 | 168 | extension HNCalendarView: NSCollectionViewDelegate { 169 | 170 | } 171 | 172 | extension HNCalendarView: NSCollectionViewDelegateFlowLayout { 173 | 174 | public func collectionView(collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> NSSize { 175 | 176 | let width = collectionView.bounds.width 177 | 178 | switch Section(rawValue: indexPath.section)! { 179 | case .Month: 180 | return NSMakeSize(width, 50) 181 | case .Week: 182 | return NSMakeSize(width / 7, 30) 183 | case .Date: 184 | return NSMakeSize(width / 7, 40) 185 | } 186 | 187 | } 188 | 189 | } 190 | -------------------------------------------------------------------------------- /Pods/SwiftDate/Sources/SwiftDate/Region.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftDate, an handy tool to manage date and timezones in swift 3 | // Created by: Daniele Margutti 4 | // Main contributors: Jeroen Houtzager 5 | // 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import Foundation 26 | 27 | // Backward compatibility resolves issue https://github.com/malcommac/SwiftDate/issues/121 28 | // 29 | @available(*, renamed="DateRegion") 30 | public typealias DateRegion = Region 31 | 32 | /// Region encapsulates all objects you need when representing a date from an absolute time like 33 | /// NSDate. 34 | /// 35 | @available(*, introduced=2.0) 36 | public struct Region: Equatable { 37 | 38 | /// Calendar to interpret date values. You can alter the calendar to adjust the representation 39 | /// of date to your needs. 40 | /// 41 | public let calendar: NSCalendar! 42 | 43 | /// Time zone to interpret date values 44 | /// Because the time zone is part of calendar, this is a shortcut to that variable. 45 | /// You can alter the time zone to adjust the representation of date to your needs. 46 | /// 47 | public var timeZone: NSTimeZone { 48 | return self.calendar.timeZone 49 | } 50 | 51 | /// Locale to interpret date values 52 | /// Because the locale is part of calendar, this is a shortcut to that variable. 53 | /// You can alter the locale to adjust the representation of date to your needs. 54 | /// 55 | public var locale: NSLocale { 56 | return self.calendar.locale! 57 | } 58 | 59 | /// Initialise with a calendar and/or a time zone 60 | /// 61 | /// - Parameters: 62 | /// - calendar: the calendar to work with 63 | /// - timeZone: the time zone to work with 64 | /// - locale: the locale to work with 65 | /// 66 | internal init( 67 | calendar: NSCalendar, 68 | timeZone: NSTimeZone? = nil, 69 | locale: NSLocale? = nil) { 70 | 71 | self.calendar = calendar 72 | self.calendar.locale = locale ?? calendar.locale ?? NSLocale.currentLocale() 73 | self.calendar.timeZone = timeZone ?? calendar.timeZone ?? NSTimeZone.defaultTimeZone() 74 | } 75 | 76 | /// Initialise with a date components 77 | /// 78 | /// - Parameters: 79 | /// - components: the date components to initialise with 80 | /// 81 | internal init(_ components: NSDateComponents) { 82 | 83 | let calendar = components.calendar ?? NSCalendar.currentCalendar() 84 | let timeZone = components.timeZone 85 | let locale = calendar.locale 86 | 87 | self.init(calendar: calendar, timeZone: timeZone, locale: locale) 88 | } 89 | 90 | /// Initialise with a calendar and/or a time zone 91 | /// 92 | /// - Parameters: 93 | /// - calendarName: the calendar to work with to assign in `CalendarName` format, default = 94 | /// the current calendar 95 | /// - timeZoneName: the time zone to work with in `TimeZoneConvertible` format, default is 96 | /// the default time zone 97 | /// - localeName: the locale to work with, default is the current locale 98 | /// 99 | public init( 100 | calendarName: CalendarName? = nil, 101 | timeZoneName: TimeZoneName? = nil, 102 | localeName: LocaleName? = nil) { 103 | 104 | let calendar = calendarName?.calendar ?? NSCalendar.currentCalendar() 105 | let timeZone = timeZoneName?.timeZone ?? NSTimeZone.defaultTimeZone() 106 | let locale = localeName?.locale ?? NSLocale.currentLocale() 107 | 108 | self.init(calendar: calendar, timeZone: timeZone, locale: locale) 109 | } 110 | 111 | /// Today's date 112 | /// 113 | /// - Returns: the date of today at midnight (00:00) in the current calendar and default time 114 | /// zone. 115 | /// 116 | public func today() -> DateInRegion { 117 | return DateInRegion(region: self).startOf(.Day) 118 | } 119 | 120 | /// Yesterday's date 121 | /// 122 | /// - Returns: the date of yesterday at midnight (00:00) 123 | /// 124 | public func yesterday() -> DateInRegion { 125 | return today() - 1.days 126 | } 127 | 128 | /// Tomorrow's date 129 | /// 130 | /// - Returns: the date of tomorrow at midnight (00:00) 131 | /// 132 | public func tomorrow() -> DateInRegion { 133 | return today() + 1.days 134 | } 135 | 136 | } 137 | 138 | public func == (left: Region, right: Region) -> Bool { 139 | if left.calendar.calendarIdentifier != right.calendar.calendarIdentifier { 140 | return false 141 | } 142 | 143 | if left.timeZone.secondsFromGMT != right.timeZone.secondsFromGMT { 144 | return false 145 | } 146 | 147 | if left.locale.localeIdentifier != right.locale.localeIdentifier { 148 | return false 149 | } 150 | 151 | return true 152 | } 153 | 154 | extension Region: Hashable { 155 | public var hashValue: Int { 156 | return calendar.hashValue ^ timeZone.hashValue ^ locale.hashValue 157 | } 158 | } 159 | 160 | extension Region: CustomStringConvertible { 161 | public var description: String { 162 | let timeZoneAbbreviation = timeZone.abbreviation ?? "" 163 | return "\(calendar.calendarIdentifier); \(timeZone.name):\(timeZoneAbbreviation); " + 164 | "\(locale.localeIdentifier)" 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /Pods/SwiftDate/Sources/SwiftDate/NSCalendar+SwiftDate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftDate, an handy tool to manage date and timezones in swift 3 | // Created by: Daniele Margutti 4 | // Main contributors: Jeroen Houtzager 5 | // 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import Foundation 26 | 27 | 28 | internal extension NSCalendarUnit { 29 | private var cfValue: CFCalendarUnit { 30 | #if os(OSX) || os(iOS) 31 | return CFCalendarUnit(rawValue: self.rawValue) 32 | #else 33 | return CFCalendarUnit(rawValue: self.rawValue) 34 | #endif 35 | } 36 | } 37 | 38 | //MARK: - Extension: NSCalendar - 39 | 40 | public extension NSCalendar { 41 | 42 | // The code below is part of the Swift.org code. It is included as rangeOfUnit is a very useful 43 | // function for the startOf and endOf functions. 44 | // As always we would prefer using Foundation code rather than inventing code ourselves. 45 | typealias CFType = CFCalendarRef 46 | 47 | private var cfObject: CFType { 48 | return unsafeBitCast(self, CFCalendarRef.self) 49 | } 50 | 51 | 52 | /// Revised API for avoiding usage of AutoreleasingUnsafeMutablePointer. 53 | /// The current exposed API in Foundation on Darwin platforms is: 54 | /// `public func rangeOfUnit(unit: NSCalendarUnit, startDate datep: 55 | /// AutoreleasingUnsafeMutablePointer, interval tip: 56 | /// UnsafeMutablePointer, forDate date: NSDate) -> Bool` 57 | /// which is not implementable on Linux due to the lack of being able to properly implement 58 | /// AutoreleasingUnsafeMutablePointer. 59 | /// 60 | /// - parameters: 61 | /// - unit: the unit to determine the range for 62 | /// - forDate: the date to wrap the unit around 63 | /// - returns: the range (date interval) of the unit around the date 64 | /// 65 | /// - Experiment: This is a draft API currently under consideration for official import into 66 | /// Foundation as a suitable alternative 67 | /// - Note: Since this API is under consideration it may be either removed or revised in the 68 | /// near future 69 | /// 70 | public func rangeOfUnit(unit: NSCalendarUnit, forDate date: NSDate) -> NSDateInterval? { 71 | var start: CFAbsoluteTime = 0.0 72 | var ti: CFTimeInterval = 0.0 73 | let res: Bool = withUnsafeMutablePointers(&start, &ti) { 74 | (startp: UnsafeMutablePointer, 75 | tip: UnsafeMutablePointer) -> Bool in 76 | 77 | let startPtr: UnsafeMutablePointer = 78 | unsafeBitCast(startp, UnsafeMutablePointer.self) 79 | let tiPtr: UnsafeMutablePointer = 80 | unsafeBitCast(tip, UnsafeMutablePointer.self) 81 | return CFCalendarGetTimeRangeOfUnit(cfObject, unit.cfValue, 82 | date.timeIntervalSinceReferenceDate, startPtr, tiPtr) 83 | } 84 | 85 | if res { 86 | return NSDateInterval(start: NSDate(timeIntervalSinceReferenceDate: start), 87 | interval: ti) 88 | } 89 | return nil 90 | } 91 | 92 | /** 93 | Create a new NSCalendar instance from CalendarName structure. You can also use 94 | .calendar to get 95 | a new instance of NSCalendar with picked type. 96 | 97 | - parameter type: type of the calendar 98 | 99 | - returns: instance of the new NSCalendar 100 | */ 101 | public static func fromType(type: CalendarName) -> NSCalendar! { 102 | return type.calendar 103 | } 104 | 105 | /** 106 | Create a new NSCalendar with current with settings for the current user’s chosen system locale 107 | overlaid with any custom settings the user has specified in System Preferences. Use autoUpdate 108 | = false to avoid auto-changes on Settings changes during runtime. 109 | 110 | - parameter autoUpdate: true to get auto-updating calendar 111 | 112 | - returns: a new NSCalendar instance from system settings 113 | */ 114 | @available(*, deprecated=2.0.3, 115 | message="locale was deprecated, use currentCalendar() or autoupdatingCurrentCalendar() ") 116 | static func locale(autoUpdate: Bool) -> NSCalendar! { 117 | return NSCalendar.fromType(CalendarName.Local(autoUpdate)) 118 | } 119 | } 120 | 121 | 122 | //MARK: - Structure: CalendarName - 123 | 124 | /** 125 | * @brief This structure represent a shortcut from NSCalendar init function. 126 | */ 127 | public enum CalendarName { 128 | 129 | @available(*, deprecated=2.0.3, 130 | message="Local was deprecated, use Current or AutoUpdatingCurrent") 131 | case Local(_: Bool) 132 | case Current 133 | case AutoUpdatingCurrent 134 | case Gregorian, Buddhist, Chinese, Coptic, EthiopicAmeteMihret, EthiopicAmeteAlem, Hebrew, 135 | ISO8601, Indian, Islamic, IslamicCivil, Japanese, Persian, RepublicOfChina, IslamicTabular, 136 | IslamicUmmAlQura 137 | 138 | public var calendar: NSCalendar { 139 | var identifier: String 140 | switch self { 141 | case .Current: return NSCalendar.currentCalendar() 142 | case .AutoUpdatingCurrent: return NSCalendar.autoupdatingCurrentCalendar() 143 | case .Gregorian: identifier = NSCalendarIdentifierGregorian 144 | case .Buddhist: identifier = NSCalendarIdentifierBuddhist 145 | case .Chinese: identifier = NSCalendarIdentifierChinese 146 | case .Coptic: identifier = NSCalendarIdentifierCoptic 147 | case .EthiopicAmeteMihret: identifier = NSCalendarIdentifierEthiopicAmeteMihret 148 | case .EthiopicAmeteAlem: identifier = NSCalendarIdentifierEthiopicAmeteAlem 149 | case .Hebrew: identifier = NSCalendarIdentifierHebrew 150 | case .ISO8601: identifier = NSCalendarIdentifierISO8601 151 | case .Indian: identifier = NSCalendarIdentifierIndian 152 | case .Islamic: identifier = NSCalendarIdentifierIslamic 153 | case .IslamicCivil: identifier = NSCalendarIdentifierIslamicCivil 154 | case .Japanese: identifier = NSCalendarIdentifierJapanese 155 | case .Persian: identifier = NSCalendarIdentifierPersian 156 | case .RepublicOfChina: identifier = NSCalendarIdentifierRepublicOfChina 157 | case .IslamicTabular: identifier = NSCalendarIdentifierIslamicTabular 158 | case .IslamicUmmAlQura: identifier = NSCalendarIdentifierIslamicUmmAlQura 159 | case .Local(let autoUpdate): 160 | if autoUpdate { 161 | return NSCalendar.autoupdatingCurrentCalendar() 162 | } else { 163 | return NSCalendar.currentCalendar() 164 | } 165 | } 166 | return NSCalendar(identifier: identifier)! 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /Pods/SwiftDate/Sources/SwiftDate/NSDateFormatter+SwiftDate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftDate, an handy tool to manage date and timezones in swift 3 | // Created by: Daniele Margutti 4 | // Main contributors: Jeroen Houtzager 5 | // 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import Foundation 26 | 27 | /// Formatter options for ISO8601 according to [link](https://www.w3.org/TR/NOTE-datetime) 28 | /// 29 | /// - `Year`: Year - 30 | /// `YYYY` (eg 1997) 31 | /// - `YearMonth`: Year and month - 32 | /// `YYYY-MM` (eg 1997-07) 33 | /// - `Date`: Complete date - 34 | /// `YYYY-MM-DD` (eg 1997-07-16) 35 | /// - `DateTime`: Complete date plus hours and minutes - 36 | /// `YYYY-MM-DDThh:mmTZD` (eg 1997-07-16T19:20+01:00) 37 | /// - `Full`: Complete date plus hours, minutes and seconds - 38 | /// `YYYY-MM-DDThh:mm:ssTZD` (eg 1997-07-16T19:20:30+01:00) 39 | /// - `Extended`: Complete date plus hours, minutes, seconds and a decimal fraction of a 40 | /// second - 41 | /// `YYYY-MM-DDThh:mm:ss.sTZD` (eg 1997-07-16T19:20:30.45+01:00) 42 | /// 43 | /// where: 44 | /// 45 | /// - `YYYY` = four-digit year 46 | /// - `MM` = two-digit month (01=January, etc.) 47 | /// - `DD` = two-digit day of month (01 through 31) 48 | /// - `hh` = two digits of hour (00 through 23) (am/pm NOT allowed) 49 | /// - `mm` = two digits of minute (00 through 59) 50 | /// - `ss` = two digits of second (00 through 59) 51 | /// - `s` = one or more digits representing a decimal fraction of a second 52 | /// - `TZD` = time zone designator (Z or +hh:mm or -hh:mm) 53 | /// 54 | /// This profile does not specify how many digits may be used to represent the decimal 55 | /// fraction of a second. An adopting standard that permits fractions of a second must 56 | /// specify both the minimum number of digits (a number greater than or equal to one) and 57 | /// the maximum number of digits (the maximum may be stated to be "unlimited"). 58 | /// 59 | /// This profile defines two ways of handling time zone offsets: 60 | /// 61 | /// Times are expressed in UTC (Coordinated Universal Time), with a special UTC designator 62 | /// ("Z"). 63 | /// Times are expressed in local time, together with a time zone offset in hours and 64 | /// minutes. A time zone offset of "+hh:mm" indicates that the date/time uses a local time 65 | /// zone which is "hh" hours and "mm" minutes ahead of UTC. A time zone offset of "-hh:mm" 66 | /// indicates that the date/time uses a local time zone which is "hh" hours and "mm" 67 | /// minutes behind UTC. 68 | /// 69 | /// A standard referencing this profile should permit one or both of these ways of 70 | /// handling time zone offsets. 71 | /// 72 | public enum ISO8601Type: String { 73 | case Year = "yyyy" 74 | case YearMonth = "yyyy-MM" 75 | case Date = "yyyy-MM-dd" 76 | case DateTime = "yyyy-MM-dd'T'HH:mmZZZZZ" 77 | case Full = "yyyy-MM-dd'T'HH:mm:ssZZZZZ" 78 | case Extended = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" 79 | } 80 | 81 | //MARK: - Structure: DateFormat - 82 | 83 | // swiftlint:disable line_length 84 | 85 | /** 86 | * @brief DateFormat structure is used to parse and format an NSDate. 87 | * Custom formats are the same provided by iOS. 88 | * See: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html#//apple_ref/doc/uid/TP40002369-SW1 89 | */ 90 | 91 | // enable line_length 92 | 93 | 94 | public enum DateFormat { 95 | case Custom(String) // Custom formatting method 96 | case ISO8601Format(ISO8601Type?) // ISO8601 format with style. 97 | // You can omit type, .Full option is used. 98 | @available(*, deprecated=3.0.3, message="Use ISO8601Format(.Full)") 99 | case ISO8601 // ISO8601 format with style. 100 | // You can omit type, .Full option is used. 101 | @available(*, deprecated=3.0.3, message="Use ISO8601(.Date)") 102 | case ISO8601Date // ISO8601 Date Only Format (same of ISO8601(.Date)) 103 | case RSS // RSS style formatter 104 | case AltRSS // Alt RSS Formatter 105 | case Extended // Extended date Formatter 106 | 107 | var formatString: String { 108 | switch self { 109 | case .Custom(let format): return format 110 | case .ISO8601Date: return (ISO8601Type.Date).rawValue 111 | case .ISO8601Format(let type): return (type != nil ? type! : ISO8601Type.Full).rawValue 112 | case .ISO8601: return (ISO8601Type.Full).rawValue 113 | case .RSS: return "EEE, d MMM yyyy HH:mm:ss ZZZ" 114 | case .AltRSS: return "d MMM yyyy HH:mm:ss ZZZ" 115 | case .Extended: return "eee dd-MMM-yyyy GG HH:mm:ss.SSS ZZZ" 116 | } 117 | } 118 | } 119 | 120 | 121 | // MARK: - Extension - ISO8601 Formatter 122 | 123 | // This class extension provide a single method which attempt to handle all different ISO8601 124 | // formatters to return 125 | // best format string which can handle provided date 126 | 127 | extension String { 128 | 129 | private enum IS08601Format: Int { 130 | // YYYY (eg 1997) 131 | case Year = 4 132 | 133 | // YYYY-MM (eg 1997-07) 134 | case YearAndMonth = 7 135 | 136 | // YYYY-MM-DD (eg 1997-07-16) 137 | case CompleteDate = 10 138 | 139 | // YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20+01:00) 140 | case CompleteDatePlusHoursAndMinutes = 22 141 | 142 | // YYYY-MM-DDThh:mmTZD (eg 1997-07-16T19:20Z) 143 | case CompleteDatePlusHoursAndMinutesAndZ = 17 144 | 145 | // YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30+01:00) 146 | case CompleteDatePlusHoursMinutesAndSeconds = 25 147 | 148 | // YYYY-MM-DDThh:mm:ssTZD (eg 1997-07-16T19:20:30Z) 149 | case CompleteDatePlusHoursAndMinutesAndSecondsAndZ = 20 150 | // swiftlint:disable:previous type_name 151 | 152 | // YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45+01:00) 153 | case CompleteDatePlusHoursMinutesSecondsAndDecimalFractionOfSecond = 28 154 | // swiftlint:disable:previous type_name 155 | 156 | // YYYY-MM-DDThh:mm:ss.sTZD (eg 1997-07-16T19:20:30.45Z) 157 | case CompleteDatePlusHoursMinutesSecondsAndDecimalFractionOfSecondAndZ = 23 158 | // swiftlint:disable:previous type_name 159 | } 160 | 161 | /// Handle all different ISO8601 formatters and returns correct date format for string 162 | /// 163 | /// - parameters: 164 | /// - fromString: string to be formatted 165 | /// 166 | /// - returns: formatted string 167 | /// 168 | static func ISO8601Formatter(fromString string: String) -> String { 169 | 170 | var dateFormatter = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" 171 | 172 | if let dateStringCount = IS08601Format(rawValue: string.characters.count) { 173 | switch dateStringCount { 174 | case .Year: 175 | dateFormatter = "yyyy" 176 | case .YearAndMonth: 177 | dateFormatter = "yyyy-MM" 178 | case .CompleteDate: 179 | dateFormatter = "yyyy-MM-dd" 180 | case .CompleteDatePlusHoursAndMinutes, .CompleteDatePlusHoursAndMinutesAndZ: 181 | dateFormatter = "yyyy-MM-dd'T'HH:mmZ" 182 | case .CompleteDatePlusHoursMinutesAndSeconds, .CompleteDatePlusHoursAndMinutesAndSecondsAndZ: 183 | dateFormatter = "yyyy-MM-dd'T'HH:mm:ssZ" 184 | case .CompleteDatePlusHoursMinutesSecondsAndDecimalFractionOfSecond, .CompleteDatePlusHoursMinutesSecondsAndDecimalFractionOfSecondAndZ: 185 | dateFormatter = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" 186 | } 187 | } 188 | return dateFormatter 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /Pods/SwiftDate/Sources/SwiftDate/NSDateComponents+SwiftDate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftDate, an handy tool to manage date and timezones in swift 3 | // Created by: Daniele Margutti 4 | // Main contributors: Jeroen Houtzager 5 | // 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import Foundation 26 | 27 | //MARK: - Extension of Int To Manage Operations - 28 | 29 | public extension NSDateComponents { 30 | 31 | /** 32 | Create a new date from a specific date by adding self components 33 | 34 | - parameter refDate: reference date 35 | - parameter region: optional region to define the timezone and calendar. By default is local 36 | region 37 | 38 | - returns: a new NSDate instance 39 | */ 40 | public func fromDate(refDate: NSDate!, inRegion region: Region = Region()) -> NSDate { 41 | let date = region.calendar.dateByAddingComponents(self, toDate: refDate, 42 | options: NSCalendarOptions(rawValue: 0)) 43 | return date! 44 | } 45 | 46 | /** 47 | Create a new date from a specific date by subtracting self components 48 | 49 | - parameter refDate: reference date 50 | - parameter region: optional region to define the timezone and calendar. By default is local 51 | region 52 | 53 | - returns: a new NSDate instance 54 | */ 55 | public func agoFromDate(refDate: NSDate!, inRegion region: Region = Region()) -> NSDate { 56 | for unit in DateInRegion.componentFlagSet { 57 | let value = self.valueForComponent(unit) 58 | if value != NSDateComponentUndefined { 59 | self.setValue((value * -1), forComponent: unit) 60 | } 61 | } 62 | return region.calendar.dateByAddingComponents(self, toDate: refDate, 63 | options: NSCalendarOptions(rawValue: 0))! 64 | } 65 | 66 | /** 67 | Create a new date from current date and add self components. 68 | So you can make something like: 69 | let date = 4.days.fromNow() 70 | 71 | - parameter region: optional region to define the timezone and calendar. By default is local 72 | Region 73 | 74 | - returns: a new NSDate instance 75 | */ 76 | public func fromNow(inRegion region: Region = Region()) -> NSDate { 77 | return fromDate(NSDate(), inRegion: region) 78 | } 79 | 80 | /** 81 | Create a new date from current date and substract self components 82 | So you can make something like: 83 | let date = 5.hours.ago() 84 | 85 | - parameter region: optional region to define the timezone and calendar. By default is local 86 | Region 87 | 88 | - returns: a new NSDate instance 89 | */ 90 | public func ago(inRegion region: Region = Region()) -> NSDate { 91 | return agoFromDate(NSDate()) 92 | } 93 | 94 | /// The same of calling fromNow() with default local region 95 | public var fromNow: NSDate { 96 | get { 97 | return fromDate(NSDate()) 98 | } 99 | } 100 | 101 | /// The same of calling ago() with default local region 102 | public var ago: NSDate { 103 | get { 104 | return agoFromDate(NSDate()) 105 | } 106 | } 107 | 108 | /// The dateInRegion for the current components 109 | public var dateInRegion: DateInRegion? { 110 | return DateInRegion(self) 111 | } 112 | 113 | } 114 | 115 | //MARK: - Combine NSDateComponents - 116 | 117 | public func | (lhs: NSDateComponents, rhs: NSDateComponents) -> NSDateComponents { 118 | let dc = NSDateComponents() 119 | for unit in DateInRegion.componentFlagSet { 120 | let lhs_value = lhs.valueForComponent(unit) 121 | let rhs_value = rhs.valueForComponent(unit) 122 | if lhs_value != NSDateComponentUndefined { 123 | dc.setValue(lhs_value, forComponent: unit) 124 | } 125 | if rhs_value != NSDateComponentUndefined { 126 | dc.setValue(rhs_value, forComponent: unit) 127 | } 128 | } 129 | return dc 130 | } 131 | 132 | /// Add date components to one another 133 | /// 134 | /// - parameters: 135 | /// - lhs: left hand side argument 136 | /// - rhs: right hand side argument 137 | /// 138 | /// - returns: date components lhs + rhs 139 | /// 140 | public func + (lhs: NSDateComponents, rhs: NSDateComponents) -> NSDateComponents { 141 | return sumDateComponents(lhs, rhs: rhs) 142 | } 143 | 144 | /// subtract date components from one another 145 | /// 146 | /// - parameters: 147 | /// - lhs: left hand side argument 148 | /// - rhs: right hand side argument 149 | /// 150 | /// - returns: date components lhs - rhs 151 | /// 152 | public func - (lhs: NSDateComponents, rhs: NSDateComponents) -> NSDateComponents { 153 | return sumDateComponents(lhs, rhs: rhs, sum: false) 154 | } 155 | 156 | /// Helper function for date component sum * subtract 157 | /// 158 | /// - parameters: 159 | /// - lhs: left hand side argument 160 | /// - rhs: right hand side argument 161 | /// - sum: indicates whether arguments should be added or subtracted 162 | /// 163 | /// - returns: date components lhs +/- rhs 164 | /// 165 | internal func sumDateComponents(lhs: NSDateComponents, rhs: NSDateComponents, sum: Bool = true) -> 166 | NSDateComponents { 167 | 168 | let newComponents = NSDateComponents() 169 | let components = DateInRegion.componentFlagSet 170 | for unit in components { 171 | let leftValue = lhs.valueForComponent(unit) 172 | let rightValue = rhs.valueForComponent(unit) 173 | 174 | guard leftValue != NSDateComponentUndefined || rightValue != NSDateComponentUndefined else { 175 | continue // both are undefined, don't touch 176 | } 177 | 178 | let checkedLeftValue = leftValue == NSDateComponentUndefined ? 0 : leftValue 179 | let checkedRightValue = rightValue == NSDateComponentUndefined ? 0 : rightValue 180 | 181 | let finalValue = checkedLeftValue + (sum ? checkedRightValue : -checkedRightValue) 182 | newComponents.setValue(finalValue, forComponent: unit) 183 | } 184 | return newComponents 185 | } 186 | 187 | // MARK: - Helpers to enable expressions e.g. date + 1.days - 20.seconds 188 | 189 | public extension NSTimeZone { 190 | 191 | /// Returns a new NSDateComponents object containing the time zone as specified by the receiver 192 | /// 193 | public var timeZone: NSDateComponents { 194 | let dateComponents = NSDateComponents() 195 | dateComponents.timeZone = self 196 | return dateComponents 197 | } 198 | 199 | } 200 | 201 | 202 | public extension NSCalendar { 203 | 204 | /// Returns a new NSDateComponents object containing the calendar as specified by the receiver 205 | /// 206 | public var calendar: NSDateComponents { 207 | let dateComponents = NSDateComponents() 208 | dateComponents.calendar = self 209 | return dateComponents 210 | } 211 | 212 | } 213 | 214 | 215 | public extension Int { 216 | 217 | /// Returns a new NSDateComponents object containing the number of nanoseconds as specified by 218 | /// the receiver 219 | /// 220 | public var nanoseconds: NSDateComponents { 221 | let dateComponents = NSDateComponents() 222 | dateComponents.nanosecond = self 223 | return dateComponents 224 | } 225 | 226 | /// Returns a new NSDateComponents object containing the number of seconds as specified by the 227 | /// receiver 228 | /// 229 | public var seconds: NSDateComponents { 230 | let dateComponents = NSDateComponents() 231 | dateComponents.second = self 232 | return dateComponents 233 | } 234 | 235 | /// Returns a new NSDateComponents object containing the number of minutes as specified by the 236 | /// receiver 237 | /// 238 | public var minutes: NSDateComponents { 239 | let dateComponents = NSDateComponents() 240 | dateComponents.minute = self 241 | return dateComponents 242 | } 243 | 244 | /// Returns a new NSDateComponents object containing the number of hours as specified by the 245 | /// receiver 246 | /// 247 | public var hours: NSDateComponents { 248 | let dateComponents = NSDateComponents() 249 | dateComponents.hour = self 250 | return dateComponents 251 | } 252 | 253 | /// Returns a new NSDateComponents object containing the number of days as specified by the 254 | /// receiver 255 | /// 256 | public var days: NSDateComponents { 257 | let dateComponents = NSDateComponents() 258 | dateComponents.day = self 259 | return dateComponents 260 | } 261 | 262 | /// Returns a new NSDateComponents object containing the number of weeks as specified by the 263 | /// receiver 264 | /// 265 | public var weeks: NSDateComponents { 266 | let dateComponents = NSDateComponents() 267 | dateComponents.weekOfYear = self 268 | return dateComponents 269 | } 270 | 271 | /// Returns a new NSDateComponents object containing the number of months as specified by the 272 | /// receiver 273 | /// 274 | public var months: NSDateComponents { 275 | let dateComponents = NSDateComponents() 276 | dateComponents.month = self 277 | return dateComponents 278 | } 279 | 280 | /// Returns a new NSDateComponents object containing the number of years as specified by the 281 | /// receiver 282 | /// 283 | public var years: NSDateComponents { 284 | let dateComponents = NSDateComponents() 285 | dateComponents.year = self 286 | return dateComponents 287 | } 288 | } 289 | -------------------------------------------------------------------------------- /Pods/SwiftDate/Sources/SwiftDate/Additions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftDate, an handy tool to manage date and timezones in swift 3 | // Created by: Daniele Margutti 4 | // Main contributors: Jeroen Houtzager 5 | // 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import Foundation 26 | 27 | /// Return the current thread's `NSDateComponentsFormatter` instance. This component is used 28 | /// internally. When using it be sure to call `beginSessionContext(create:)` method to preserve and 29 | /// restore configuration of the object. 30 | /// 31 | ///- returns: an instance of the formatter 32 | /// 33 | internal func sharedDateComponentsFormatter() -> NSDateComponentsFormatter { 34 | let name = "SwiftDate_\(NSStringFromClass(NSDateComponentsFormatter.self))" 35 | return threadLocalObj(name, create: { (Void) -> NSDateComponentsFormatter in 36 | return NSDateComponentsFormatter() 37 | }) 38 | } 39 | 40 | /// Return the current thread's `NSDateFormatter` instance. This component is used internally. 41 | /// When using it be sure to call `beginSessionContext(create:)` method to preserve and restore 42 | /// configuration of the object. 43 | /// 44 | /// - returns: an instance of the formatter 45 | /// 46 | internal func sharedDateFormatter() -> NSDateFormatter { 47 | let name = "SwiftDate_\(NSStringFromClass(NSDateFormatter.self))" 48 | return threadLocalObj(name, create: { (Void) -> NSDateFormatter in 49 | return NSDateFormatter() 50 | }) 51 | } 52 | 53 | /// Provide a mechanism to create and return local-thread object you can share. 54 | /// 55 | /// Basically you assign a key to the object and return the initializated instance in `create` 56 | /// block. Again this code is used internally to provide a common way to create local-thread date 57 | /// formatter as like `NSDateFormatter` (which is expensive to create) or 58 | /// `NSDateComponentsFormatter`. 59 | /// Instance is saved automatically into current thread own dictionary. 60 | /// 61 | /// - parameter key: identification string of the object 62 | /// - parameter create: creation block. At the end of the block you need to provide the instance you 63 | /// want to save. 64 | /// 65 | /// - returns: the instance you have created into the current thread 66 | /// 67 | internal func threadLocalObj(key: String, create: (Void) -> T) -> T { 68 | if let cachedObj = NSThread.currentThread().threadDictionary[key] as? T { 69 | return cachedObj 70 | } else { 71 | let newObject = create() 72 | NSThread.currentThread().threadDictionary[key] = newObject 73 | return newObject 74 | } 75 | } 76 | 77 | 78 | //MARK: - FormatterStyle - 79 | 80 | /// This structure is used to encapsulate all attributes you can use to specify the formatting 81 | /// behavior of a string or an interval of time. You need to provide it when you want to convert an 82 | /// `NSDate`, `DateInRegion` or a `NSTimeInterval` instance into a colloquial representation. 83 | /// 84 | public struct FormatterStyle { 85 | /// Configure the strings to use for unit names such as days, hours, minutes and seconds. 86 | /// Use this property to specify the style of abbreviations used to identify each time 87 | /// component. By default the value of this property is .Abbreviated; so for example, one hour 88 | /// and ten minutes is displayed as “1h 10m”. 89 | public var style: NSDateComponentsFormatterUnitsStyle = .Abbreviated 90 | 91 | /// The bitmask of calendrical units such as day and month to include in the output string. 92 | /// By default all available values are 93 | /// used; this means each unit of time is part of the output string if the relative value is not 94 | /// zero. 95 | /// 96 | /// You can use: 97 | /// * `Year` 98 | /// * `Month` 99 | /// * `WeekOfMonth` 100 | /// * `Day` 101 | /// * `Hour` 102 | /// * `Minute` 103 | /// * `Second` 104 | /// 105 | /// Any other value of the `NSCalendarUnit` enum will result in an exception. 106 | public var units: NSCalendarUnit 107 | 108 | /// This property can be used to limit the number of units displayed in the resulting string. 109 | /// For example if set to 2, instead of “1h 10m, 30s” the output string will be “1h 10m”. You 110 | /// can use it to provide a round up version of the output when you are constrained. 111 | /// 112 | public var maxUnits: Int = 0 113 | 114 | /// Setting the value of this property to `true` adds phrasing to output strings to reflect 115 | /// that the given time value is approximate and not exact. 116 | /// Using this property yields more correct phrasing than simply prepending the string “About” 117 | /// to an output string. 118 | /// By default is set to `false` 119 | public var approximate: Bool = false 120 | 121 | /// Setting this property to `true` results in output strings like “30 minutes remaining”. 122 | /// The default value of this property is `false`. 123 | public var approximatePast: Bool = false 124 | 125 | /// An example of when this property might apply is when expressing 63 seconds worth of time. 126 | /// When this property is set to `true`, the formatted value would be “63s”. When the value of 127 | /// this property is `false`, 128 | /// the formatted value would be “1m 3s”. 129 | /// By default is set to `false` 130 | public var collapsesLargestUnit: Bool = false 131 | 132 | /// This specify the behavior of the formatter when it encounter a zero value for a 133 | /// particular unit of time. 134 | public var zeroBehavior: NSDateComponentsFormatterZeroFormattingBehavior = .Default 135 | 136 | /// Initialize a new `FormatterStyle` struct you can use to format a `NSDate`,`DateInRegion` or 137 | /// `NSTimeInterval` 138 | /// 139 | /// - parameter style: abbreviations you could use to format each time unit of the output string 140 | /// (by default `.Abbreviated` form is used) 141 | /// - parameter units: units you want to include in output string (by default all values are 142 | /// set) 143 | /// - parameter max: number of units you wan to include in ouput string (by default is `0` and 144 | /// means: do not omit anything) 145 | /// 146 | public init(style: NSDateComponentsFormatterUnitsStyle = .Abbreviated, 147 | units: NSCalendarUnit? = nil, max: Int = 0) { 148 | 149 | self.style = style 150 | self.units = units ?? [.Year, .Month, .WeekOfMonth, .Day, .Hour, .Minute, .Second] 151 | self.maxUnits = max 152 | } 153 | 154 | internal func restoreInto(formatter: NSDateComponentsFormatter) { 155 | formatter.unitsStyle = self.style 156 | formatter.allowedUnits = self.units 157 | formatter.maximumUnitCount = self.maxUnits 158 | formatter.includesApproximationPhrase = self.approximate 159 | formatter.includesTimeRemainingPhrase = self.approximatePast 160 | formatter.zeroFormattingBehavior = self.zeroBehavior 161 | formatter.collapsesLargestUnit = self.collapsesLargestUnit 162 | } 163 | 164 | internal init(formatter: NSDateComponentsFormatter) { 165 | self.style = formatter.unitsStyle 166 | self.units = formatter.allowedUnits 167 | self.maxUnits = formatter.maximumUnitCount 168 | self.approximate = formatter.includesApproximationPhrase 169 | self.approximatePast = formatter.includesTimeRemainingPhrase 170 | self.zeroBehavior = formatter.zeroFormattingBehavior 171 | self.collapsesLargestUnit = formatter.collapsesLargestUnit 172 | } 173 | } 174 | 175 | //MARK: - NSDateComponentsFormatter - 176 | 177 | internal extension NSDateComponentsFormatter { 178 | 179 | 180 | /// This method is used to provide a session context to create and use an instance of 181 | /// `NSDateComponentsFormatter` by preserving pre-task configuration. When you start a new 182 | /// session the current attributes of the instance are saved automatically and restored at the 183 | /// end of the session. We have this function because a single `NSDateComponentsFormatter` is 184 | /// shared along a thread. *You don't need to use it externally so it's a private method *. 185 | /// 186 | /// - parameter block: block to execute your formast operation. It could return something 187 | /// 188 | /// - returns: the result of the operation 189 | /// 190 | func beginSessionContext(block: (Void) -> (T?)) -> T? { 191 | let saved_cfg = FormatterStyle(formatter: self) 192 | let block_result = block() 193 | saved_cfg.restoreInto(self) 194 | return block_result 195 | } 196 | 197 | } 198 | 199 | //MARK: - Common Share Functions - 200 | 201 | internal extension NSDateFormatter { 202 | 203 | /// This method is used to provide a session context to create and use an instance of 204 | /// `NSDateFormatter` by preserving pre-task configuration. When you start a new session the 205 | /// current attributes of the instance are saved automatically and restored at the end of the 206 | /// session. We have this function because a single `NSDateFormatter` is shared along a thread. 207 | /// *You don't need to use it externally so it's a private method *. 208 | /// 209 | /// - parameter block: block to execute your formast operation. It could return something 210 | /// 211 | /// - returns: the result of the operation 212 | /// 213 | func beginSessionContext(block: (Void) -> (T?)) -> T? { 214 | let saved_cfg = NSDateFormatterConfig(formatter: self) 215 | let block_result = block() 216 | saved_cfg.restoreInto(self) 217 | return block_result 218 | } 219 | 220 | 221 | /// This is the object we use to store attributes of NSDateFormatter. We don't need to expose 222 | /// it. 223 | /// 224 | struct NSDateFormatterConfig { 225 | var dateFormat: String? 226 | var locale: NSLocale? 227 | var timeZone: NSTimeZone? 228 | var relative: Bool 229 | 230 | init(formatter: NSDateFormatter) { 231 | dateFormat = formatter.dateFormat 232 | locale = formatter.locale 233 | timeZone = formatter.timeZone 234 | relative = formatter.doesRelativeDateFormatting 235 | } 236 | 237 | func restoreInto(formatter: NSDateFormatter) { 238 | formatter.dateFormat = self.dateFormat 239 | formatter.locale = self.locale 240 | formatter.timeZone = self.timeZone 241 | formatter.doesRelativeDateFormatting = self.relative 242 | } 243 | } 244 | } 245 | -------------------------------------------------------------------------------- /Pods/SwiftDate/Sources/SwiftDate/DateInRegion+Comparisons.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftDate, an handy tool to manage date and timezones in swift 3 | // Created by: Daniele Margutti 4 | // Main contributors: Jeroen Houtzager 5 | // 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import Foundation 26 | 27 | // MARK: - Comparators 28 | 29 | public extension DateInRegion { 30 | 31 | // swiftlint:disable line_length 32 | 33 | /// Returns an NSComparisonResult value that indicates the ordering of two given dates based on 34 | /// their components down to a given unit granularity. 35 | /// 36 | /// - Parameters: 37 | /// - date: date to compare. 38 | /// - toUnitGranularity: The smallest unit that must, along with all larger units, be equal 39 | /// for the given dates to be considered the same. 40 | /// For possible values, see “[Calendar Units](xcdoc://?url=developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSCalendar_Class/index.html#//apple_ref/c/tdef/NSCalendarUnit)” 41 | /// 42 | /// - Returns: NSOrderedSame if the dates are the same down to the given granularity, otherwise 43 | /// NSOrderedAscending or NSOrderedDescending. 44 | /// 45 | /// - seealso: [compareDate:toDate:toUnitGranularity:](xcdoc://?url=developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSCalendar_Class/index.html#//apple_ref/occ/instm/NSCalendar/compareDate:toDate:toUnitGranularity:) 46 | /// 47 | public func compareDate(date: DateInRegion, toUnitGranularity unit: NSCalendarUnit) 48 | -> NSComparisonResult { 49 | 50 | return calendar.compareDate(self.absoluteTime, toDate: date.absoluteTime, 51 | toUnitGranularity: unit) 52 | } 53 | 54 | /// Compares equality of two given dates based on their components down to a given unit 55 | /// granularity. 56 | /// 57 | /// - Parameters: 58 | /// - unit: The smallest unit that must, along with all larger units, be equal for the given 59 | /// dates to be considered the same. 60 | /// - date: date to compare. 61 | /// 62 | /// - Returns: `true` if the dates are the same down to the given granularity, otherwise `false` 63 | /// 64 | /// - seealso: [compareDate:toDate:toUnitGranularity:](xcdoc://?url=developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSCalendar_Class/index.html#//apple_ref/occ/instm/NSCalendar/compareDate:toDate:toUnitGranularity:) 65 | /// 66 | public func isIn(unit: NSCalendarUnit, ofDate date: DateInRegion) -> Bool { 67 | return self.compareDate(date, toUnitGranularity: unit) == .OrderedSame 68 | } 69 | 70 | /// Compares whether the receiver is before `date` based on their components down to a given 71 | /// unit granularity. 72 | /// 73 | /// - Parameters: 74 | /// - unit: The smallest unit that must, along with all larger units, be less for the given 75 | /// dates. 76 | /// - date: date to compare. 77 | /// 78 | /// - Returns: `true` if the unit of the receiver is less than the unit of `date`, otherwise 79 | /// `false` 80 | /// 81 | /// - seealso: [compareDate:toDate:toUnitGranularity:](xcdoc://?url=developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSCalendar_Class/index.html#//apple_ref/occ/instm/NSCalendar/compareDate:toDate:toUnitGranularity:) 82 | /// 83 | public func isBefore(unit: NSCalendarUnit, ofDate date: DateInRegion) -> Bool { 84 | return self.compareDate(date, toUnitGranularity: unit) == .OrderedAscending 85 | } 86 | 87 | /// Compares whether the receiver is after `date` based on their components down to a given unit 88 | /// granularity. 89 | /// 90 | /// - Parameters: 91 | /// - unit: The smallest unit that must, along with all larger units, be greater 92 | /// - date: date to compare. 93 | /// 94 | /// - Returns: `true` if the unit of the receiver is greater than the unit of `date`, otherwise 95 | /// `false` 96 | /// 97 | /// - seealso: [compareDate:toDate:toUnitGranularity:](xcdoc://?url=developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSCalendar_Class/index.html#//apple_ref/occ/instm/NSCalendar/compareDate:toDate:toUnitGranularity:) 98 | /// 99 | public func isAfter(unit: NSCalendarUnit, ofDate date: DateInRegion) -> Bool { 100 | return self.compareDate(date, toUnitGranularity: unit) == .OrderedDescending 101 | } 102 | 103 | /// Returns whether the given date is in today. 104 | /// 105 | /// - Returns: a boolean indicating whether the receiver is in today 106 | /// 107 | /// - note: This value is interpreted in the context of the calendar of the receiver 108 | /// 109 | /// - seealso: [isDateInToday:](xcdoc://?url=developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSCalendar_Class/index.html#//apple_ref/occ/instm/NSCalendar/isDateInToday:) 110 | /// 111 | public func isInToday( ) -> Bool { 112 | return calendar.isDateInToday(absoluteTime) 113 | } 114 | 115 | /// Returns whether the given date is in yesterday. 116 | /// 117 | /// - Returns: a boolean indicating whether the receiver is in yesterday 118 | /// 119 | /// - note: This value is interpreted in the context of the calendar of the receiver 120 | /// 121 | /// - seealso: [isDateInYesterday:](xcdoc://?url=developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSCalendar_Class/index.html#//apple_ref/occ/instm/NSCalendar/isDateInYesterday:) 122 | /// 123 | public func isInYesterday() -> Bool { 124 | return calendar.isDateInYesterday(absoluteTime) 125 | } 126 | 127 | /// Returns whether the given date is in tomorrow. 128 | /// 129 | /// - Returns: a boolean indicating whether the receiver is in tomorrow 130 | /// 131 | /// - note: This value is interpreted in the context of the calendar of the receiver 132 | /// 133 | /// - seealso: [isDateInTomorrow:](xcdoc://?url=developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSCalendar_Class/index.html#//apple_ref/occ/instm/NSCalendar/isDateInTomorrow:) 134 | /// 135 | public func isInTomorrow() -> Bool { 136 | return calendar.isDateInTomorrow(absoluteTime) 137 | } 138 | 139 | /// Returns whether the given date is in the weekend. 140 | /// 141 | /// - Returns: a boolean indicating whether the receiver is in the weekend 142 | /// 143 | /// - note: This value is interpreted in the context of the calendar of the receiver 144 | /// 145 | /// - seealso: [isDateInWeekend:](xcdoc://?url=developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSCalendar_Class/index.html#//apple_ref/occ/instm/NSCalendar/isDateInWeekend:) 146 | /// 147 | public func isInWeekend() -> Bool { 148 | return calendar.isDateInWeekend(absoluteTime) 149 | } 150 | 151 | /// Returns whether the given date is on the same day as the receiver in the time zone and 152 | /// calendar of the receiver. 153 | /// 154 | /// - Parameters: 155 | /// - date: a date to compare against 156 | /// 157 | /// - Returns: a boolean indicating whether the receiver is on the same day as the given date in 158 | /// the time zone and calendar of the receiver. 159 | /// 160 | /// - seealso: [isDate:inSameDayAsDate:](xcdoc://?url=developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSCalendar_Class/index.html#//apple_ref/occ/instm/NSCalendar/isDate:inSameDayAsDate:) 161 | /// 162 | public func isInSameDayAsDate(date: DateInRegion) -> Bool { 163 | return calendar.isDate(self.absoluteTime, inSameDayAsDate: date.absoluteTime) 164 | } 165 | 166 | /// Returns whether the given date is equal to the receiver. 167 | /// 168 | /// - Parameters: 169 | /// - date: a date to compare against 170 | /// 171 | /// - Returns: a boolean indicating whether the receiver is equal to the given date 172 | /// 173 | /// - seealso: [isEqualToDate:](xcdoc://?url=developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSDate_Class/index.html#//apple_ref/occ/instm/NSDate/isEqualToDate:) 174 | /// 175 | public func isEqualToDate(right: DateInRegion) -> Bool { 176 | // Compare the content, first the date 177 | if absoluteTime != right.absoluteTime { 178 | return false 179 | } 180 | 181 | // Then the region 182 | if region != right.region { 183 | return false 184 | } 185 | 186 | // We have made it! They are equal! 187 | return true 188 | } 189 | } 190 | 191 | // MARK: - Comparable delegate 192 | 193 | 194 | /// Instances of conforming types can be compared using relational operators, which define a strict 195 | /// total order. 196 | /// 197 | /// A type conforming to Comparable need only supply the < and == operators; default implementations 198 | /// of <=, >, >=, and != are supplied by the standard library: 199 | /// 200 | extension DateInRegion: Comparable {} 201 | 202 | /// Returns whether the given date is later than the receiver. 203 | /// Just the dates are compared. Calendars, time zones are irrelevant. 204 | /// 205 | /// - Parameters: 206 | /// - date: a date to compare against 207 | /// 208 | /// - Returns: a boolean indicating whether the receiver is earlier than the given date 209 | /// 210 | public func < (ldate: DateInRegion, rdate: DateInRegion) -> Bool { 211 | return ldate.absoluteTime.compare(rdate.absoluteTime) == .OrderedAscending 212 | } 213 | 214 | /// Returns whether the given date is earlier than the receiver. 215 | /// Just the dates are compared. Calendars, time zones are irrelevant. 216 | /// 217 | /// - Parameters: 218 | /// - date: a date to compare against 219 | /// 220 | /// - Returns: a boolean indicating whether the receiver is later than the given date 221 | /// 222 | public func > (ldate: DateInRegion, rdate: DateInRegion) -> Bool { 223 | return ldate.absoluteTime.compare(rdate.absoluteTime) == .OrderedDescending 224 | } 225 | -------------------------------------------------------------------------------- /Pods/SwiftDate/Sources/SwiftDate/DateInRegion+Components.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftDate, an handy tool to manage date and timezones in swift 3 | // Created by: Daniele Margutti 4 | // Main contributors: Jeroen Houtzager 5 | // 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import Foundation 26 | 27 | 28 | // MARK: - NSCalendar & NSDateComponent ports 29 | 30 | public extension DateInRegion { 31 | 32 | /// Returns a NSDateComponents object containing a given date decomposed into components: 33 | /// day, month, year, hour, minute, second, nanosecond, timeZone, calendar, 34 | /// yearForWeekOfYear, weekOfYear, weekday, quarter and weekOfMonth. 35 | /// Values returned are in the context of the calendar and time zone properties. 36 | /// 37 | /// - Returns: An NSDateComponents object containing date decomposed 38 | /// into the components as specified. 39 | /// 40 | public var components: NSDateComponents { 41 | return calendar.components(DateInRegion.componentFlags, fromDate: self.absoluteTime) 42 | } 43 | 44 | /// Returns the value for an NSDateComponents object. 45 | /// Values returned are in the context of the calendar and time zone properties. 46 | /// 47 | /// - Parameters: 48 | /// - flag: specifies the calendrical unit that should be returned 49 | /// - Returns: The value of the NSDateComponents object for the date. 50 | /// - remark: asserts that no calendar or time zone flags are specified. 51 | /// If one of these is present, an assertion fails and execution will halt. 52 | /// 53 | internal func valueForComponent(flag: NSCalendarUnit) -> Int { 54 | assert(!flag.contains(.Calendar)) 55 | assert(!flag.contains(.TimeZone)) 56 | 57 | let components = calendar.components(flag, fromDate: absoluteTime) 58 | let value = components.valueForComponent(flag) 59 | return value 60 | } 61 | 62 | /// The number of era units for the receiver. 63 | /// 64 | /// - note: This value is interpreted in the context of the calendar with which it is used 65 | /// 66 | public var era: Int { 67 | return valueForComponent(.Era) 68 | } 69 | 70 | /// The number of year units for the receiver. 71 | /// 72 | /// - note: This value is interpreted in the context of the calendar with which it is used 73 | /// 74 | public var year: Int { 75 | return valueForComponent(.Year) 76 | } 77 | 78 | /// The number of month units for the receiver. 79 | /// 80 | /// - note: This value is interpreted in the context of the calendar with which it is used 81 | /// 82 | public var month: Int { 83 | return valueForComponent(.Month) 84 | } 85 | 86 | /// The number of day units for the receiver. 87 | /// 88 | /// - note: This value is interpreted in the context of the calendar with which it is used 89 | /// 90 | public var day: Int { 91 | return valueForComponent(.Day) 92 | } 93 | 94 | /// The number of hour units for the receiver. 95 | /// 96 | /// - note: This value is interpreted in the context of the calendar with which it is used 97 | /// 98 | public var hour: Int { 99 | return valueForComponent(.Hour) 100 | } 101 | 102 | /// Nearest rounded hour from the date expressed in this region's timezone 103 | public var nearestHour: Int { 104 | let date = self + 30.minutes 105 | return Int(date.hour) 106 | } 107 | 108 | /// The number of minute units for the receiver. 109 | /// 110 | /// - note: This value is interpreted in the context of the calendar with which it is used 111 | /// 112 | public var minute: Int { 113 | return valueForComponent(.Minute) 114 | } 115 | 116 | /// The number of second units for the receiver. 117 | /// 118 | /// - note: This value is interpreted in the context of the calendar with which it is used 119 | /// 120 | public var second: Int { 121 | return valueForComponent(.Second) 122 | } 123 | 124 | /// The number of nanosecond units for the receiver. 125 | /// 126 | /// - note: This value is interpreted in the context of the calendar with which it is used 127 | /// 128 | public var nanosecond: Int { 129 | return valueForComponent(.Nanosecond) 130 | } 131 | 132 | /// The week-numbering year of the receiver. 133 | /// 134 | /// - note: This value is interpreted in the context of the calendar with which it is used 135 | /// 136 | public var yearForWeekOfYear: Int { 137 | return valueForComponent(.YearForWeekOfYear) 138 | } 139 | 140 | /// The week date of the year for the receiver. 141 | /// 142 | /// - note: This value is interpreted in the context of the calendar with which it is used 143 | /// 144 | public var weekOfYear: Int { 145 | return valueForComponent(.WeekOfYear) 146 | } 147 | 148 | /// The number of weekday units for the receiver. 149 | /// Weekday units are the numbers 1 through n, where n is the number of days in the week. 150 | /// For example, in the Gregorian calendar, n is 7 and Sunday is represented by 1. 151 | /// 152 | /// - note: This value is interpreted in the context of the calendar with which it is used 153 | /// 154 | public var weekday: Int { 155 | return valueForComponent(.Weekday) 156 | } 157 | 158 | /// The ordinal number of weekday units for the receiver. 159 | /// Weekday ordinal units represent the position of the weekday within 160 | /// the next larger calendar unit, such as the month. 161 | /// For example, 2 is the weekday ordinal unit for the second Friday of the month. 162 | /// 163 | /// - note: This value is interpreted in the context of the calendar with which it is used 164 | /// 165 | public var weekdayOrdinal: Int { 166 | return valueForComponent(.WeekdayOrdinal) 167 | } 168 | 169 | /// Week day name of the date expressed in this region's locale 170 | public var weekdayName: String { 171 | 172 | let cachedFormatter = sharedDateFormatter() 173 | return cachedFormatter.beginSessionContext { () -> (String) in 174 | cachedFormatter.dateFormat = "EEEE" 175 | cachedFormatter.locale = self.region.locale 176 | let value = cachedFormatter.stringFromDate(self.absoluteTime) 177 | return value 178 | }! 179 | } 180 | 181 | /// Nmber of days into current's date month expressed in current region calendar and locale 182 | public var monthDays: Int { 183 | return region.calendar.rangeOfUnit(.Day, inUnit: .Month, forDate: absoluteTime).length 184 | } 185 | 186 | /** QUARTER IS NOT INCLUDED DUE TO INCORRECT REPRESENTATION OF QUARTER IN NSCALENDAR 187 | /// The number of quarter units for the receiver. 188 | /// Weekday ordinal units represent the position of the weekday within the next larger 189 | /// calendar unit, such as the month. For example, 2 is the weekday 190 | /// ordinal unit for the second Friday of the month. 191 | /// 192 | /// - note: This value is interpreted in the context of the calendar with which it is used 193 | /// 194 | public var quarter: Int? { 195 | return valueForComponent(.Quarter) 196 | } 197 | **/ 198 | 199 | /// The week number in the month for the receiver. 200 | /// 201 | /// - note: This value is interpreted in the context of the calendar with which it is used 202 | /// 203 | public var weekOfMonth: Int { 204 | return valueForComponent(.WeekOfMonth) 205 | } 206 | 207 | /// Month name of the date expressed in this region's timezone using region's locale 208 | public var monthName: String { 209 | let cachedFormatter = sharedDateFormatter() 210 | return cachedFormatter.beginSessionContext { () -> (String) in 211 | cachedFormatter.locale = self.region.locale 212 | let value = cachedFormatter.monthSymbols[self.month - 1] as String 213 | return value 214 | }! 215 | } 216 | 217 | 218 | /// Boolean value that indicates whether the month is a leap month. 219 | /// ``YES`` if the month is a leap month, ``NO`` otherwise 220 | /// 221 | /// - note: This value is interpreted in the context of the calendar with which it is used 222 | /// 223 | public var leapMonth: Bool { 224 | // Library function for leap contains a bug for Gregorian calendars, implemented workaround 225 | if calendar.calendarIdentifier == NSCalendarIdentifierGregorian && year >= 1582 { 226 | let range = calendar.rangeOfUnit(.Day, inUnit: .Month, forDate: absoluteTime) 227 | return range.length == 29 228 | } 229 | 230 | // For other calendars: 231 | return calendar.components([.Day, .Month, .Year], fromDate: absoluteTime).leapMonth 232 | } 233 | 234 | /// Boolean value that indicates whether the year is a leap year. 235 | /// ``YES`` if the year is a leap year, ``NO`` otherwise 236 | /// 237 | /// - note: This value is interpreted in the context of the calendar with which it is used 238 | /// 239 | public var leapYear: Bool { 240 | // Library function for leap contains a bug for Gregorian calendars, implemented workaround 241 | if calendar.calendarIdentifier == NSCalendarIdentifierGregorian { 242 | let newComponents = components 243 | newComponents.month = 2 244 | newComponents.day = 10 245 | let testDate = newComponents.dateInRegion! 246 | return testDate.leapMonth 247 | } 248 | 249 | // For other calendars: 250 | return calendar.components([.Day, .Month, .Year], fromDate: absoluteTime).leapMonth 251 | } 252 | 253 | /// Returns two DateInRegion objects indicating the start and the end of the current weekend . 254 | /// 255 | /// - Returns: a tuple of two DateInRegion objects indicating the start and the end of 256 | /// the current weekend. If this is unto a weekend, then `nil` is returned. 257 | /// 258 | public func thisWeekend() -> (startDate: DateInRegion, endDate: DateInRegion)? { 259 | guard calendar.isDateInWeekend(self.absoluteTime) else { 260 | return nil 261 | } 262 | let date = self - 2.days 263 | return date.nextWeekend() 264 | } 265 | 266 | /// Returns two DateInRegion objects indicating the start and the end of 267 | /// the previous weekend before the date. 268 | /// 269 | /// - Returns: a tuple of two DateInRegion objects indicating the start 270 | /// and the end of the next weekend after the date. 271 | /// 272 | /// - Note: The weekend returned when the receiver is in a weekend is 273 | /// the previous weekend not the current one. 274 | /// 275 | public func previousWeekend() -> (startDate: DateInRegion, endDate: DateInRegion)? { 276 | let date = self - 9.days 277 | return date.nextWeekend() 278 | } 279 | 280 | /// Returns two DateInRegion objects indicating the start and the end 281 | /// of the next weekend after the date. 282 | /// 283 | /// - Returns: a tuple of two DateInRegion objects indicating the 284 | /// start and the end of the next weekend after the date. 285 | /// 286 | /// - Note: The weekend returned when the receiver is in a weekend 287 | /// is the next weekend not the current one. 288 | /// 289 | public func nextWeekend() -> (startDate: DateInRegion, endDate: DateInRegion)? { 290 | var wkStart: NSDate? 291 | var tInt: NSTimeInterval = 0 292 | let opt = NSCalendarOptions(rawValue: 0) 293 | let d = self.absoluteTime 294 | if !calendar.nextWeekendStartDate(&wkStart, interval: &tInt, options: opt, afterDate: d) { 295 | return nil 296 | } 297 | 298 | // Subtract one thousandth of a second to distinguish from Midnigth 299 | // on the next Monday for the isEqualDate function of NSDate 300 | let wkEnd = wkStart!.dateByAddingTimeInterval(tInt - 0.001) 301 | 302 | let startDate = DateInRegion(absoluteTime: wkStart!, region: region) 303 | let endDate = DateInRegion(absoluteTime: wkEnd, region: region) 304 | return (startDate, endDate) 305 | } 306 | 307 | } 308 | -------------------------------------------------------------------------------- /Pods/SwiftDate/Sources/SwiftDate/DateInRegion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftDate, an handy tool to manage date and timezones in swift 3 | // Created by: Daniele Margutti 4 | // Main contributors: Jeroen Houtzager 5 | // 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import Foundation 26 | 27 | /** 28 | `DateInRegion` is essentially a wrapper around `NSDate` which encapsulate 29 | additional region informations like the timezone (`NSTimeZone`), 30 | calendar (`NSCalendar`) and locale (`NSLocale`) and offer a set of method 31 | and properties to access and manage date components. 32 | You can think `DateInRegion` as representation of an absolute `NSDate` expressed 33 | in a particular world location. 34 | In order to specify region attributes each `DateInRegion` object contains 35 | a `Region` object. 36 | 37 | Using `DateInRegion` you can: 38 | * Represent an absolute NSDate in a specific timezone/calendar/locale 39 | * Easy access to all date components (day,month,hour,minute etc.) of the date in specified region 40 | * Easily create a new date from string, date components or swift operators 41 | * Compare date using Swift operators like `==, !=, <, >, <=, >=` and several 42 | additional methods like `isInWeekend,isYesterday`... 43 | * Change date by adding or subtracting elements with Swift operators 44 | (e.g. `date + 2.days + 15.minutes`) 45 | 46 | */ 47 | public struct DateInRegion { 48 | 49 | /// Set to loop throuhg all NSCalendarUnit values 50 | /// 51 | internal static let componentFlagSet: [NSCalendarUnit] = [.Nanosecond, .Second, .Minute, .Hour, 52 | .Day, .Month, .Year, .YearForWeekOfYear, .WeekOfYear, .Weekday, .Quarter, .WeekdayOrdinal, 53 | .WeekOfMonth] 54 | 55 | /// NSCalendarUnit values used to obtain data from a date with a calendar and time zone 56 | /// 57 | internal static let componentFlags: NSCalendarUnit = [.Day, .Month, .Year, .Hour, .Minute, 58 | .Second, .Nanosecond, .TimeZone, .Calendar, .YearForWeekOfYear, .WeekOfYear, .Weekday, 59 | .Quarter, .WeekOfMonth] 60 | 61 | // MARK: - Instance variables 62 | 63 | /// NSDate value (i.e. absolute time) around which the DateInRegion evolves. 64 | /// 65 | /// - warning: Please note that the date is immutable alike NSDate. 66 | /// This keeps the main datemvalue of this class thread safe. 67 | /// If you want to assign a new value then you must assign it to a new instance of DateInRegion. 68 | /// 69 | public let absoluteTime: NSDate! 70 | 71 | /// The region where the date lives. Use it to represent the date. 72 | public let region: Region 73 | 74 | /// Calendar to interpret date values. You can alter the calendar to 75 | /// adjust the representation of date to your needs. 76 | /// 77 | public var calendar: NSCalendar! { return region.calendar } 78 | 79 | /// Time zone to interpret date values 80 | /// Because the time zone is part of calendar, this is a shortcut to that variable. 81 | /// You can alter the time zone to adjust the representation of date to your needs. 82 | /// 83 | public var timeZone: NSTimeZone! { return region.timeZone } 84 | 85 | /// Locale to interpret date values 86 | /// Because the locale is part of calendar, this is a shortcut to that variable. 87 | /// You can alter the locale to adjust the representation of date to your needs. 88 | /// 89 | public var locale: NSLocale! { return region.locale } 90 | 91 | // MARK: - Initialisations 92 | 93 | 94 | /// Initialise with a date, a region and some properties. 95 | /// This initialiser can be used to copy a date while setting certain properties. 96 | /// 97 | /// - parameters: 98 | /// - absoluteTime: the date to assign, `default = NSDate()` (that is the current 99 | /// time) 100 | /// - region: the region to work with to assign, default = the current region 101 | /// 102 | public init(absoluteTime newDate: NSDate? = nil, region newRegion: Region? = nil) { 103 | absoluteTime = newDate ?? NSDate() 104 | region = newRegion ?? Region() 105 | } 106 | 107 | /// Initialise a `DateInRegion` object from a set of date components. Default values will be 108 | /// used if the components are insufficient to create a date. 109 | /// 110 | /// - parameters: 111 | /// - components: date components to generate the date from 112 | /// 113 | internal init(_ components: NSDateComponents) { 114 | let region = Region(components) 115 | let absoluteTime = region.calendar.dateFromComponents(components) 116 | self.init(absoluteTime: absoluteTime, region: region) 117 | } 118 | 119 | 120 | /// Initialise a `DateInRegion` object from a source date and a number of optional date 121 | /// properties. 122 | /// 123 | /// Please note that if a new region is specified, parameters are evaluated against that region. 124 | /// I.e. you might have a different absolute time generated. To use time zone conversion you 125 | /// should use `date.inRegion()`. 126 | /// 127 | /// - parameters: 128 | /// - fromDate: reference `DateInRegion` 129 | /// - era: era to set (optional) 130 | /// - year: year number to set (optional) 131 | /// - month: year number to set (optional) 132 | /// - day: day number to set (optional) 133 | /// - hour: hour number to set (optional) 134 | /// - minute: minute number to set (optional) 135 | /// - second: second number to set (optional) 136 | /// - nanosecond: nanosecond number to set (optional) 137 | /// - region: region to set (optional) 138 | /// 139 | public init( 140 | fromDate: DateInRegion, 141 | era: Int? = nil, 142 | year: Int? = nil, 143 | month: Int? = nil, 144 | day: Int? = nil, 145 | hour: Int? = nil, 146 | minute: Int? = nil, 147 | second: Int? = nil, 148 | nanosecond: Int? = nil, 149 | region: Region? = nil) { 150 | 151 | let newComponents = NSDateComponents() 152 | newComponents.era = era ?? fromDate.era 153 | newComponents.year = year ?? fromDate.year 154 | newComponents.month = month ?? fromDate.month 155 | newComponents.day = day ?? fromDate.day 156 | newComponents.hour = hour ?? fromDate.hour 157 | newComponents.minute = minute ?? fromDate.minute 158 | newComponents.second = second ?? fromDate.second 159 | newComponents.nanosecond = nanosecond ?? fromDate.nanosecond 160 | newComponents.calendar = region?.calendar ?? fromDate.calendar 161 | 162 | self.init(newComponents) 163 | } 164 | 165 | 166 | /// Initialise a `DateInRegion` object from a number of date properties. 167 | /// Parameters are kind of fuzzy; they can overlap functionality and can contradict eachother. 168 | /// In such a case the parameter highest in the parameter list below has priority. 169 | /// All parameters but `year`, `month` and `day` are optional. 170 | /// 171 | /// - Parameters: 172 | /// - era: era to set (optional) 173 | /// - year: year number to set 174 | /// - month: month number to set 175 | /// - day: day number to set 176 | /// - hour: hour number to set (optional) 177 | /// - minute: minute number to set (optional) 178 | /// - second: second number to set (optional) 179 | /// - nanosecond: nanosecond number to set (optional) 180 | /// - region: region to set (optional) 181 | /// 182 | public init( 183 | era: Int? = nil, 184 | year: Int, 185 | month: Int, 186 | day: Int, 187 | hour: Int? = nil, 188 | minute: Int? = nil, 189 | second: Int? = nil, 190 | nanosecond: Int? = nil, 191 | region: Region? = nil) { 192 | 193 | let newComponents = NSDateComponents() 194 | newComponents.era = era ?? 1 195 | newComponents.year = year 196 | newComponents.month = month 197 | newComponents.day = day 198 | newComponents.hour = hour ?? 0 199 | newComponents.minute = minute ?? 0 200 | newComponents.second = second ?? 0 201 | newComponents.nanosecond = nanosecond ?? 0 202 | newComponents.calendar = region?.calendar 203 | newComponents.timeZone = region?.timeZone 204 | 205 | self.init(newComponents) 206 | } 207 | 208 | 209 | /** 210 | Initialise a `DateInRegion` object from a number of date properties. 211 | Parameters are kind of fuzzy; they can overlap functionality and can contradict eachother. 212 | In such a case the parameter highest in the parameter list below has priority. 213 | All parameters but `yearForWeekOfYear`, `weekOfYear` and `weekday` are optional. 214 | 215 | Use this initialiser if you have a source date based on week number from 216 | which to copy the properties. 217 | 218 | - Parameters: 219 | - era: era to set (optional) 220 | - yearForWeekOfYear: year number to set 221 | - weekOfYear: week number to set 222 | - weekday: weekday number to set 223 | - hour: hour number to set (optional) 224 | - minute: minute number to set (optional) 225 | - second: second number to set (optional) 226 | - nanosecond: nanosecond number to set (optional) 227 | - region: region to set (optional) 228 | */ 229 | public init( 230 | era: Int? = nil, 231 | yearForWeekOfYear: Int, 232 | weekOfYear: Int, 233 | weekday: Int, 234 | hour: Int? = nil, 235 | minute: Int? = nil, 236 | second: Int? = nil, 237 | nanosecond: Int? = nil, 238 | region: Region? = nil) { 239 | 240 | let newComponents = NSDateComponents() 241 | newComponents.era = era ?? 1 242 | newComponents.yearForWeekOfYear = yearForWeekOfYear 243 | newComponents.weekOfYear = weekOfYear 244 | newComponents.weekday = weekday 245 | newComponents.hour = hour ?? 0 246 | newComponents.minute = minute ?? 0 247 | newComponents.second = second ?? 0 248 | newComponents.nanosecond = nanosecond ?? 0 249 | newComponents.calendar = region?.calendar 250 | newComponents.timeZone = region?.timeZone 251 | 252 | self.init(newComponents) 253 | } 254 | 255 | 256 | /// Initialize a new DateInRegion string from a specified date string, a given format and a 257 | /// destination region for the date 258 | /// 259 | /// - parameter fromString: date value as string 260 | /// - parameter format: format used to parse string 261 | /// - parameter region: region of destination (date is parsed with the 262 | /// format specified by the string value) 263 | /// 264 | public init?(fromString dateString: String, format: DateFormat, 265 | region nilRegion: Region? = nil) { 266 | 267 | let region = nilRegion ?? Region() 268 | 269 | let cFormatter = sharedDateFormatter() 270 | let parsedDate = cFormatter.beginSessionContext { () -> (NSDate?) in 271 | cFormatter.timeZone = region.timeZone 272 | cFormatter.calendar = region.calendar 273 | cFormatter.locale = region.locale 274 | 275 | let parsedDate: NSDate? 276 | 277 | let stringWithTimeZone = dateString.hasSuffix("Z") 278 | ? dateString.substringToIndex(dateString.endIndex.advancedBy(-1)) + "+0000" 279 | : dateString 280 | 281 | switch format { 282 | case .ISO8601Date: 283 | cFormatter.dateFormat = "yyyy-MM-dd" 284 | parsedDate = cFormatter.dateFromString(stringWithTimeZone) 285 | case .ISO8601: 286 | cFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") 287 | cFormatter.dateFormat = (ISO8601Type.Full).rawValue 288 | parsedDate = cFormatter.dateFromString(stringWithTimeZone) 289 | case .ISO8601Format(let type): 290 | cFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") 291 | cFormatter.dateFormat = type!.rawValue 292 | parsedDate = cFormatter.dateFromString(stringWithTimeZone) 293 | case .AltRSS: // 09 Sep 2011 15:26:08 +0200 294 | cFormatter.dateFormat = "d MMM yyyy HH:mm:ss ZZZ" 295 | parsedDate = cFormatter.dateFromString(stringWithTimeZone) 296 | case .RSS: // Fri, 09 Sep 2011 15:26:08 +0200 297 | cFormatter.dateFormat = "EEE, d MMM yyyy HH:mm:ss ZZZ" 298 | parsedDate = cFormatter.dateFromString(stringWithTimeZone) 299 | case .Extended: 300 | cFormatter.dateFormat = "eee dd-MMM-yyyy GG HH:mm:ss.SSS zzz" 301 | parsedDate = cFormatter.dateFromString(stringWithTimeZone) 302 | case .Custom(let dateFormat): 303 | cFormatter.dateFormat = dateFormat 304 | parsedDate = cFormatter.dateFromString(stringWithTimeZone) 305 | } 306 | return parsedDate 307 | } 308 | 309 | guard parsedDate != nil else { 310 | return nil 311 | } 312 | self.init(absoluteTime: parsedDate!, region: region) 313 | } 314 | 315 | 316 | 317 | /// Convert receiver to another region with the same absolute time. 318 | /// Typically used for regional conversions (time zone, calendar, locale) 319 | /// 320 | /// - parameters: 321 | /// - region: new destination region for the date 322 | /// 323 | /// - returns: the new `DateInRegion` object with the new region 324 | /// 325 | public func inRegion(region: Region) -> DateInRegion { 326 | return DateInRegion(absoluteTime: self.absoluteTime, region: region) 327 | } 328 | } 329 | 330 | // MARK: - CustomStringConvertable delegate 331 | 332 | extension DateInRegion: CustomDebugStringConvertible { 333 | 334 | /// Returns a full description of the class 335 | public var description: String { 336 | let formatter = NSDateFormatter() 337 | formatter.dateStyle = .MediumStyle 338 | formatter.timeStyle = .LongStyle 339 | formatter.locale = self.locale 340 | formatter.calendar = self.calendar 341 | formatter.timeZone = self.timeZone 342 | return formatter.stringFromDate(self.absoluteTime) 343 | } 344 | 345 | /// Returns a full debug description of the class 346 | public var debugDescription: String { 347 | var descriptor: [String] = [] 348 | 349 | let formatter = NSDateFormatter() 350 | formatter.dateStyle = .LongStyle 351 | formatter.timeStyle = .LongStyle 352 | formatter.locale = self.locale 353 | formatter.calendar = self.calendar 354 | formatter.timeZone = self.timeZone 355 | descriptor.append(formatter.stringFromDate(self.absoluteTime)) 356 | 357 | descriptor.append("Calendar: \(calendar.calendarIdentifier)") 358 | descriptor.append("Time zone: \(timeZone.name)") 359 | descriptor.append("Locale: \(locale.localeIdentifier)") 360 | 361 | return descriptor.joinWithSeparator("\n") 362 | } 363 | } 364 | 365 | //MARK: - DateInRegion Hashable - 366 | 367 | extension DateInRegion: Hashable { 368 | 369 | /// Allows to generate an unique hash vaalue for an instance of `DateInRegion` 370 | public var hashValue: Int { 371 | return absoluteTime.hashValue ^ region.hashValue 372 | } 373 | } 374 | -------------------------------------------------------------------------------- /Pods/SwiftDate/Sources/SwiftDate/DateInRegion+Formatter.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftDate, an handy tool to manage date and timezones in swift 3 | // Created by: Daniele Margutti 4 | // Main contributors: Jeroen Houtzager 5 | // 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions: 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software. 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | 25 | import Foundation 26 | 27 | // MARK: - DateInRegion Formatter Extension - 28 | 29 | public extension DateInRegion { 30 | 31 | /** 32 | This method produces a colloquial representation of time elapsed 33 | between this `DateInRegion` (`self`) and another reference `DateInRegion` (`refDate`). 34 | 35 | - parameters: 36 | - refDate: reference date to compare (if not specified current date into `self` region 37 | is used) 38 | - style: style of the output string 39 | 40 | - returns: formatted string or nil if representation cannot be provided 41 | */ 42 | public func toNaturalString(refDate: DateInRegion?, style: FormatterStyle = FormatterStyle()) 43 | -> String? { 44 | 45 | let rDate = (refDate != nil ? refDate! : DateInRegion(absoluteTime: NSDate(), 46 | region: self.region)) 47 | let formatter: NSDateComponentsFormatter = sharedDateComponentsFormatter() 48 | return formatter.beginSessionContext({ (Void) -> (String?) in 49 | style.restoreInto(formatter) 50 | formatter.calendar = self.calendar 51 | // NOTE: why this method still return nil? 52 | // let str2 = formatter.stringFromDate(refDate.absoluteTime, toDate: self.absoluteTime) 53 | let diff = fabs(self.absoluteTime.timeIntervalSinceDate(rDate.absoluteTime)) 54 | let str = formatter.stringFromTimeInterval(diff) 55 | return str 56 | }) 57 | } 58 | 59 | /** 60 | Return an `ISO8601` string for the date. 61 | More information about this standard can be found on 62 | [Wikipedia/ISO8601](https://en.wikipedia.org/wiki/ISO_8601). 63 | 64 | Some examples of the formatted output are: 65 | * `2016-01-11T17:31:10+00:00` 66 | * `2016-01-11T17:31:10Z` 67 | * `20160111T173110Z` 68 | 69 | - returns: a new string or nil if `DateInRegion` does not contains any valid date 70 | */ 71 | @available(*, deprecated=3.0.2, obsoleted=3.1, message="Use toString(.ISO8601)") 72 | public func toISO8601String() -> String? { 73 | return self.toString(.ISO8601) 74 | } 75 | 76 | /** 77 | Convert a DateInRegion to a string using region's timezone, locale and calendar 78 | 79 | - parameter dateFormat: format of the string 80 | 81 | - returns: a new string or nil if DateInRegion does not contains any valid date 82 | */ 83 | public func toString(dateFormat: DateFormat) -> String? { 84 | guard let _ = absoluteTime else { 85 | return nil 86 | } 87 | let cachedFormatter = sharedDateFormatter() 88 | return cachedFormatter.beginSessionContext { (void) -> (String?) in 89 | let dateFormatString = dateFormat.formatString 90 | cachedFormatter.dateFormat = dateFormatString 91 | cachedFormatter.timeZone = self.region.timeZone 92 | cachedFormatter.calendar = self.region.calendar 93 | cachedFormatter.locale = self.region.calendar.locale 94 | let value = cachedFormatter.stringFromDate(self.absoluteTime!) 95 | return value 96 | } 97 | } 98 | 99 | /** 100 | Convert a `DateInRegion` date into a date with date & time style specific format style 101 | 102 | - parameter style: style to format both date and time (if you specify this you don't need to 103 | specify dateStyle,timeStyle) 104 | - parameter dateStyle: style to format the date 105 | - parameter timeStyle: style to format the time 106 | - parameter relative: `true` indicates whether the receiver uses phrases such as “today” and 107 | “tomorrow” for the date component. 108 | 109 | - returns: a new string which represent the date expressed into the current region or nil if 110 | region does not contain valid date 111 | */ 112 | public func toString(style: NSDateFormatterStyle? = nil, dateStyle: NSDateFormatterStyle? = nil, 113 | timeStyle: NSDateFormatterStyle? = nil, relative: Bool = false) -> String? { 114 | guard let _ = absoluteTime else { 115 | return nil 116 | } 117 | 118 | let cachedFormatter = sharedDateFormatter() 119 | return cachedFormatter.beginSessionContext { (void) -> (String?) in 120 | cachedFormatter.dateStyle = style ?? dateStyle ?? .NoStyle 121 | cachedFormatter.timeStyle = style ?? timeStyle ?? .NoStyle 122 | if cachedFormatter.dateStyle == .NoStyle && cachedFormatter.timeStyle == .NoStyle { 123 | cachedFormatter.dateStyle = .MediumStyle 124 | cachedFormatter.timeStyle = .MediumStyle 125 | } 126 | cachedFormatter.locale = self.region.locale 127 | cachedFormatter.calendar = self.region.calendar 128 | cachedFormatter.timeZone = self.region.timeZone 129 | cachedFormatter.doesRelativeDateFormatting = relative 130 | let value = cachedFormatter.stringFromDate(self.absoluteTime) 131 | 132 | return value 133 | } 134 | } 135 | 136 | /** 137 | Convert this `DateInRegion` date in a string representation where you have date/time in short 138 | form 139 | 140 | Example of this output is: 141 | `"1/1/15, 11:00 AM"` 142 | 143 | - parameter date: `true` to include date in output string, `false` to omit it 144 | - parameter time: `true` to include time in output string, `false` to omit it 145 | 146 | - returns: output string representation of the date represented by `self` 147 | */ 148 | public func toShortString(date date: Bool = true, time: Bool = true) -> String? { 149 | let dateStyle = date ? NSDateFormatterStyle.ShortStyle : NSDateFormatterStyle.NoStyle 150 | let timeStyle = time ? NSDateFormatterStyle.ShortStyle : NSDateFormatterStyle.NoStyle 151 | 152 | return toString(dateStyle: dateStyle, timeStyle: timeStyle) 153 | } 154 | 155 | /** 156 | Convert this `DateInRegion` date in a string representation where you have date/time in medium 157 | form 158 | 159 | Example of this output is: 160 | `"Jan 1, 2015, 11:00:00 AM"` 161 | 162 | - parameter date: `true` to include date in output string, `false` to omit it 163 | - parameter time: `true` to include time in output string, `false` to omit it 164 | 165 | - returns: output string representation of the date represented by `self` 166 | */ 167 | public func toMediumString(date date: Bool = true, time: Bool = true) -> String? { 168 | let dateStyle = date ? NSDateFormatterStyle.MediumStyle : NSDateFormatterStyle.NoStyle 169 | let timeStyle = time ? NSDateFormatterStyle.MediumStyle : NSDateFormatterStyle.NoStyle 170 | 171 | return toString(dateStyle: dateStyle, timeStyle: timeStyle) 172 | } 173 | 174 | /** 175 | Convert this `DateInRegion` date in a string representation where you have date/time in long form 176 | 177 | Example of this output is: 178 | `"January 1, 2015 at 11:00:00 AM GMT+1"` 179 | 180 | - parameter date: `true` to include date in output string, `false` to omit it 181 | - parameter time: `true` to include time in output string, `false` to omit it 182 | 183 | - returns: output string representation of the date represented by `self` 184 | */ 185 | public func toLongString(date date: Bool = true, time: Bool = true) -> String? { 186 | let dateStyle = date ? NSDateFormatterStyle.LongStyle : NSDateFormatterStyle.NoStyle 187 | let timeStyle = time ? NSDateFormatterStyle.LongStyle : NSDateFormatterStyle.NoStyle 188 | 189 | return toString(dateStyle: dateStyle, timeStyle: timeStyle) 190 | } 191 | 192 | @available(*, deprecated=2.2, 193 | message="Use toString(style:dateStyle:timeStyle:relative:) with relative parameters") 194 | /** 195 | Output relative string representation of the date. 196 | **This method was deprecated: use `toString(style:dateStyle:timeStyle:)` instead.** 197 | 198 | - parameter style: style of the formatted output 199 | 200 | - returns: string representation 201 | */ 202 | public func toRelativeCocoaString(style style: NSDateFormatterStyle = 203 | NSDateFormatterStyle.MediumStyle) -> String? { 204 | 205 | let cachedFormatter = sharedDateFormatter() 206 | return cachedFormatter.beginSessionContext { (void) -> (String?) in 207 | cachedFormatter.locale = self.region.locale 208 | cachedFormatter.calendar = self.region.calendar 209 | cachedFormatter.timeZone = self.region.timeZone 210 | cachedFormatter.dateStyle = style 211 | cachedFormatter.doesRelativeDateFormatting = true 212 | let str = cachedFormatter.stringFromDate(self.absoluteTime) 213 | return str 214 | } 215 | } 216 | 217 | @available(*, deprecated=2.2, message="Use toNaturalString() with relative parameters") 218 | /** 219 | Output colloquial representation of the string. 220 | **This method was deprecated: use `toString(style:dateStyle:timeStyle:)` instead.** 221 | 222 | - parameter fromDate: reference date 223 | - parameter abbreviated: `true` to use abbreviated form 224 | - parameter maxUnits: number of non zero units to print 225 | 226 | - returns: colloquial string representation 227 | */ 228 | public func toRelativeString(fromDate: DateInRegion!, abbreviated: Bool = false, 229 | maxUnits: Int = 1) -> String { 230 | 231 | let seconds = fromDate.absoluteTime.timeIntervalSinceDate(absoluteTime) 232 | if fabs(seconds) < 1 { 233 | return "just now".sdLocalize 234 | } 235 | 236 | let significantFlags: NSCalendarUnit = DateInRegion.componentFlags 237 | let components = region.calendar.components(significantFlags, 238 | fromDate: fromDate.absoluteTime, toDate: absoluteTime, options: []) 239 | 240 | var string = String() 241 | var numberOfUnits: Int = 0 242 | let unitList: [String] = ["year", "month", "weekOfYear", "day", "hour", "minute", 243 | "second", "nanosecond"] 244 | for unitName in unitList { 245 | let unit: NSCalendarUnit = unitName.sdToCalendarUnit() 246 | if ((significantFlags.rawValue & unit.rawValue) != 0) && 247 | (absoluteTime.sdCompareCalendarUnit(NSCalendarUnit.Nanosecond, other: unit) 248 | != .OrderedDescending) { 249 | 250 | let number: NSNumber = NSNumber(float: 251 | fabsf(components.valueForKey(unitName)!.floatValue)) 252 | if Bool(number.integerValue) { 253 | let singular = (number.unsignedIntegerValue == 1) 254 | let suffix = String(format: "%@ %@", arguments: 255 | [number, absoluteTime.sdLocalizeStringForValue(singular, unit: unit, 256 | abbreviated: abbreviated)]) 257 | if string.isEmpty { 258 | string = suffix 259 | } else if numberOfUnits < maxUnits { 260 | string += String(format: " %@", arguments: [suffix]) 261 | } 262 | numberOfUnits += 1 263 | } 264 | } 265 | } 266 | return string 267 | } 268 | } 269 | 270 | //MARK: - DateInRegion Formatters - 271 | 272 | public extension String { 273 | 274 | /** 275 | Convert a string into `NSDate` by passing conversion format 276 | 277 | - parameter format: format used to parse the string 278 | 279 | - returns: a new `NSDate` instance or nil if something went wrong during parsing 280 | */ 281 | public func toDate(format: DateFormat) -> NSDate? { 282 | return self.toDateInRegion(format)?.absoluteTime 283 | } 284 | 285 | /** 286 | Convert a string into `DateInRegion` by passing conversion format 287 | 288 | - parameter format: format used to parse the string 289 | 290 | - returns: a new `NSDate` instance or nil if something went wrong during parsing 291 | */ 292 | public func toDateInRegion(format: DateFormat) -> DateInRegion? { 293 | return DateInRegion(fromString: self, format: format) 294 | } 295 | 296 | /** 297 | Convert a string which represent an `ISO8601` date into `NSDate` 298 | 299 | - returns: `NSDate` instance or nil if string cannot be parsed 300 | */ 301 | public func toDateFromISO8601() -> NSDate? { 302 | return toDate(DateFormat.ISO8601Format(.Full)) 303 | } 304 | 305 | private var sdLocalize: String { 306 | return NSBundle.mainBundle().localizedStringForKey(self, value: nil, table: "SwiftDate") 307 | } 308 | 309 | private func sdToCalendarUnit() -> NSCalendarUnit { 310 | switch self { 311 | case "year": 312 | return NSCalendarUnit.Year 313 | case "month": 314 | return NSCalendarUnit.Month 315 | case "weekOfYear": 316 | return NSCalendarUnit.WeekOfYear 317 | case "day": 318 | return NSCalendarUnit.Day 319 | case "hour": 320 | return NSCalendarUnit.Hour 321 | case "minute": 322 | return NSCalendarUnit.Minute 323 | case "second": 324 | return NSCalendarUnit.Second 325 | case "nanosecond": 326 | return NSCalendarUnit.Nanosecond 327 | default: 328 | return [] 329 | } 330 | } 331 | } 332 | 333 | 334 | internal extension NSDate { 335 | private func sdCompareCalendarUnit(unit: NSCalendarUnit, other: NSCalendarUnit) -> 336 | NSComparisonResult { 337 | 338 | let nUnit = sdNormalizedCalendarUnit(unit) 339 | let nOther = sdNormalizedCalendarUnit(other) 340 | 341 | if (nUnit == NSCalendarUnit.WeekOfYear) != (nOther == NSCalendarUnit.WeekOfYear) { 342 | if nUnit == NSCalendarUnit.WeekOfYear { 343 | switch nUnit { 344 | case NSCalendarUnit.Year, NSCalendarUnit.Month: 345 | return .OrderedAscending 346 | default: 347 | return .OrderedDescending 348 | } 349 | } else { 350 | switch nOther { 351 | case NSCalendarUnit.Year, NSCalendarUnit.Month: 352 | return .OrderedDescending 353 | default: 354 | return .OrderedAscending 355 | } 356 | } 357 | } else { 358 | if nUnit.rawValue > nOther.rawValue { 359 | return .OrderedAscending 360 | } else if nUnit.rawValue < nOther.rawValue { 361 | return .OrderedDescending 362 | } else { 363 | return .OrderedSame 364 | } 365 | } 366 | } 367 | 368 | private func sdNormalizedCalendarUnit(unit: NSCalendarUnit) -> NSCalendarUnit { 369 | switch unit { 370 | case NSCalendarUnit.WeekOfMonth, NSCalendarUnit.WeekOfYear: 371 | return NSCalendarUnit.WeekOfYear 372 | case NSCalendarUnit.Weekday, NSCalendarUnit.WeekdayOrdinal: 373 | return NSCalendarUnit.Day 374 | default: 375 | return unit 376 | } 377 | } 378 | 379 | 380 | private func sdLocalizeStringForValue(singular: Bool, unit: NSCalendarUnit, 381 | abbreviated: Bool = false) -> String { 382 | 383 | var toTranslate: String = "" 384 | switch unit { 385 | 386 | case NSCalendarUnit.Year where singular: 387 | toTranslate = (abbreviated ? "yr": "year") 388 | case NSCalendarUnit.Year where !singular: 389 | toTranslate = (abbreviated ? "yrs": "years") 390 | 391 | case NSCalendarUnit.Month where singular: 392 | toTranslate = (abbreviated ? "mo": "month") 393 | case NSCalendarUnit.Month where !singular: 394 | toTranslate = (abbreviated ? "mos": "months") 395 | 396 | case NSCalendarUnit.WeekOfYear where singular: 397 | toTranslate = (abbreviated ? "wk": "week") 398 | case NSCalendarUnit.WeekOfYear where !singular: 399 | toTranslate = (abbreviated ? "wks": "weeks") 400 | 401 | case NSCalendarUnit.Day where singular: 402 | toTranslate = "day" 403 | case NSCalendarUnit.Day where !singular: 404 | toTranslate = "days" 405 | 406 | case NSCalendarUnit.Hour where singular: 407 | toTranslate = (abbreviated ? "hr": "hour") 408 | case NSCalendarUnit.Hour where !singular: 409 | toTranslate = (abbreviated ? "hrs": "hours") 410 | 411 | case NSCalendarUnit.Minute where singular: 412 | toTranslate = (abbreviated ? "min": "minute") 413 | case NSCalendarUnit.Minute where !singular: 414 | toTranslate = (abbreviated ? "mins": "minutes") 415 | 416 | case NSCalendarUnit.Second where singular: 417 | toTranslate = (abbreviated ? "s": "second") 418 | case NSCalendarUnit.Second where !singular: 419 | toTranslate = (abbreviated ? "s": "seconds") 420 | 421 | case NSCalendarUnit.Nanosecond where singular: 422 | toTranslate = (abbreviated ? "ns": "nanosecond") 423 | case NSCalendarUnit.Nanosecond where !singular: 424 | toTranslate = (abbreviated ? "ns": "nanoseconds") 425 | 426 | default: 427 | toTranslate = "" 428 | } 429 | return toTranslate.sdLocalize 430 | } 431 | 432 | func localizedSimpleStringForComponents(components: NSDateComponents) -> String { 433 | if components.year == -1 { 434 | return "last year".sdLocalize 435 | } else if components.month == -1 && components.year == 0 { 436 | return "last month".sdLocalize 437 | } else if components.weekOfYear == -1 && components.year == 0 && components.month == 0 { 438 | return "last week".sdLocalize 439 | } else if components.day == -1 && components.year == 0 && components.month == 0 && 440 | components.weekOfYear == 0 { 441 | return "yesterday".sdLocalize 442 | } else if components == 1 { 443 | return "next year".sdLocalize 444 | } else if components.month == 1 && components.year == 0 { 445 | return "next month".sdLocalize 446 | } else if components.weekOfYear == 1 && components.year == 0 && components.month == 0 { 447 | return "next week".sdLocalize 448 | } else if components.day == 1 && components.year == 0 && components.month == 0 && 449 | components.weekOfYear == 0 { 450 | return "tomorrow".sdLocalize 451 | } 452 | return "" 453 | } 454 | } 455 | --------------------------------------------------------------------------------