├── screenshots
└── 00.png
├── ZBJCalendar
├── Assets.xcassets
│ ├── Contents.json
│ ├── unav.imageset
│ │ ├── 可租.png
│ │ └── Contents.json
│ ├── cancel.imageset
│ │ ├── 关闭.png
│ │ └── Contents.json
│ ├── unavaible.imageset
│ │ ├── 订单页.png
│ │ └── Contents.json
│ ├── AppIcon.appiconset
│ │ ├── logo120.png
│ │ ├── logo180.png
│ │ └── Contents.json
│ ├── cal_selected.imageset
│ │ ├── selected@2x.png
│ │ └── Contents.json
│ ├── cal_selected_left.imageset
│ │ ├── left@2x.png
│ │ └── Contents.json
│ ├── cal_selected_right.imageset
│ │ ├── right@2x.png
│ │ └── Contents.json
│ └── cal_selected_middle.imageset
│ │ ├── middle@2x.png
│ │ └── Contents.json
├── ViewController.h
├── CommonViews
│ ├── ZBJCalendarSectionFooter.h
│ ├── ZBJCalendarSectionHeader.h
│ ├── ZBJCalendarSectionFooter.m
│ └── ZBJCalendarSectionHeader.m
├── SingleSelection
│ ├── ZBJSingleSelectionController.h
│ ├── UINavigationBar+ZBJAddition.h
│ ├── ZBJSingleSelectionHeaderView.h
│ ├── ZBJSingleSelectionCell.h
│ ├── UINavigationBar+ZBJAddition.m
│ ├── ZBJSingleSelectionHeaderView.m
│ ├── ZBJSingleSelectionCell.m
│ └── ZBJSingleSelectionController.m
├── AppDelegate.h
├── main.m
├── ZBJCalendar
│ ├── ZBJCalendar.h
│ ├── NSDate+IndexPath.h
│ ├── NSDate+ZBJAddition.h
│ ├── ZBJCalendarWeekView.h
│ ├── NSDate+IndexPath.m
│ ├── ZBJCalendarWeekView.m
│ ├── NSDate+ZBJAddition.m
│ └── ZBJCalendarView.h
├── MutipleSelection
│ ├── ZBJSimpleMutipleSelectionViewController.h
│ ├── ZBJMutipleSelectionSectionHeaderView.h
│ ├── ZBJSimpleMutipleSelectionCell.h
│ ├── ZBJMutipleSelectionSectionHeaderView.m
│ ├── ZBJSimpleMutipleSelectionCell.m
│ └── ZBJSimpleMutipleSelectionViewController.m
├── Show
│ ├── ZBJCalendarShowView.h
│ ├── ZBJCalendarShowCell.h
│ ├── ZBJCalendarShowCell.m
│ └── ZBJCalendarShowView.m
├── RangeSelection
│ ├── simple
│ │ ├── ZBJSimpleRangeSelectionController.h
│ │ ├── ZBJSimpleRangeSelectionCell.h
│ │ ├── ZBJSimpleRangeSelectionCell.m
│ │ └── ZBJSimpleRangeSelectionController.m
│ └── complex
│ │ ├── ZBJComplexRangeSelectionCell.h
│ │ ├── ZBJComplexRangeSelectionController.h
│ │ ├── ZBJComplexRangeSelectionCell.m
│ │ └── ZBJComplexRangeSelectionController.m
├── Model
│ ├── ZBJCalendarDates.h
│ ├── ZBJCalendarDates.m
│ └── calendar_dates.json
├── Info.plist
├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
├── AppDelegate.m
└── ViewController.m
├── ZBJCalendar.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ │ └── wanggang.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── xcuserdata
│ └── wanggang.xcuserdatad
│ │ ├── xcschemes
│ │ └── xcschememanagement.plist
│ │ └── xcdebugger
│ │ └── Breakpoints_v2.xcbkptlist
└── xcshareddata
│ └── xcschemes
│ └── ZBJCalendar.xcscheme
├── .travis.yml.bak
├── .gitignore
├── ZBJCalendar.podspec
├── ZBJCalendarTests
├── Info.plist
└── ZBJCalendarTests.m
├── ZBJCalendarUITests
├── Info.plist
└── ZBJCalendarUITests.m
├── LICENSE
├── README.md
└── calendar_dates.json
/screenshots/00.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wanggang316/ZBJCalendar/HEAD/screenshots/00.png
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/unav.imageset/可租.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wanggang316/ZBJCalendar/HEAD/ZBJCalendar/Assets.xcassets/unav.imageset/可租.png
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/cancel.imageset/关闭.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wanggang316/ZBJCalendar/HEAD/ZBJCalendar/Assets.xcassets/cancel.imageset/关闭.png
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/unavaible.imageset/订单页.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wanggang316/ZBJCalendar/HEAD/ZBJCalendar/Assets.xcassets/unavaible.imageset/订单页.png
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/AppIcon.appiconset/logo120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wanggang316/ZBJCalendar/HEAD/ZBJCalendar/Assets.xcassets/AppIcon.appiconset/logo120.png
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/AppIcon.appiconset/logo180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wanggang316/ZBJCalendar/HEAD/ZBJCalendar/Assets.xcassets/AppIcon.appiconset/logo180.png
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/cal_selected.imageset/selected@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wanggang316/ZBJCalendar/HEAD/ZBJCalendar/Assets.xcassets/cal_selected.imageset/selected@2x.png
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/cal_selected_left.imageset/left@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wanggang316/ZBJCalendar/HEAD/ZBJCalendar/Assets.xcassets/cal_selected_left.imageset/left@2x.png
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/cal_selected_right.imageset/right@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wanggang316/ZBJCalendar/HEAD/ZBJCalendar/Assets.xcassets/cal_selected_right.imageset/right@2x.png
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/cal_selected_middle.imageset/middle@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wanggang316/ZBJCalendar/HEAD/ZBJCalendar/Assets.xcassets/cal_selected_middle.imageset/middle@2x.png
--------------------------------------------------------------------------------
/ZBJCalendar.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ZBJCalendar.xcodeproj/project.xcworkspace/xcuserdata/wanggang.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wanggang316/ZBJCalendar/HEAD/ZBJCalendar.xcodeproj/project.xcworkspace/xcuserdata/wanggang.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/ZBJCalendar/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 15/12/8.
6 | // Copyright © 2015年 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ViewController : UITableViewController
12 |
13 |
14 | @end
15 |
16 |
--------------------------------------------------------------------------------
/.travis.yml.bak:
--------------------------------------------------------------------------------
1 | # language: objective-c #语言种类
2 |
3 | # xcode_project: ZBJCalendar.xcodeproj # 项目文件相对于.travis.yml文件的路径
4 |
5 | # xcode_scheme: ZBJCalendar #你需要集成测试的scheme
6 |
7 | language: objective-c
8 | osx_image: xcode7.3
9 | xcode_project: ZBJCalendar.xcodeproj
10 | xcode_scheme: ZBJCalendar
11 | xcode_sdk: iphonesimulator9.2
12 |
--------------------------------------------------------------------------------
/ZBJCalendar/CommonViews/ZBJCalendarSectionFooter.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendarSectionFooter.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 3/15/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ZBJCalendarSectionFooter : UICollectionReusableView
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/ZBJCalendar/SingleSelection/ZBJSingleSelectionController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJSingleSelectionController.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 5/26/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ZBJSingleSelectionController : UIViewController
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/ZBJCalendar/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 15/12/8.
6 | // Copyright © 2015年 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface AppDelegate : UIResponder
12 |
13 | @property (strong, nonatomic) UIWindow *window;
14 |
15 |
16 | @end
17 |
18 |
--------------------------------------------------------------------------------
/ZBJCalendar/SingleSelection/UINavigationBar+ZBJAddition.h:
--------------------------------------------------------------------------------
1 | //
2 | // UINavigationBar+ZBJAddition.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 5/26/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface UINavigationBar (ZBJAddition)
12 |
13 | - (void)hidenHairLine:(BOOL)hiden;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/ZBJCalendar/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 15/12/8.
6 | // Copyright © 2015年 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "AppDelegate.h"
11 |
12 | int main(int argc, char * argv[]) {
13 | @autoreleasepool {
14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/ZBJCalendar/SingleSelection/ZBJSingleSelectionHeaderView.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJSingleSelectionHeaderView.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 5/26/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ZBJSingleSelectionHeaderView : UICollectionReusableView
12 |
13 | @property (nonatomic, strong) NSDate *firstDateOfMonth;
14 |
15 | @end
16 |
--------------------------------------------------------------------------------
/ZBJCalendar/ZBJCalendar/ZBJCalendar.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendar.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 3/2/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #ifndef ZBJCalendar_h
10 | #define ZBJCalendar_h
11 |
12 | #import "ZBJCalendarView.h"
13 | #import "ZBJCalendarWeekView.h"
14 | #import "NSDate+ZBJAddition.h"
15 | #import "NSDate+IndexPath.h"
16 |
17 | #endif /* ZBJCalendar_h */
18 |
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/cancel.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "关闭.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/unav.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "可租.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/unavaible.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "订单页.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/ZBJCalendar/CommonViews/ZBJCalendarSectionHeader.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendarSectionHeader.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 2/24/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ZBJCalendarSectionHeader : UICollectionReusableView
12 |
13 | @property (nonatomic, assign) NSInteger year;
14 | @property (nonatomic, assign) NSInteger month;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/cal_selected.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "selected@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/cal_selected_left.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "left@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/cal_selected_middle.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "middle@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/cal_selected_right.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "scale" : "1x"
6 | },
7 | {
8 | "idiom" : "universal",
9 | "filename" : "right@2x.png",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/ZBJCalendar/MutipleSelection/ZBJSimpleMutipleSelectionViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJSimpleMutipleSelectionViewController.h
3 | // ZBJCalendar
4 | //
5 | // Created by wanggang on 7/4/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ZBJSimpleMutipleSelectionViewController : UIViewController
12 |
13 | @property (nonatomic, assign) NSInteger year;
14 | @property (nonatomic, assign) NSInteger month;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/ZBJCalendar/Show/ZBJCalendarShowView.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendarShowView.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 3/15/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "ZBJCalendarDates.h"
11 |
12 | @interface ZBJCalendarShowView : UIView
13 |
14 | - (instancetype)initWithFrame:(CGRect)frame calendarDates:(ZBJCalendarDates *)calendarDates;
15 |
16 | @property (nonatomic, strong) ZBJCalendarDates *calendarDates;
17 |
18 |
19 | @end
20 |
--------------------------------------------------------------------------------
/ZBJCalendar/MutipleSelection/ZBJMutipleSelectionSectionHeaderView.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJMutipleSelectionSectionHeaderView.h
3 | // ZBJCalendar
4 | //
5 | // Created by wanggang on 7/4/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef void (^ZBJMonthTappedHandler)(NSDate *month);
12 | @interface ZBJMutipleSelectionSectionHeaderView : UICollectionReusableView
13 |
14 | @property (nonatomic, strong) NSDate *firstDateOfMonth;
15 | @property (nonatomic, copy) ZBJMonthTappedHandler tapHandler;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | build/
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 |
20 | # CocoaPods
21 | #
22 | # We recommend against adding the Pods directory to your .gitignore. However
23 | # you should judge for yourself, the pros and cons are mentioned at:
24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
25 | #
26 | #Pods/
--------------------------------------------------------------------------------
/ZBJCalendar/SingleSelection/ZBJSingleSelectionCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJSingleSelectionCell.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 5/26/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef CF_ENUM(NSInteger, ZBJCalendarCellState) {
12 | ZBJCalendarCellStateEmpty,
13 | ZBJCalendarCellStateNormal,
14 | ZBJCalendarCellStateSelected,
15 | };
16 |
17 |
18 |
19 | @interface ZBJSingleSelectionCell : UICollectionViewCell
20 |
21 | @property (nonatomic, strong) NSDate *date;
22 | @property (nonatomic, assign) ZBJCalendarCellState cellState;
23 |
24 | @end
25 |
--------------------------------------------------------------------------------
/ZBJCalendar/ZBJCalendar/NSDate+IndexPath.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSDate+IndexPath.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 2/29/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /**
12 | * This category provide methods used to corresponding relations between indexpath and date.
13 | */
14 | @interface NSDate (IndexPath)
15 |
16 | + (NSDate *)dateForFirstDayInSection:(NSInteger)section firstDate:(NSDate *)firstDate;
17 | + (NSDate *)dateAtIndexPath:(NSIndexPath *)indexPath firstDate:(NSDate *)firstDate;
18 | + (NSIndexPath *)indexPathAtDate:(NSDate *)date firstDate:(NSDate *)firstDate;
19 |
20 | @end
21 |
--------------------------------------------------------------------------------
/ZBJCalendar.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 |
3 | s.name = "ZBJCalendar"
4 | s.version = "0.0.9"
5 | s.summary = "ZBJCalendar is a simple calendar framework."
6 |
7 | s.homepage = "https://github.com/wanggang316/ZBJCalendar"
8 | s.license = "MIT"
9 | s.authors = { "Gump" => "gummpwang@gmail.com" }
10 | s.social_media_url = "https://twitter.com/wgang316"
11 | s.platform = :ios, "7.0"
12 | s.source = { :git => "https://github.com/wanggang316/ZBJCalendar.git", :tag => s.version }
13 |
14 | s.source_files = "ZBJCalendar/ZBJCalendar/*.{h,m}"
15 | s.public_header_files = "ZBJCalendar/ZBJCalendar/*.h"
16 |
17 |
18 | end
19 |
--------------------------------------------------------------------------------
/ZBJCalendar/Show/ZBJCalendarShowCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendarShowCell.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 3/15/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef CF_ENUM(NSInteger, ZBJCalendarCellState) {
12 | ZBJCalendarCellStateEmpty,
13 | ZBJCalendarCellStateDisabled,
14 | ZBJCalendarCellStateAvaible,
15 | ZBJCalendarCellStateUnavaible,
16 | };
17 |
18 | @interface ZBJCalendarShowCell : UICollectionViewCell
19 |
20 | @property (nonatomic, strong) NSDate *date;
21 | @property (nonatomic, strong) NSNumber *price;
22 |
23 | @property (nonatomic, assign) ZBJCalendarCellState cellState;
24 |
25 | @end
26 |
--------------------------------------------------------------------------------
/ZBJCalendar/CommonViews/ZBJCalendarSectionFooter.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendarSectionFooter.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 3/15/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJCalendarSectionFooter.h"
10 |
11 | @implementation ZBJCalendarSectionFooter
12 |
13 | - (instancetype)initWithFrame:(CGRect)frame {
14 | if (self = [super initWithFrame:frame]) {
15 | CALayer *layer = [CALayer layer];
16 | layer.frame = CGRectMake(0, CGRectGetHeight(self.frame) - 0.5, CGRectGetWidth(self.frame), 0.5);
17 | layer.backgroundColor = [UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:233.0/255.0 alpha:1.0].CGColor;
18 | [self.layer addSublayer:layer];
19 | }
20 | return self;
21 | }
22 |
23 | @end
24 |
--------------------------------------------------------------------------------
/ZBJCalendar/RangeSelection/simple/ZBJSimpleRangeSelectionController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJSimpleRangeSelectionController.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 2/26/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @protocol ZBJCalendarRangeSelectorDelegate;
12 |
13 | @interface ZBJSimpleRangeSelectionController : UIViewController
14 |
15 | @property (nonatomic, weak) id delegate;
16 |
17 | @property (nonatomic, strong) NSDate *startDate;
18 | @property (nonatomic, strong) NSDate *endDate;
19 |
20 | @end
21 |
22 | @protocol ZBJCalendarRangeSelectorDelegate
23 |
24 | - (void)popViewController:(UIViewController *)viewController startDate:(NSDate *)startDate endDate:(NSDate *)endDate;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/ZBJCalendar/MutipleSelection/ZBJSimpleMutipleSelectionCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJMutipleSelectionCell.h
3 | // ZBJCalendar
4 | //
5 | // Created by wanggang on 7/4/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef CF_ENUM(NSInteger, ZBJCalendarCellState) {
12 | ZBJCalendarCellStateEmpty = 0,
13 | ZBJCalendarCellStateDisabled = 1,
14 | ZBJCalendarCellStateNormal = 2,
15 | ZBJCalendarCellStateSelected = 3,
16 | ZBJCalendarCellStateSelectedLeft = 4,
17 | ZBJCalendarCellStateSelectedMiddle = 5,
18 | ZBJCalendarCellStateSelectedRight = 6,
19 | };
20 |
21 | @interface ZBJSimpleMutipleSelectionCell : UICollectionViewCell
22 |
23 | @property (nonatomic, strong) NSDate *date;
24 | @property (nonatomic, assign) ZBJCalendarCellState cellState;
25 |
26 | @end
27 |
--------------------------------------------------------------------------------
/ZBJCalendarTests/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 |
--------------------------------------------------------------------------------
/ZBJCalendarUITests/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 |
--------------------------------------------------------------------------------
/ZBJCalendar/Model/ZBJCalendarDates.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendarDates.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 3/10/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ZBJCalendarDates : NSObject
12 |
13 | @property (nonatomic, strong) NSNumber *offerId;
14 | @property (nonatomic, strong) NSDate *startDate;
15 | @property (nonatomic, strong) NSDate *endDate;
16 |
17 | @property (nonatomic, strong, readonly) NSSet *dates;
18 |
19 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary;
20 |
21 | @end
22 |
23 | @interface ZBJCalendarDate : NSObject
24 |
25 | @property (nonatomic, strong) NSDate *date;
26 | @property (nonatomic, strong) NSNumber *available;
27 | @property (nonatomic, strong) NSNumber *price;
28 |
29 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary;
30 |
31 | @end
32 |
--------------------------------------------------------------------------------
/ZBJCalendar.xcodeproj/xcuserdata/wanggang.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | ZBJCalendar.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 32F7EBE51C16779F00ED2DA4
16 |
17 | primary
18 |
19 |
20 | 32F7EBFE1C16779F00ED2DA4
21 |
22 | primary
23 |
24 |
25 | 32F7EC091C16779F00ED2DA4
26 |
27 | primary
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/ZBJCalendar/SingleSelection/UINavigationBar+ZBJAddition.m:
--------------------------------------------------------------------------------
1 | //
2 | // UINavigationBar+ZBJAddition.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 5/26/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "UINavigationBar+ZBJAddition.h"
10 |
11 | @implementation UINavigationBar (ZBJAddition)
12 |
13 | - (void)hidenHairLine:(BOOL)hiden {
14 | UIImageView *lineView = [self findHairlineFromView:self];
15 | lineView.hidden = hiden;
16 | }
17 |
18 | - (UIImageView *)findHairlineFromView:(UIView *)view
19 | {
20 | if ([view isKindOfClass:[UIImageView class]] && view.frame.size.height <= 1.0) {
21 | return (UIImageView *)view;
22 | }
23 |
24 | for (UIView *subView in view.subviews) {
25 | UIImageView *imageView = [self findHairlineFromView:subView];
26 | if (imageView) {
27 | return imageView;
28 | }
29 | }
30 |
31 | return nil;
32 | }
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/ZBJCalendar/RangeSelection/simple/ZBJSimpleRangeSelectionCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJSimpleRangeSelectionCell.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 3/15/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef CF_ENUM(NSInteger, ZBJCalendarCellState) {
12 | ZBJCalendarCellStateEmpty,
13 | ZBJCalendarCellStateDisabled,
14 | ZBJCalendarCellStateAvaible,
15 | ZBJCalendarCellStateAvaibleDisabled,
16 | ZBJCalendarCellStateSelectedStart,
17 | ZBJCalendarCellStateSelectedMiddle,
18 | ZBJCalendarCellStateSelectedEnd,
19 | };
20 |
21 | typedef CF_ENUM(NSInteger, ZBJRangeCellStyle) {
22 | ZBJRangeCellStyle1 = 0,
23 | ZBJRangeCellStyle2,
24 | };
25 |
26 | @interface ZBJSimpleRangeSelectionCell : UICollectionViewCell
27 |
28 | @property (nonatomic, strong) NSDate *date;
29 | @property (nonatomic, assign) ZBJCalendarCellState cellState;
30 |
31 | @property (nonatomic, assign) ZBJRangeCellStyle cellStyle;
32 | @end
33 |
--------------------------------------------------------------------------------
/ZBJCalendar/RangeSelection/complex/ZBJComplexRangeSelectionCell.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJComplexRangeSelectionCell.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 2/24/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | typedef CF_ENUM(NSInteger, ZBJCalendarCellState) {
12 | ZBJCalendarCellStateEmpty,
13 | ZBJCalendarCellStateDisabled,
14 | ZBJCalendarCellStateUnavaible,
15 | ZBJCalendarCellStateAvaible,
16 | ZBJCalendarCellStateAvaibleDisabled,
17 | ZBJCalendarCellStateSelectedStart,
18 | ZBJCalendarCellStateSelectedMiddle,
19 | ZBJCalendarCellStateSelectedEnd,
20 | ZBJCalendarCellStateSelectedTempEnd,
21 | };
22 |
23 |
24 | @interface ZBJComplexRangeSelectionCell : UICollectionViewCell
25 |
26 | @property (nonatomic, strong) NSDate *day;
27 | @property (nonatomic, strong) NSNumber *price;
28 | @property (nonatomic, assign) BOOL isToday;
29 |
30 | @property (nonatomic, assign) ZBJCalendarCellState cellState;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/ZBJCalendar/RangeSelection/complex/ZBJComplexRangeSelectionController.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJComplexRangeSelectionController.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 3/10/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "ZBJCalendarDates.h"
11 |
12 | @protocol ZBJCalendarAdvanceSelectorDelegate;
13 |
14 | @interface ZBJComplexRangeSelectionController : UIViewController
15 |
16 | @property (nonatomic, weak) id delegate;
17 |
18 | @property (nonatomic, strong) NSDate *firstDate;
19 | @property (nonatomic, strong) NSDate *lastDate;
20 |
21 | @property (nonatomic, strong) NSSet *dates;
22 |
23 | @property (nonatomic, assign) NSInteger minNights; // 最小入住天数
24 |
25 | @property (nonatomic, strong) NSDate *startDate;
26 | @property (nonatomic, strong) NSDate *endDate;
27 |
28 | @end
29 |
30 | @protocol ZBJCalendarAdvanceSelectorDelegate
31 |
32 | - (void)popViewController:(UIViewController *)viewController startDate:(NSDate *)startDate endDate:(NSDate *)endDate;
33 |
34 | @end
35 |
--------------------------------------------------------------------------------
/ZBJCalendarTests/ZBJCalendarTests.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendarTests.m
3 | // ZBJCalendarTests
4 | //
5 | // Created by 王刚 on 15/12/8.
6 | // Copyright © 2015年 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ZBJCalendarTests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation ZBJCalendarTests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 | // Put setup code here. This method is called before the invocation of each test method in the class.
20 | }
21 |
22 | - (void)tearDown {
23 | // Put teardown code here. This method is called after the invocation of each test method in the class.
24 | [super tearDown];
25 | }
26 |
27 | - (void)testExample {
28 | // This is an example of a functional test case.
29 | // Use XCTAssert and related functions to verify your tests produce the correct results.
30 | }
31 |
32 | - (void)testPerformanceExample {
33 | // This is an example of a performance test case.
34 | [self measureBlock:^{
35 | // Put the code you want to measure the time of here.
36 | }];
37 | }
38 |
39 | @end
40 |
--------------------------------------------------------------------------------
/ZBJCalendar/ZBJCalendar/NSDate+ZBJAddition.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSDate+ZBJAddition.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 2/26/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | /**
12 | * This category provide utility methods for `NSDate`.
13 | */
14 | @interface NSDate (ZBJAddition)
15 |
16 | + (NSCalendar *)gregorianCalendar;
17 | + (NSLocale *)locale;
18 |
19 | + (NSDate *)today;
20 | + (NSInteger)numberOfMonthsFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate;
21 | + (NSInteger)numberOfDaysFromMonth:(NSDate *)fromMonth toMonth:(NSDate *)toMonth;
22 | + (NSInteger)numberOfDaysInMonth:(NSDate *)date;
23 | + (NSInteger)numberOfNightsFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate;
24 |
25 | - (NSDate *)firstDateOfMonth;
26 | - (NSDate *)firstDateOfWeek;
27 | - (NSDate *)lastDateOfMonth;
28 |
29 | - (NSInteger)weekday;
30 |
31 | - (BOOL)isToday;
32 | - (BOOL)isWeekend;
33 |
34 | //- (BOOL)isEqualToDate:(NSDate *)date toUnitGranularity:(NSCalendarUnit)unit;
35 | - (BOOL)isSameMonthWithDate:(NSDate *)date;
36 | @end
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Copyright (c) 2015-2016 gumpwangg
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy
5 | of this software and associated documentation files (the "Software"), to deal
6 | in the Software without restriction, including without limitation the rights
7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the Software is
9 | furnished to do so, subject to the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be included in
12 | all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 | THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/ZBJCalendarUITests/ZBJCalendarUITests.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendarUITests.m
3 | // ZBJCalendarUITests
4 | //
5 | // Created by 王刚 on 15/12/8.
6 | // Copyright © 2015年 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @interface ZBJCalendarUITests : XCTestCase
12 |
13 | @end
14 |
15 | @implementation ZBJCalendarUITests
16 |
17 | - (void)setUp {
18 | [super setUp];
19 |
20 | // Put setup code here. This method is called before the invocation of each test method in the class.
21 |
22 | // In UI tests it is usually best to stop immediately when a failure occurs.
23 | self.continueAfterFailure = NO;
24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
25 | [[[XCUIApplication alloc] init] launch];
26 |
27 | // 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.
28 | }
29 |
30 | - (void)tearDown {
31 | // Put teardown code here. This method is called after the invocation of each test method in the class.
32 | [super tearDown];
33 | }
34 |
35 | - (void)testExample {
36 | // Use recording to get started writing UI tests.
37 | // Use XCTAssert and related functions to verify your tests produce the correct results.
38 | }
39 |
40 | @end
41 |
--------------------------------------------------------------------------------
/ZBJCalendar/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "size" : "60x60",
25 | "idiom" : "iphone",
26 | "filename" : "logo120.png",
27 | "scale" : "2x"
28 | },
29 | {
30 | "size" : "60x60",
31 | "idiom" : "iphone",
32 | "filename" : "logo180.png",
33 | "scale" : "3x"
34 | },
35 | {
36 | "idiom" : "ipad",
37 | "size" : "29x29",
38 | "scale" : "1x"
39 | },
40 | {
41 | "idiom" : "ipad",
42 | "size" : "29x29",
43 | "scale" : "2x"
44 | },
45 | {
46 | "idiom" : "ipad",
47 | "size" : "40x40",
48 | "scale" : "1x"
49 | },
50 | {
51 | "idiom" : "ipad",
52 | "size" : "40x40",
53 | "scale" : "2x"
54 | },
55 | {
56 | "idiom" : "ipad",
57 | "size" : "76x76",
58 | "scale" : "1x"
59 | },
60 | {
61 | "idiom" : "ipad",
62 | "size" : "76x76",
63 | "scale" : "2x"
64 | },
65 | {
66 | "idiom" : "ipad",
67 | "size" : "83.5x83.5",
68 | "scale" : "2x"
69 | }
70 | ],
71 | "info" : {
72 | "version" : 1,
73 | "author" : "xcode"
74 | }
75 | }
--------------------------------------------------------------------------------
/ZBJCalendar/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 | APPL
17 | CFBundleShortVersionString
18 | 0.0.1
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UIStatusBarStyle
34 | UIStatusBarStyleDefault
35 | UISupportedInterfaceOrientations
36 |
37 | UIInterfaceOrientationPortrait
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 | UIViewControllerBasedStatusBarAppearance
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/ZBJCalendar/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/ZBJCalendar/ZBJCalendar/ZBJCalendarWeekView.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendarWeekView.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 16/2/25.
6 | // Copyright © 2016年 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | @protocol ZBJCalendarWeekViewDelegate;
12 |
13 | /**
14 | * `ZBJCalendarWeekView` is the default view for display week days.
15 | * By default, is contains 7 labels present monday to sunday.
16 | * You can custom weekView style by the public property `weekView` of `ZBJCalendarView`.
17 | * If you want to change each week day's style, you can conform the `ZBJCalendarWeekViewDelegate` and implement `- (void)calendarWeekView:(ZBJCalendarWeekView *)weekView configureWeekDayLabel:(UILabel *)dayLabel atWeekDay:(NSInteger)weekDay;` method.
18 | */
19 | @interface ZBJCalendarWeekView : UIView
20 |
21 | /**
22 | * A reference of `ZBJCalendarWeekViewDelegate` which can custom week day label.
23 | */
24 | @property (nonatomic, weak) id delegate;
25 |
26 | /**
27 | * The inner padding of week view.
28 | */
29 | @property (nonatomic, assign) UIEdgeInsets contentInsets; // the inner padding
30 |
31 | /**
32 | * Default line at the bottom of week view.
33 | */
34 | @property (nonatomic, strong) CALayer *bottomLine;
35 |
36 | /**
37 | * reload week View manual
38 | */
39 | - (void)reloadWeekView;
40 |
41 | @end
42 |
43 | @protocol ZBJCalendarWeekViewDelegate
44 |
45 | @optional
46 | /**
47 | * Used to configure the weekday label with the `weekDay`
48 | *
49 | * @param weekView self
50 | * @param dayLabel weekday label
51 | * @param weekDay integer of the weekday
52 | */
53 | - (void)calendarWeekView:(ZBJCalendarWeekView *)weekView configureWeekDayLabel:(UILabel *)dayLabel atWeekDay:(NSInteger)weekDay;
54 |
55 | @end
56 |
--------------------------------------------------------------------------------
/ZBJCalendar/SingleSelection/ZBJSingleSelectionHeaderView.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJSingleSelectionHeaderView.m
3 | // ZBJCalendar
4 | //
5 | // Created by wanggang on 5/26/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJSingleSelectionHeaderView.h"
10 | #import "ZBJCalendar.h"
11 |
12 | @interface ZBJSingleSelectionHeaderView ()
13 |
14 | @property (nonatomic, strong) UILabel *monthLabel;
15 | @property (nonatomic, assign) NSInteger weekday;
16 | @end
17 | @implementation ZBJSingleSelectionHeaderView
18 |
19 |
20 | - (id)initWithFrame:(CGRect)frame {
21 | self = [super initWithFrame:frame];
22 | if (self) {
23 | [self addSubview:self.monthLabel];
24 | }
25 | return self;
26 | }
27 |
28 | - (void)layoutSubviews {
29 | [super layoutSubviews];
30 | self.monthLabel.frame = CGRectMake(0, 0, CGRectGetWidth(self.monthLabel.frame), 20);
31 | self.monthLabel.center = CGPointMake(25 * ((self.weekday - 1) * 2 + 1), CGRectGetHeight(self.frame) / 2);
32 | }
33 |
34 | #pragma mark - setters
35 | - (void)setFirstDateOfMonth:(NSDate *)firstDateOfMonth {
36 | _firstDateOfMonth = firstDateOfMonth;
37 | NSCalendar *calendar = [NSDate gregorianCalendar];
38 | NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitWeekday fromDate:firstDateOfMonth];
39 | self.weekday = components.weekday;
40 | self.monthLabel.text = [NSString stringWithFormat:@"%ld月", components.month];
41 | [self.monthLabel sizeToFit];
42 | [self layoutSubviews];
43 | }
44 |
45 |
46 | #pragma mark - getters
47 | - (UILabel *)monthLabel {
48 | if (!_monthLabel) {
49 | _monthLabel = [[UILabel alloc] init];
50 | _monthLabel.font = [UIFont systemFontOfSize:17];
51 | _monthLabel.textColor = [UIColor darkTextColor];
52 | }
53 | return _monthLabel;
54 | }
55 | @end
56 |
--------------------------------------------------------------------------------
/ZBJCalendar/Model/ZBJCalendarDates.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendarDates.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 3/10/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJCalendarDates.h"
10 |
11 | @interface ZBJCalendarDates()
12 |
13 | @property (nonatomic, strong, readwrite) NSMutableSet *adates;
14 |
15 | @end
16 |
17 | @implementation ZBJCalendarDates
18 |
19 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary {
20 | if (self = [super init]) {
21 |
22 | NSDateFormatter *format = [[NSDateFormatter alloc] init];
23 | [format setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
24 | [format setDateFormat:@"yyyy-MM-dd"];
25 |
26 | self.offerId = [dictionary objectForKey:@"offer_id"];
27 | self.startDate = [format dateFromString:[dictionary objectForKey:@"start_date"]];
28 | self.endDate = [format dateFromString:[dictionary objectForKey:@"end_date"]];
29 |
30 | self.adates = [NSMutableSet new];
31 | NSArray *datesArr = [dictionary objectForKey:@"dates"];
32 | for (NSDictionary *dic in datesArr) {
33 | [self.adates addObject:[[ZBJCalendarDate alloc] initWithDictionary:dic]];
34 | }
35 | }
36 | return self;
37 | }
38 |
39 | - (NSArray *)dates {
40 | return [self.adates copy];
41 | }
42 |
43 | @end
44 |
45 |
46 | @implementation ZBJCalendarDate
47 |
48 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary {
49 | if (self = [super init]) {
50 | NSDateFormatter *format = [[NSDateFormatter alloc] init];
51 | [format setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
52 | [format setDateFormat:@"yyyy-MM-dd"];
53 |
54 | self.date = [format dateFromString:[dictionary objectForKey:@"date"]];
55 | self.available = [dictionary objectForKey:@"available"];
56 | self.price = [dictionary objectForKey:@"price"];
57 | }
58 | return self;
59 | }
60 |
61 | @end
--------------------------------------------------------------------------------
/ZBJCalendar/MutipleSelection/ZBJMutipleSelectionSectionHeaderView.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJMutipleSelectionSectionHeaderView.m
3 | // ZBJCalendar
4 | //
5 | // Created by wanggang on 7/4/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJMutipleSelectionSectionHeaderView.h"
10 | #import "ZBJCalendar.h"
11 |
12 | @interface ZBJMutipleSelectionSectionHeaderView ()
13 |
14 | @property (nonatomic, strong) UILabel *monthLabel;
15 | @property (nonatomic, assign) NSInteger weekday;
16 |
17 | @end
18 |
19 | @implementation ZBJMutipleSelectionSectionHeaderView
20 |
21 | - (id)initWithFrame:(CGRect)frame {
22 | self = [super initWithFrame:frame];
23 | if (self) {
24 | [self addSubview:self.monthLabel];
25 |
26 | UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapMonthView:)];
27 | self.userInteractionEnabled = YES;
28 | [self addGestureRecognizer:gesture];
29 | }
30 | return self;
31 | }
32 |
33 | - (void)layoutSubviews {
34 | [super layoutSubviews];
35 | self.monthLabel.frame = CGRectMake(10, (CGRectGetHeight(self.frame) - 20) / 2, CGRectGetWidth(self.monthLabel.frame), 20);
36 | }
37 |
38 | #pragma mark - events
39 | - (void)tapMonthView:(id)sender {
40 | if (self.tapHandler) {
41 | self.tapHandler(self.firstDateOfMonth);
42 | }
43 | }
44 |
45 | #pragma mark - setters
46 | - (void)setFirstDateOfMonth:(NSDate *)firstDateOfMonth {
47 | _firstDateOfMonth = firstDateOfMonth;
48 | NSCalendar *calendar = [NSDate gregorianCalendar];
49 | NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitWeekday fromDate:firstDateOfMonth];
50 | self.monthLabel.text = [NSString stringWithFormat:@"%ld月%ld", components.month, components.year];
51 | [self.monthLabel sizeToFit];
52 | [self layoutSubviews];
53 | }
54 |
55 |
56 | #pragma mark - getters
57 | - (UILabel *)monthLabel {
58 | if (!_monthLabel) {
59 | _monthLabel = [[UILabel alloc] init];
60 | _monthLabel.font = [UIFont systemFontOfSize:18];
61 | _monthLabel.textColor = [UIColor grayColor];
62 | }
63 | return _monthLabel;
64 | }
65 |
66 | @end
67 |
--------------------------------------------------------------------------------
/ZBJCalendar/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 15/12/8.
6 | // Copyright © 2015年 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | @interface AppDelegate ()
12 |
13 | @end
14 |
15 | @implementation AppDelegate
16 |
17 |
18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
19 | // Override point for customization after application launch.
20 |
21 | // [[UINavigationBar appearance] setBarTintColor:[UIColor colorWithRed:9.0/255.0 green:9.0/255.0 blue:26.0/255.0 alpha:0.8]];
22 | // [[UINavigationBar appearance] setTintColor:[UIColor whiteColor]];
23 | // [[UINavigationBar appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]}];
24 | return YES;
25 | }
26 |
27 | - (void)applicationWillResignActive:(UIApplication *)application {
28 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
29 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
30 | }
31 |
32 | - (void)applicationDidEnterBackground:(UIApplication *)application {
33 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
34 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
35 | }
36 |
37 | - (void)applicationWillEnterForeground:(UIApplication *)application {
38 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
39 | }
40 |
41 | - (void)applicationDidBecomeActive:(UIApplication *)application {
42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
43 | }
44 |
45 | - (void)applicationWillTerminate:(UIApplication *)application {
46 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
47 | }
48 |
49 | @end
50 |
--------------------------------------------------------------------------------
/ZBJCalendar/ZBJCalendar/NSDate+IndexPath.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSDate+IndexPath.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 2/29/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "NSDate+IndexPath.h"
10 | #import "NSDate+ZBJAddition.h"
11 | #import
12 |
13 | @implementation NSDate (IndexPath)
14 |
15 | + (NSDate *)dateForFirstDayInSection:(NSInteger)section firstDate:(NSDate *)firstDate {
16 | NSCalendar *calendar = [NSDate gregorianCalendar];
17 |
18 | NSDateComponents *dateComponents = [NSDateComponents new];
19 | dateComponents.month = section;
20 | return [calendar dateByAddingComponents:dateComponents toDate:[firstDate firstDateOfMonth] options:0];
21 | }
22 |
23 | + (NSDate *)dateAtIndexPath:(NSIndexPath *)indexPath firstDate:(NSDate *)firstDate {
24 | NSDate *firstDay = [NSDate dateForFirstDayInSection:indexPath.section firstDate:firstDate];
25 | NSInteger weekDay = [firstDay weekday];
26 | NSDate *dateToReturn = nil;
27 |
28 | if (indexPath.row < (weekDay - 1) || indexPath.row > weekDay - 1 + [NSDate numberOfDaysInMonth:firstDay] - 1) {
29 | dateToReturn = nil;
30 | } else {
31 | NSCalendar *calendar = [NSDate gregorianCalendar];
32 |
33 | NSDateComponents *components = [calendar components:NSCalendarUnitMonth | NSCalendarUnitDay fromDate:firstDay];
34 | [components setDay:indexPath.row - (weekDay - 1)];
35 | [components setMonth:indexPath.section];
36 | dateToReturn = [calendar dateByAddingComponents:components toDate:[firstDate firstDateOfMonth] options:0];
37 | }
38 | return dateToReturn;
39 | }
40 |
41 | + (NSIndexPath *)indexPathAtDate:(NSDate *)date firstDate:(NSDate *)firstDate {
42 | NSCalendar *calendar = [NSDate gregorianCalendar];
43 | NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];
44 |
45 | NSDateComponents *firstDateComponents = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth fromDate:firstDate];
46 |
47 | NSDate *firstDateOfMonth = [date firstDateOfMonth];
48 | NSDateComponents *firstDateOfMonthComponents = [calendar components:NSCalendarUnitWeekday fromDate:firstDateOfMonth];
49 |
50 | NSInteger section = (components.year - firstDateComponents.year) * 12 + components.month - firstDateComponents.month;
51 | NSInteger index = firstDateOfMonthComponents.weekday + components.day - 2;
52 |
53 | return [NSIndexPath indexPathForItem:index inSection:section];
54 | }
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/ZBJCalendar/CommonViews/ZBJCalendarSectionHeader.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendarSectionHeader.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 2/24/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJCalendarSectionHeader.h"
10 |
11 | @interface ZBJCalendarSectionHeader()
12 |
13 | @property (nonatomic, strong) UILabel *yearLabel;
14 | @property (nonatomic, strong) UILabel *monthLabel;
15 | @property (nonatomic, strong) UIView *bottomLine;
16 |
17 | @end
18 |
19 | @implementation ZBJCalendarSectionHeader
20 |
21 | - (id)initWithFrame:(CGRect)frame {
22 | self = [super initWithFrame:frame];
23 | if (self) {
24 | [self addSubview:self.yearLabel];
25 | [self addSubview:self.monthLabel];
26 | [self addSubview:self.bottomLine];
27 | }
28 | return self;
29 | }
30 |
31 | - (void)layoutSubviews {
32 | [super layoutSubviews];
33 | self.monthLabel.frame = CGRectMake(13, 25, CGRectGetWidth(self.monthLabel.frame), 20);
34 | self.yearLabel.frame = CGRectMake(CGRectGetMaxX(self.monthLabel.frame) + 3, CGRectGetMaxY(self.monthLabel.frame) - 2 - 9, 100, 9);
35 | self.bottomLine.frame = CGRectMake(CGRectGetMinX(self.monthLabel.frame), CGRectGetMaxY(self.monthLabel.frame) + 11, 30, 2);
36 | }
37 |
38 | #pragma mark - setters
39 | - (void)setYear:(NSInteger)year {
40 | self.yearLabel.text = [NSString stringWithFormat:@"%ld", year];
41 | }
42 |
43 | - (void)setMonth:(NSInteger)month {
44 | self.monthLabel.text = [NSString stringWithFormat:@"%ld月", month];
45 | [self.monthLabel sizeToFit];
46 | }
47 |
48 |
49 | #pragma mark - getters
50 | - (UILabel *)yearLabel {
51 | if (!_yearLabel) {
52 | _yearLabel = [[UILabel alloc] init];
53 | _yearLabel.font = [UIFont systemFontOfSize:10];
54 | _yearLabel.textColor = [UIColor darkTextColor];
55 | _yearLabel.textAlignment = NSTextAlignmentLeft;
56 | }
57 | return _yearLabel;
58 | }
59 |
60 | - (UILabel *)monthLabel {
61 | if (!_monthLabel) {
62 | _monthLabel = [[UILabel alloc] init];
63 | _monthLabel.font = [UIFont systemFontOfSize:22];
64 | _monthLabel.textColor = [UIColor darkTextColor];
65 | }
66 | return _monthLabel;
67 | }
68 |
69 | - (UIView *)bottomLine {
70 | if (!_bottomLine) {
71 | _bottomLine = [[UIView alloc] init];
72 | _bottomLine.backgroundColor = [UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:233.0/255.0 alpha:1.0];
73 | _bottomLine.layer.cornerRadius = 1.0;
74 | _bottomLine.clipsToBounds = YES;
75 | }
76 |
77 | return _bottomLine;
78 | }
79 |
80 |
81 | @end
82 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | ## ZBJCalendar [](https://raw.githubusercontent.com/wanggang316/ZBJCalendar/master/LICENSE) [](https://cocoapods.org/?q=zbjcALENDAR) [](https://www.codewake.com/p/zbjcalendar)
3 |
4 | > ZBJCalendar is a simple way to create a calendar view. The concept of ZBJCalendar is UICollectionView or UITableView.
5 |
6 | > As we know, UICollectionView and UITableView set up the corresponding relations between cell and indexPath. Differently, ZBJCalendar set up the corresponding relations between cell and date, this is important to understand ZBJCalendar.
7 |
8 | ## Requirements
9 |
10 | * iOS7 or later
11 |
12 | ## Installation with CocoaPods
13 | `pod 'ZBJCalendar'`
14 |
15 | ## Installation with Carthage
16 | `github "wanggang316/ZBJCalendar"`
17 |
18 | ## Architecture
19 |
20 | ### ZBJCalendarView
21 |
22 | This is the main class of ZBJCalendar, an instance of this is a calendar view.
23 |
24 | You can find some familiar properties and new properties:
25 |
26 | * `dataSource` is `` protocol property which used to custom cells or headers
27 | * `delegate` is `` protocol property which used to handle the display and behaviour of the day cells.
28 | * `firstDate` and `lastDate` use to set the calendar's start date and end date.
29 | * `selectionMode` is a enum of `ZBJSelectionMode` which express the single selection or mutable selection or can't be select.
30 |
31 |
32 | Also, it contains some familiar methods like:
33 | * `- (void)registerCellClass:(id)clazz withReuseIdentifier:(NSString *)identifier;`
34 | * `- (void)reloadData;`
35 | * `- (id)cellAtDate:(NSDate *)date;`
36 | * `- (void)reloadCellsAtDates:(NSSet *)dates;`
37 |
38 | ####
39 |
40 | A protocol to custom the cell data model object. It supplies the cell and supplementary view's information about appearance and data.
41 |
42 | * `- (void)calendarView:(ZBJCalendarView *)calendarView configureCell:(id)cell forDate:(NSDate *)date;`
43 | * `- (void)calendarView:(ZBJCalendarView *)calendarView configureSectionHeaderView:(id)headerView firstDateOfMonth:(NSDate *)firstDateOfMonth;`
44 | * `- (void)calendarView:(ZBJCalendarView *)calendarView configureSectionFooterView:(id)headerView lastDateOfMonth:(NSDate *)lastDateOfMonth;`
45 | * `- (void)calendarView:(ZBJCalendarView *)calendarView configureWeekDayLabel:(UILabel *)dayLabel atWeekDay:(NSInteger)weekDay;`
46 |
47 | ####
48 |
49 | A protocol use to handle the display and behaviour of ZBJCalendar.
50 |
51 | * `- (BOOL)calendarView:(ZBJCalendarView *)calendarView shouldSelectDate:(NSDate *)date;`
52 | * `- (void)calendarView:(ZBJCalendarView *)calendarView didSelectDate:(NSDate *)date ofCell:(id)cell;`
53 |
54 | ### ZBJCalendarWeekView
55 |
56 | ZBJCalendar provider a week view by this class, you can change it's style by implement
57 |
58 | ### NSDate+ZBJAddition
59 |
60 | This category provide utility methods for `NSDate`.
61 |
62 | ### NSDate+IndexPath
63 |
64 | This category provide methods used to corresponding relations between indexpath and date.
65 |
66 |
67 | ## Examples
68 |
69 | 
70 |
71 | ## License
72 |
73 | ZBJCalendar is released under the MIT license.
74 |
--------------------------------------------------------------------------------
/ZBJCalendar/ZBJCalendar/ZBJCalendarWeekView.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendarWeekView.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 16/2/25.
6 | // Copyright © 2016年 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJCalendarWeekView.h"
10 | #import "NSDate+ZBJAddition.h"
11 |
12 | @interface ZBJCalendarWeekView ()
13 | @property (nonatomic, strong) NSMutableArray *adjustedSymbols;
14 | @end
15 |
16 | @implementation ZBJCalendarWeekView
17 |
18 | - (instancetype)initWithFrame:(CGRect)frame
19 | {
20 | self = [super initWithFrame:frame];
21 | if (self) {
22 |
23 | self.backgroundColor = [UIColor whiteColor];
24 | NSCalendar *calendar = [NSDate gregorianCalendar];
25 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
26 | dateFormatter.calendar = calendar;
27 | NSArray *weekdaySymbols = nil;
28 |
29 | weekdaySymbols = [dateFormatter veryShortWeekdaySymbols];
30 |
31 | NSMutableArray *adjustedSymbols = [NSMutableArray arrayWithArray:weekdaySymbols];
32 | for (NSInteger index = 0; index < (1 - calendar.firstWeekday + weekdaySymbols.count + 1); index++) {
33 | NSString *lastObject = [adjustedSymbols lastObject];
34 | [adjustedSymbols removeLastObject];
35 | [adjustedSymbols insertObject:lastObject atIndex:0];
36 | }
37 |
38 | self.adjustedSymbols = adjustedSymbols;
39 |
40 | for (int i = 0 ; i < self.adjustedSymbols.count; i++) {
41 | CGFloat w = CGRectGetWidth(self.frame)/7;
42 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(w * i, 0, w, CGRectGetHeight(self.frame))];
43 | label.tag = 10901 + i;
44 | label.textColor = [UIColor darkTextColor];
45 | label.font = [UIFont systemFontOfSize:15];
46 | label.text = [self.adjustedSymbols[i] uppercaseString];
47 | label.textAlignment = NSTextAlignmentCenter;
48 | [self addSubview:label];
49 |
50 | }
51 |
52 | // bottom line is default style, you
53 | if (!self.bottomLine) {
54 | self.bottomLine = [CALayer layer];
55 | self.bottomLine.frame = CGRectMake(0, CGRectGetHeight(self.frame) - 0.5, CGRectGetWidth(self.frame), 0.5);
56 | self.bottomLine.backgroundColor = [UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:233.0/255.0 alpha:1.0].CGColor;
57 | [self.layer addSublayer:self.bottomLine];
58 | }
59 | }
60 | return self;
61 | }
62 |
63 | - (void)layoutSubviews {
64 | [super layoutSubviews];
65 | for (int i = 0; i < 7; i++) {
66 | UILabel *label = [self viewWithTag:10901 + i];
67 | CGFloat width = (self.frame.size.width - _contentInsets.left - _contentInsets.right) / 7;
68 | label.frame = CGRectMake(_contentInsets.left + i * width, 0, width, CGRectGetHeight(self.frame));
69 | }
70 | self.bottomLine.frame = CGRectMake(0, CGRectGetHeight(self.frame) - 0.5, CGRectGetWidth(self.frame), 0.5);
71 | }
72 |
73 | - (void)reloadWeekView {
74 | for (int i = 0; i < self.adjustedSymbols.count; i++) {
75 | UILabel *label = [self viewWithTag:10901 + i];
76 | if (label && _delegate && [_delegate respondsToSelector:@selector(calendarWeekView:configureWeekDayLabel:atWeekDay:)]) {
77 | [_delegate calendarWeekView:self configureWeekDayLabel:label atWeekDay:i];
78 | }
79 | }
80 | }
81 |
82 | - (void)setDelegate:(id)delegate {
83 | _delegate = delegate;
84 | [self reloadWeekView];
85 | }
86 |
87 | - (void)setContentInsets:(UIEdgeInsets)contentInsets {
88 | _contentInsets = contentInsets;
89 | [self layoutSubviews];
90 | }
91 |
92 | @end
93 |
--------------------------------------------------------------------------------
/ZBJCalendar/SingleSelection/ZBJSingleSelectionCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJSingleSelectionCell.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 5/26/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJSingleSelectionCell.h"
10 | #import "NSDate+ZBJAddition.h"
11 |
12 | @interface ZBJSingleSelectionCell()
13 |
14 | @property (nonatomic, strong) UILabel *dateLabel;
15 | @property (nonatomic, strong) NSCalendar *calendar;
16 |
17 | @property (nonatomic, strong) CALayer *topLine;
18 | @end
19 | @implementation ZBJSingleSelectionCell
20 |
21 | - (instancetype)initWithFrame:(CGRect)frame {
22 | if (self = [super initWithFrame:frame]) {
23 | [self.contentView addSubview:self.dateLabel];
24 | [self.contentView.layer addSublayer:self.topLine];
25 | self.calendar = [NSDate gregorianCalendar];
26 | }
27 | return self;
28 | }
29 |
30 | - (void)layoutSubviews {
31 | [super layoutSubviews];
32 | self.topLine.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), 0.5);
33 | self.dateLabel.center = CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) / 2 - 13);
34 | }
35 |
36 |
37 | - (void)setDate:(NSDate *)date {
38 | _date = date;
39 | if (_date) {
40 | self.dateLabel.text = [NSString stringWithFormat:@"%ld", [self.calendar component:NSCalendarUnitDay fromDate:_date]];
41 | } else {
42 | self.dateLabel.text = nil;
43 | }
44 | }
45 |
46 | - (void)setCellState:(ZBJCalendarCellState)cellState {
47 | _cellState = cellState;
48 | switch (_cellState) {
49 | case ZBJCalendarCellStateEmpty: {
50 | self.dateLabel.text = nil;
51 | self.dateLabel.textColor = [UIColor whiteColor];
52 | self.dateLabel.backgroundColor = [UIColor whiteColor];
53 | self.dateLabel.layer.cornerRadius = 0;
54 |
55 | self.topLine.hidden = YES;
56 | break;
57 | }
58 | case ZBJCalendarCellStateNormal: {
59 | self.dateLabel.backgroundColor = [UIColor whiteColor];
60 | self.dateLabel.layer.cornerRadius = 0;
61 |
62 | if ([self.date isWeekend]) {
63 | self.dateLabel.textColor = [UIColor lightGrayColor];
64 | } else if ([self.date isToday]) {
65 | self.dateLabel.textColor = [UIColor colorWithRed:255.0/255.0 green:60.0/255.0 blue:57.0/255.0 alpha:1.0];
66 | } else {
67 | self.dateLabel.textColor = [UIColor darkTextColor];
68 | }
69 |
70 | self.topLine.hidden = NO;
71 | break;
72 | }
73 | case ZBJCalendarCellStateSelected: {
74 | self.dateLabel.textColor = [UIColor whiteColor];
75 | self.dateLabel.layer.cornerRadius = 17;
76 |
77 | if ([self.date isToday]) {
78 | self.dateLabel.backgroundColor = [UIColor colorWithRed:255.0/255.0 green:60.0/255.0 blue:57.0/255.0 alpha:1.0];
79 | } else {
80 | self.dateLabel.backgroundColor = [UIColor darkTextColor];
81 | }
82 |
83 | self.topLine.hidden = NO;
84 | break;
85 | }
86 | default:
87 | break;
88 | }
89 |
90 | [self layoutSubviews];
91 | }
92 |
93 | #pragma mark - getters
94 | - (UILabel *)dateLabel {
95 | if (!_dateLabel) {
96 | _dateLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 34, 34)];
97 | _dateLabel.textAlignment = NSTextAlignmentCenter;
98 | _dateLabel.font = [UIFont systemFontOfSize:17];
99 | _dateLabel.textColor = [UIColor darkTextColor];
100 | _dateLabel.clipsToBounds = YES;
101 | }
102 | return _dateLabel;
103 | }
104 |
105 | - (CALayer *)topLine {
106 | if (!_topLine) {
107 | _topLine = [CALayer layer];
108 | _topLine.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), 0.5);
109 | _topLine.backgroundColor = [UIColor colorWithRed:204.0/255.0 green:204.0/255.0 blue:204.0/255.0 alpha:1.0].CGColor;
110 | }
111 | return _topLine;
112 | }
113 | @end
114 |
--------------------------------------------------------------------------------
/ZBJCalendar/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
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 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/ZBJCalendar/Show/ZBJCalendarShowCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendarShowCell.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 3/15/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJCalendarShowCell.h"
10 | #import "NSDate+ZBJAddition.h"
11 |
12 | @interface ZBJCalendarShowCell()
13 |
14 | @property (nonatomic, strong) UILabel *dateLabel;
15 | @property (nonatomic, strong) UILabel *priceLabel;
16 | @property (nonatomic, strong) UIImageView *backgroundImageView;
17 |
18 | @property (nonatomic, strong) NSCalendar *calendar;
19 |
20 | @end
21 |
22 | @implementation ZBJCalendarShowCell
23 |
24 | - (instancetype)initWithFrame:(CGRect)frame {
25 | if (self = [super initWithFrame:frame]) {
26 |
27 | [self.contentView addSubview:self.dateLabel];
28 | [self.contentView addSubview:self.priceLabel];
29 | self.calendar = [NSDate gregorianCalendar];
30 | }
31 | return self;
32 | }
33 |
34 | - (void)layoutSubviews {
35 | [super layoutSubviews];
36 | self.dateLabel.frame = CGRectMake(0, self.contentView.center.y - CGRectGetHeight(self.dateLabel.frame) - 1, CGRectGetWidth(self.bounds), 15);
37 | self.priceLabel.frame = CGRectMake(0, self.contentView.center.y + 5, CGRectGetWidth(self.frame), 9);
38 | self.backgroundImageView.frame = self.contentView.bounds;
39 | }
40 |
41 |
42 | #pragma mark - setters
43 | - (void)setDate:(NSDate *)date {
44 | _date = date;
45 | if (_date) {
46 | self.dateLabel.text = [NSString stringWithFormat:@"%ld", [self.calendar component:NSCalendarUnitDay fromDate:_date]];
47 | } else {
48 | self.dateLabel.text = nil;
49 | }
50 | }
51 |
52 | - (void)setPrice:(NSNumber *)price {
53 | _price = price;
54 | if (_price) {
55 | self.priceLabel.text = [NSString stringWithFormat:@"¥%@", _price];
56 | } else {
57 | self.priceLabel.text = nil;
58 | }
59 | }
60 |
61 | - (void)setCellState:(ZBJCalendarCellState)cellState {
62 | _cellState = cellState;
63 | switch (_cellState) {
64 | case ZBJCalendarCellStateDisabled: {
65 | self.backgroundView = nil;
66 | self.dateLabel.textColor = [UIColor colorWithRed:192.0/255.0 green:192.0/255.0 blue:200.0/255.0 alpha:1.0];
67 | break;
68 | }
69 | case ZBJCalendarCellStateAvaible: {
70 | self.backgroundView = nil;
71 | self.dateLabel.textColor = [UIColor colorWithRed:9.0/255.0 green:9.0/255.0 blue:26.0/255.0 alpha:1.0];
72 | break;
73 | }
74 | case ZBJCalendarCellStateUnavaible: {
75 | self.backgroundView = self.backgroundImageView;
76 |
77 | self.dateLabel.textColor = [UIColor colorWithRed:192.0/255.0 green:192.0/255.0 blue:200.0/255.0 alpha:1.0];
78 | self.priceLabel.textColor = [UIColor colorWithRed:192.0/255.0 green:192.0/255.0 blue:200.0/255.0 alpha:1.0];
79 |
80 | self.priceLabel.text = @"已租";
81 | break;
82 | }
83 |
84 | case ZBJCalendarCellStateEmpty: {
85 | self.dateLabel.text = nil;
86 | self.priceLabel.text = nil;
87 | self.backgroundView = nil;
88 | break;
89 | }
90 | default: {
91 | break;
92 | }
93 |
94 | }
95 | [self layoutSubviews];
96 | }
97 |
98 | #pragma mark - getters
99 | - (UILabel *)dateLabel {
100 | if (!_dateLabel) {
101 | _dateLabel = [[UILabel alloc] initWithFrame:self.bounds];
102 | _dateLabel.textAlignment = NSTextAlignmentCenter;
103 | _dateLabel.font = [UIFont systemFontOfSize:15];
104 | _dateLabel.textColor = [UIColor darkTextColor];
105 | }
106 | return _dateLabel;
107 | }
108 |
109 | - (UILabel *)priceLabel {
110 | if (!_priceLabel) {
111 | _priceLabel = [[UILabel alloc] init];
112 | _priceLabel.font = [UIFont systemFontOfSize:9];
113 | _priceLabel.textAlignment = NSTextAlignmentCenter;
114 | _priceLabel.textColor = [UIColor colorWithRed:157.0/255.0 green:157.0/255.0 blue:163.0/255.0 alpha:1.0];
115 | }
116 | return _priceLabel;
117 | }
118 |
119 | - (UIImageView *)backgroundImageView {
120 | if (!_backgroundImageView) {
121 | _backgroundImageView = [[UIImageView alloc] initWithFrame:self.contentView.bounds];
122 | _backgroundImageView.image = [UIImage imageNamed:@"unav"];
123 | _backgroundImageView.contentMode = UIViewContentModeScaleAspectFill;
124 | }
125 | return _backgroundImageView;
126 | }
127 |
128 |
129 | @end
130 |
--------------------------------------------------------------------------------
/ZBJCalendar/MutipleSelection/ZBJSimpleMutipleSelectionCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJMutipleSelectionCell.m
3 | // ZBJCalendar
4 | //
5 | // Created by wanggang on 7/4/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJSimpleMutipleSelectionCell.h"
10 | #import "NSDate+ZBJAddition.h"
11 |
12 | @interface ZBJSimpleMutipleSelectionCell ()
13 |
14 | @property (nonatomic, strong) UILabel *dateLabel;
15 | @property (nonatomic, strong) NSCalendar *calendar;
16 |
17 | @property (nonatomic, strong) UIImageView *backView;
18 |
19 | @end
20 |
21 | @implementation ZBJSimpleMutipleSelectionCell
22 |
23 |
24 | - (instancetype)initWithFrame:(CGRect)frame {
25 | if (self = [super initWithFrame:frame]) {
26 | [self.contentView addSubview:self.backView];
27 | [self.contentView addSubview:self.dateLabel];
28 | self.calendar = [NSDate gregorianCalendar];
29 | }
30 | return self;
31 | }
32 |
33 | - (void)layoutSubviews {
34 | [super layoutSubviews];
35 | CGFloat min = MIN(CGRectGetHeight(self.frame), CGRectGetWidth(self.frame));
36 | self.dateLabel.frame = CGRectMake(0, 0, min, min);
37 | self.dateLabel.center = CGPointMake(CGRectGetWidth(self.frame) / 2, CGRectGetHeight(self.frame) / 2);
38 | self.backView.frame = self.bounds;
39 | }
40 |
41 |
42 | - (void)setDate:(NSDate *)date {
43 | _date = date;
44 | if (_date) {
45 | self.dateLabel.text = [NSString stringWithFormat:@"%ld", [self.calendar component:NSCalendarUnitDay fromDate:_date]];
46 | } else {
47 | self.dateLabel.text = nil;
48 | }
49 | }
50 |
51 | - (void)setCellState:(ZBJCalendarCellState)cellState {
52 |
53 | _cellState = cellState;
54 |
55 | switch (_cellState) {
56 | case ZBJCalendarCellStateEmpty: {
57 | self.backView.image = nil;
58 | self.dateLabel.text = nil;
59 | self.dateLabel.textColor = [UIColor whiteColor];
60 | break;
61 | }
62 | case ZBJCalendarCellStateDisabled: {
63 | self.backView.image = nil;
64 | self.dateLabel.textColor = [UIColor lightGrayColor];
65 | break;
66 | }
67 | case ZBJCalendarCellStateNormal: {
68 | self.backView.image = nil;
69 | if ([self.date isToday]) {
70 | self.dateLabel.textColor = [UIColor colorWithRed:255.0/255.0 green:60.0/255.0 blue:57.0/255.0 alpha:1.0];
71 | } else {
72 | self.dateLabel.textColor = [UIColor darkTextColor];
73 | }
74 | break;
75 | }
76 | case ZBJCalendarCellStateSelected: {
77 | self.dateLabel.textColor = [UIColor whiteColor];
78 | self.backView.image = [UIImage imageNamed:@"cal_selected"];
79 | break;
80 | }
81 | case ZBJCalendarCellStateSelectedLeft: {
82 |
83 | self.dateLabel.textColor = [UIColor whiteColor];
84 | self.backView.image = [UIImage imageNamed:@"cal_selected_left"];
85 |
86 | break;
87 | }
88 | case ZBJCalendarCellStateSelectedRight: {
89 | self.dateLabel.textColor = [UIColor whiteColor];
90 | self.backView.image = [UIImage imageNamed:@"cal_selected_right"];
91 | break;
92 | }
93 | case ZBJCalendarCellStateSelectedMiddle: {
94 | self.dateLabel.textColor = [UIColor whiteColor];
95 | self.backView.image = [UIImage imageNamed:@"cal_selected_middle"];
96 | break;
97 | }
98 | default:
99 | break;
100 | }
101 |
102 | [self layoutSubviews];
103 | }
104 |
105 | #pragma mark - getters
106 | - (UILabel *)dateLabel {
107 | if (!_dateLabel) {
108 | _dateLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 34, 34)];
109 | _dateLabel.textAlignment = NSTextAlignmentCenter;
110 | _dateLabel.font = [UIFont systemFontOfSize:17];
111 | _dateLabel.textColor = [UIColor darkTextColor];
112 | _dateLabel.clipsToBounds = YES;
113 | }
114 | return _dateLabel;
115 | }
116 |
117 | - (UIImageView *)backView {
118 | if (!_backView) {
119 | _backView = [[UIImageView alloc] init];
120 | _backView.contentMode = UIViewContentModeScaleAspectFill;
121 | }
122 | return _backView;
123 | }
124 |
125 | //- (CALayer *)topLine {
126 | // if (!_topLine) {
127 | // _topLine = [CALayer layer];
128 | // _topLine.frame = CGRectMake(0, 0, CGRectGetWidth(self.frame), 0.5);
129 | // _topLine.backgroundColor = [UIColor colorWithRed:204.0/255.0 green:204.0/255.0 blue:204.0/255.0 alpha:1.0].CGColor;
130 | // }
131 | // return _topLine;
132 | //}
133 |
134 | @end
135 |
--------------------------------------------------------------------------------
/ZBJCalendar/SingleSelection/ZBJSingleSelectionController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJSingleSelectionController.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 5/26/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJSingleSelectionController.h"
10 | #import "ZBJCalendar.h"
11 | #import "ZBJSingleSelectionCell.h"
12 | #import "ZBJSingleSelectionHeaderView.h"
13 | #import "UINavigationBar+ZBJAddition.h"
14 |
15 | @interface ZBJSingleSelectionController ()
16 |
17 | @property (nonatomic, strong) ZBJCalendarView *calendarView;
18 | @property (nonatomic, strong) NSDate *selectedDate;
19 |
20 | @end
21 | @implementation ZBJSingleSelectionController
22 |
23 | - (void)viewWillAppear:(BOOL)animated {
24 | [super viewWillAppear:animated];
25 | [self.navigationController.navigationBar hidenHairLine:YES];
26 | }
27 |
28 | -(void)viewWillDisappear:(BOOL)animated {
29 | [super viewWillDisappear:animated];
30 | [self.navigationController.navigationBar hidenHairLine:NO];
31 | }
32 |
33 | - (void)viewDidLoad {
34 | [super viewDidLoad];
35 | self.view.backgroundColor = [UIColor whiteColor];
36 |
37 | // 获取当前日期
38 | NSDate *today = [NSDate today];
39 |
40 | // NSDate *today = [NSDate date];
41 | // 获取6个月后的最后一天
42 | NSCalendar *calendar = [NSDate gregorianCalendar];
43 | NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:today];
44 |
45 | NSDate *firstDate = [calendar dateFromComponents:components];
46 |
47 | components.month = components.month + 6 + 1;
48 | components.day = 0;
49 | NSDate *lastDate = [calendar dateFromComponents:components];
50 |
51 | self.calendarView.firstDate = firstDate;
52 | self.calendarView.lastDate = lastDate;
53 |
54 | [self.view addSubview:self.calendarView];
55 |
56 | self.selectedDate = firstDate;
57 | }
58 |
59 | - (void)didReceiveMemoryWarning {
60 | [super didReceiveMemoryWarning];
61 | }
62 |
63 |
64 | #pragma mark - ZBJCalendarDataSource
65 | - (void)calendarView:(ZBJCalendarView *)calendarView configureCell:(ZBJSingleSelectionCell *)cell forDate:(NSDate *)date {
66 |
67 | cell.date = date;
68 | if (date) {
69 | if ([date isEqualToDate:self.selectedDate]) {
70 | cell.cellState = ZBJCalendarCellStateSelected;
71 | } else {
72 | cell.cellState = ZBJCalendarCellStateNormal;
73 | }
74 | } else {
75 | cell.cellState = ZBJCalendarCellStateEmpty;
76 | }
77 | }
78 |
79 | - (void)calendarView:(ZBJCalendarView *)calendarView configureSectionHeaderView:(ZBJSingleSelectionHeaderView *)headerView firstDateOfMonth:(NSDate *)firstDateOfMonth {
80 | headerView.firstDateOfMonth = firstDateOfMonth;
81 | }
82 |
83 | - (void)calendarView:(ZBJCalendarView *)calendarView configureWeekDayLabel:(UILabel *)dayLabel atWeekDay:(NSInteger)weekDay {
84 | dayLabel.font = [UIFont systemFontOfSize:13];
85 | if (weekDay == 0 || weekDay == 6) {
86 | dayLabel.textColor = [UIColor lightGrayColor];
87 | }
88 | }
89 |
90 | #pragma mark - ZBJCalendarDelegate
91 | - (void)calendarView:(ZBJCalendarView *)calendarView didSelectDate:(NSDate *)date ofCell:(ZBJSingleSelectionCell *)cell {
92 |
93 | NSDate *oldDate = [self.selectedDate copy];
94 | self.selectedDate = date;
95 |
96 | [calendarView reloadItemsAtDates:[NSMutableSet setWithObjects:oldDate, self.selectedDate, nil]];
97 | // if (date) {
98 | NSLog(@"selected date is : %@", self.selectedDate);
99 | // cell.cellState = ZBJCalendarCellStateSelected;
100 | // }
101 |
102 | }
103 |
104 |
105 | #pragma mark -
106 | - (ZBJCalendarView *)calendarView {
107 | if (!_calendarView) {
108 | _calendarView = [[ZBJCalendarView alloc] initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame) - 64)];
109 | [_calendarView registerCellClass:[ZBJSingleSelectionCell class] withReuseIdentifier:@"singleCell"];
110 | [_calendarView registerSectionHeader:[ZBJSingleSelectionHeaderView class] withReuseIdentifier:@"singleSectionHeader"];
111 | _calendarView.selectionMode = ZBJSelectionModeSingle;
112 | _calendarView.dataSource = self;
113 | _calendarView.delegate = self;
114 | _calendarView.backgroundColor = [UIColor whiteColor];
115 | _calendarView.contentInsets = UIEdgeInsetsMake(0, 14, 0, 14);
116 | _calendarView.cellScale = 140.0 / 100.0;
117 | _calendarView.sectionHeaderHeight = 27;
118 | _calendarView.weekViewHeight = 20;
119 | _calendarView.weekView.backgroundColor = [UIColor colorWithRed:249.0f/255.0f green:249.0f/255.0f blue:249.0f/255.0f alpha:1.0];
120 | }
121 | return _calendarView;
122 | }
123 | @end
124 |
--------------------------------------------------------------------------------
/ZBJCalendar.xcodeproj/xcshareddata/xcschemes/ZBJCalendar.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
57 |
63 |
64 |
65 |
66 |
67 |
73 |
74 |
75 |
76 |
77 |
78 |
88 |
90 |
96 |
97 |
98 |
99 |
100 |
101 |
107 |
109 |
115 |
116 |
117 |
118 |
120 |
121 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/ZBJCalendar/Show/ZBJCalendarShowView.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendarShowView.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 3/15/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJCalendarShowView.h"
10 | #import "ZBJCalendar.h"
11 | #import "ZBJCalendarShowCell.h"
12 | #import "ZBJCalendarSectionHeader.h"
13 | #import "ZBJCalendarSectionFooter.h"
14 |
15 | @interface ZBJCalendarShowView ()
16 |
17 | @property (nonatomic, strong) UIView *backView;
18 | @property (nonatomic, strong) UILabel *titleLable;
19 | @property (nonatomic, strong) ZBJCalendarView *calendarView;
20 | @property (nonatomic, strong) UIButton *cancelButton;
21 |
22 | @end
23 |
24 | @implementation ZBJCalendarShowView
25 |
26 | - (instancetype)initWithFrame:(CGRect)frame calendarDates:(ZBJCalendarDates *)calendarDates {
27 | if (self = [super initWithFrame:frame]) {
28 | self.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.8];
29 | [self addSubview:self.backView];
30 | self.calendarDates = calendarDates;
31 | }
32 | return self;
33 | }
34 |
35 | - (void)cancel:(id)sender {
36 | [UIView animateWithDuration:0.2 animations:^{
37 | self.alpha = 0.0;
38 | } completion:^(BOOL finished) {
39 | [self removeFromSuperview];
40 | }];
41 | }
42 |
43 | - (void)layoutSubviews {
44 | [super layoutSubviews];
45 | self.cancelButton.center = CGPointMake(self.backView.frame.size.width/2, CGRectGetHeight(self.backView.frame) - 15 - 13);
46 | }
47 |
48 |
49 |
50 | #pragma mark - private methods
51 | - (ZBJCalendarDate *)offerDateWithDate:(NSDate *)date {
52 | for (ZBJCalendarDate *day in self.calendarDates.dates) {
53 | if ([day.date isEqualToDate:date]) {
54 | return day;
55 | break;
56 | }
57 | }
58 | return nil;
59 | }
60 |
61 | #pragma mark - ZBJCalendarDataSource
62 | - (void)calendarView:(ZBJCalendarView *)calendarView configureCell:(ZBJCalendarShowCell *)cell forDate:(NSDate *)date {
63 |
64 | cell.date = date;
65 |
66 | ZBJCalendarCellState cellState = -1;
67 | NSNumber *price = nil;
68 |
69 | if (date) {
70 | // 如果小于起始日期或大于结束日期,那么disabled
71 | if ([[date dateByAddingTimeInterval:86400.0 - 1] compare:calendarView.firstDate] == NSOrderedAscending ||
72 | [date compare:calendarView.lastDate] == NSOrderedDescending) { //不小于最后一天
73 | cellState = ZBJCalendarCellStateDisabled;
74 | } else {
75 |
76 | ZBJCalendarDate *day = [self offerDateWithDate:date];
77 | price = day.price;
78 |
79 | if (day.available.boolValue) {
80 | cellState = ZBJCalendarCellStateAvaible;
81 | } else {
82 | cellState = ZBJCalendarCellStateUnavaible;
83 | }
84 | }
85 | } else {
86 | cellState = ZBJCalendarCellStateEmpty;
87 | }
88 |
89 | cell.price = price;
90 | cell.cellState = cellState;
91 | }
92 |
93 | - (void)calendarView:(ZBJCalendarView *)calendarView configureSectionHeaderView:(ZBJCalendarSectionHeader *)headerView firstDateOfMonth:(NSDate *)firstDateOfMonth {
94 | NSCalendar *calendar = [NSDate gregorianCalendar];
95 | NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth fromDate:firstDateOfMonth];
96 | headerView.year = components.year;
97 | headerView.month = components.month;
98 | }
99 |
100 |
101 | #pragma mark - getters
102 | - (ZBJCalendarView *)calendarView {
103 | if (!_calendarView) {
104 | _calendarView = [[ZBJCalendarView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(self.titleLable.frame) + 17, CGRectGetWidth(self.backView.frame), CGRectGetHeight(self.backView.frame) - CGRectGetMaxY(self.titleLable.frame) - 17 - 55)];
105 | [_calendarView registerCellClass:[ZBJCalendarShowCell class] withReuseIdentifier:@"cell"];
106 | [_calendarView registerSectionHeader:[ZBJCalendarSectionHeader class] withReuseIdentifier:@"sectionHader"];
107 | [_calendarView registerSectionFooter:[ZBJCalendarSectionFooter class] withReuseIdentifier:@"sectionFooter"];
108 | _calendarView.selectionMode = ZBJSelectionModeDisable;
109 | _calendarView.contentInsets = UIEdgeInsetsMake(0, 16, 0, 16);
110 | _calendarView.sectionHeaderHeight = 52;
111 | _calendarView.sectionFooterHeight = 13;
112 | }
113 | return _calendarView;
114 | }
115 |
116 | - (UIView *)backView {
117 | if (!_backView) {
118 | _backView = [[UIView alloc] initWithFrame:CGRectMake(15, 40, CGRectGetWidth(self.frame) - 30, CGRectGetHeight(self.frame) - 70)];
119 | _backView.backgroundColor = [UIColor whiteColor];
120 | _backView.layer.cornerRadius = 3;
121 | _backView.clipsToBounds = YES;
122 |
123 | [_backView addSubview:self.titleLable];
124 | [_backView addSubview:self.calendarView];
125 | [_backView addSubview:self.cancelButton];
126 | }
127 | return _backView;
128 | }
129 |
130 | - (UILabel *)titleLable {
131 | if (!_titleLable) {
132 | _titleLable = [[UILabel alloc] initWithFrame:CGRectMake(25, 25, 200, 20)];
133 | _titleLable.font = [UIFont systemFontOfSize:20];
134 | _titleLable.text = @"可租价格日历";
135 | }
136 | return _titleLable;
137 | }
138 |
139 | - (UIButton *)cancelButton {
140 | if (!_cancelButton) {
141 | _cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
142 | _cancelButton.frame = CGRectMake(self.backView.frame.size.width/2 - 12, CGRectGetHeight(self.backView.frame) - 15 - 25, 25, 25);
143 | [_cancelButton setImage:[UIImage imageNamed:@"cancel"] forState:UIControlStateNormal];
144 | [_cancelButton addTarget:self action:@selector(cancel:) forControlEvents:UIControlEventTouchUpInside];
145 | }
146 | return _cancelButton;
147 | }
148 |
149 | #pragma mark - setters
150 | - (void)setCalendarDates:(ZBJCalendarDates *)calendarDates {
151 | _calendarDates = calendarDates;
152 | self.calendarView.firstDate = self.calendarDates.startDate;
153 | self.calendarView.lastDate = self.calendarDates.endDate;
154 | self.calendarView.dataSource = self;
155 | }
156 |
157 | @end
158 |
--------------------------------------------------------------------------------
/ZBJCalendar/ZBJCalendar/NSDate+ZBJAddition.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSDate+ZBJAddition.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 2/26/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "NSDate+ZBJAddition.h"
10 | #import
11 |
12 | const char * const JmoCalendarStoreKey = "jmo.calendar";
13 | const char * const JmoLocaleStoreKey = "jmo.locale";
14 |
15 | @implementation NSDate (ZBJAddition)
16 |
17 | #pragma mark -
18 | + (void)setGregorianCalendar:(NSCalendar *)gregorianCalendar
19 | {
20 | objc_setAssociatedObject(self, JmoCalendarStoreKey, gregorianCalendar, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
21 | }
22 |
23 | + (NSCalendar *)gregorianCalendar
24 | {
25 | NSCalendar *cal = objc_getAssociatedObject(self, JmoCalendarStoreKey);
26 | if (nil == cal) {
27 | cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
28 | [cal setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];
29 | [cal setLocale:[self locale]];
30 | [self setGregorianCalendar:cal];
31 | }
32 | return cal;
33 | }
34 |
35 | + (void)setLocal:(NSLocale *)locale
36 | {
37 | objc_setAssociatedObject(self, JmoLocaleStoreKey, locale, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
38 | }
39 |
40 | + (NSLocale *)locale
41 | {
42 | NSLocale *locale = objc_getAssociatedObject(self, JmoLocaleStoreKey);
43 | if (nil == locale) {
44 | locale = [[NSLocale alloc] initWithLocaleIdentifier:@"fr_FR"];
45 | [self setLocal:locale];
46 | }
47 | return locale;
48 | }
49 |
50 |
51 | #pragma mark -
52 | + (NSDate *)today {
53 | NSDate *sourceDate = [NSDate date];
54 |
55 | NSTimeZone *sourceTimeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
56 | NSTimeZone *destinationTimeZone = [NSTimeZone systemTimeZone];
57 |
58 | NSInteger sourceGMTOffset = [sourceTimeZone secondsFromGMTForDate:sourceDate];
59 | NSInteger destinationGMTOffset = [destinationTimeZone secondsFromGMTForDate:sourceDate];
60 | NSTimeInterval interval = destinationGMTOffset - sourceGMTOffset;
61 |
62 | return [[NSDate alloc] initWithTimeInterval:interval sinceDate:sourceDate];
63 | }
64 | + (NSInteger)numberOfMonthsFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate {
65 | NSCalendar *calendar = [self gregorianCalendar];
66 | NSDateComponents *components = [calendar components:NSCalendarUnitMonth fromDate:[fromDate firstDateOfMonth] toDate:[toDate lastDateOfMonth] options:NSCalendarMatchStrictly];
67 | // 2016.9.16 - 2016.3.16 = 5 if use [fromDate firstDateOfMonth] and [toDate lastDateOfMonth], the result is 6. ok
68 | // 2017.3.16 - 2016.3.16 = 12
69 | return components.month + 1;
70 | }
71 |
72 | + (NSInteger)numberOfDaysFromMonth:(NSDate *)fromMonth toMonth:(NSDate *)toMonth {
73 | NSCalendar *calendar = [self gregorianCalendar];
74 | NSDate *firstDate = [fromMonth firstDateOfMonth];
75 | NSDate *lastDate = [toMonth lastDateOfMonth];
76 | NSDateComponents *components = [calendar components:NSCalendarUnitDay fromDate:firstDate toDate:lastDate options:NSCalendarMatchStrictly];
77 | return components.day + 1;
78 | }
79 |
80 | + (NSInteger)numberOfDaysInMonth:(NSDate *)date {
81 | NSCalendar *calendar = [self gregorianCalendar];
82 | NSRange range = [calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date];
83 | return range.length;
84 | }
85 |
86 | + (NSInteger)numberOfNightsFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate {
87 | NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
88 | unsigned int unitFlag = NSCalendarUnitDay;
89 | NSDateComponents *components = [calendar components:unitFlag fromDate:fromDate toDate:toDate options:0];
90 | NSInteger days = [components day];
91 | return days;
92 | }
93 |
94 | #pragma mark -
95 | - (NSDate *)firstDateOfMonth {
96 | NSCalendar *calendar = [self.class gregorianCalendar];
97 | NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:self];
98 | components.day = 1;
99 | return [calendar dateFromComponents:components];
100 | }
101 |
102 | - (NSDate *)firstDateOfWeek {
103 |
104 | NSInteger weekDay = self.weekday;
105 |
106 | NSCalendar *calendar = [self.class gregorianCalendar];
107 | NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitWeekday fromDate:self];
108 | components.day = components.day - weekDay + 1;
109 | return [calendar dateFromComponents:components];
110 | }
111 |
112 | - (NSDate *)lastDateOfMonth {
113 | NSCalendar *calendar = [self.class gregorianCalendar];
114 | NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:self];
115 | components.month = components.month + 1;
116 | components.day = 0;
117 | return [calendar dateFromComponents:components];
118 | }
119 |
120 | - (NSInteger)weekday {
121 | NSCalendar *calendar = [self.class gregorianCalendar];
122 | NSDateComponents *compoents = [calendar components:NSCalendarUnitWeekday fromDate:self];
123 | return compoents.weekday;
124 | }
125 |
126 | - (BOOL)isToday {
127 | NSCalendar *calendar = [self.class gregorianCalendar];
128 | NSDateComponents *otherDay = [calendar components:NSCalendarUnitEra | NSCalendarUnitYear |NSCalendarUnitMonth | NSCalendarUnitDay fromDate:self];
129 | NSDateComponents *today = [[NSCalendar currentCalendar] components:NSCalendarUnitEra | NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:[NSDate date]];
130 | if([today day] == [otherDay day] &&
131 | [today month] == [otherDay month] &&
132 | [today year] == [otherDay year] &&
133 | [today era] == [otherDay era]) {
134 | return YES;
135 | }
136 | return NO;
137 | }
138 |
139 | - (BOOL)isWeekend {
140 | NSCalendar *calendar = [self.class gregorianCalendar];
141 | NSRange weekdayRange = [calendar maximumRangeOfUnit:NSCalendarUnitWeekday];
142 | NSDateComponents *components = [calendar components:NSCalendarUnitWeekday fromDate:self];
143 | NSUInteger weekdayOfDate = [components weekday];
144 |
145 | if (weekdayOfDate == weekdayRange.location || weekdayOfDate == weekdayRange.length) {
146 | //the date falls somewhere on the first or last days of the week
147 | return YES;
148 | }
149 | return NO;
150 | }
151 |
152 | - (BOOL)isSameMonthWithDate:(NSDate *)date {
153 |
154 | NSCalendar *calendar = [self.class gregorianCalendar];
155 | NSDateComponents *components = [calendar components:NSCalendarUnitMonth fromDate:self];
156 | NSDateComponents *toComponents = [calendar components:NSCalendarUnitMonth fromDate:date];
157 |
158 | return components.month == toComponents.month;
159 | }
160 |
161 |
162 |
163 |
164 | @end
165 |
--------------------------------------------------------------------------------
/ZBJCalendar/RangeSelection/simple/ZBJSimpleRangeSelectionCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJSimpleRangeSelectionCell.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 3/15/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJSimpleRangeSelectionCell.h"
10 | #import "NSDate+ZBJAddition.h"
11 |
12 | @interface ZBJSimpleRangeSelectionCell()
13 |
14 | @property (nonatomic, strong) NSCalendar *calendar;
15 |
16 | @property (nonatomic, strong) UILabel *dateLabel;
17 | @property (nonatomic, strong) UILabel *stateLabel;
18 | @end
19 |
20 | @implementation ZBJSimpleRangeSelectionCell
21 |
22 | - (instancetype)initWithFrame:(CGRect)frame {
23 | if (self = [super initWithFrame:frame]) {
24 | [self.contentView addSubview:self.dateLabel];
25 | self.calendar = [NSDate gregorianCalendar];
26 | }
27 | return self;
28 | }
29 |
30 | - (void)layoutSubviews {
31 | [super layoutSubviews];
32 |
33 | if (self.cellStyle == ZBJRangeCellStyle2) {
34 |
35 | if (![self.stateLabel superview] || !self.stateLabel.text) {
36 | self.dateLabel.frame = CGRectMake(0, (CGRectGetHeight(self.bounds) - 15) / 2, CGRectGetWidth(self.bounds), 15);
37 | } else {
38 | self.dateLabel.frame = CGRectMake(0, CGRectGetHeight(self.bounds) / 2 - CGRectGetHeight(self.dateLabel.frame) - 2, CGRectGetWidth(self.bounds), 15);
39 | self.stateLabel.frame = CGRectMake(0, CGRectGetHeight(self.frame) / 2 + 5, CGRectGetWidth(self.contentView.frame), 9);
40 | }
41 |
42 | } else {
43 | if (![self.stateLabel superview] || !self.stateLabel.text) {
44 | self.dateLabel.frame = CGRectMake(0, (CGRectGetHeight(self.bounds) - 17) / 2, CGRectGetWidth(self.bounds), 17);
45 | } else {
46 | self.dateLabel.frame = CGRectMake(0, CGRectGetHeight(self.bounds) / 2 - CGRectGetHeight(self.dateLabel.frame) + 1, CGRectGetWidth(self.bounds), 17);
47 | self.stateLabel.frame = CGRectMake(0, CGRectGetHeight(self.frame) / 2 + 4, CGRectGetWidth(self.contentView.frame), 10);
48 | }
49 |
50 | }
51 |
52 |
53 | }
54 |
55 |
56 | #pragma mark - setters
57 |
58 | - (void)setCellStyle:(ZBJRangeCellStyle)cellStyle {
59 |
60 | if (_cellStyle != cellStyle) {
61 | _cellStyle = cellStyle;
62 |
63 | switch (_cellStyle) {
64 | case ZBJRangeCellStyle2: {
65 | self.dateLabel.font = [UIFont systemFontOfSize:15];
66 | self.stateLabel.font = [UIFont systemFontOfSize:9];
67 | break;
68 | }
69 | default: {
70 | self.dateLabel.font = [UIFont systemFontOfSize:17];
71 | self.stateLabel.font = [UIFont systemFontOfSize:10];
72 | break;
73 | }
74 | }
75 | }
76 | }
77 |
78 | - (void)setDate:(NSDate *)date {
79 | _date = date;
80 | if (_date) {
81 | self.dateLabel.text = [NSString stringWithFormat:@"%ld", [self.calendar component:NSCalendarUnitDay fromDate:_date]];
82 | } else {
83 | self.dateLabel.text = nil;
84 | }
85 | }
86 |
87 | - (void)setCellState:(ZBJCalendarCellState)cellState {
88 | _cellState = cellState;
89 | switch (_cellState) {
90 | case ZBJCalendarCellStateDisabled: {
91 |
92 | if (self.stateLabel.superview) {
93 | [self.stateLabel removeFromSuperview];
94 | }
95 | self.contentView.backgroundColor = [UIColor clearColor];
96 | self.dateLabel.textColor = [UIColor colorWithRed:192.0/255.0 green:192.0/255.0 blue:200.0/255.0 alpha:1.0];
97 | break;
98 | }
99 | case ZBJCalendarCellStateAvaible: {
100 |
101 | if (self.stateLabel.superview) {
102 | [self.stateLabel removeFromSuperview];
103 | }
104 | self.contentView.backgroundColor = [UIColor clearColor];
105 | self.dateLabel.textColor = [UIColor colorWithRed:9.0/255.0 green:9.0/255.0 blue:26.0/255.0 alpha:1.0];
106 | break;
107 | }
108 | case ZBJCalendarCellStateAvaibleDisabled: {
109 | if (self.stateLabel.superview) {
110 | [self.stateLabel removeFromSuperview];
111 | }
112 | self.contentView.backgroundColor = [UIColor clearColor];
113 | self.dateLabel.textColor = [UIColor colorWithRed:192.0/255.0 green:192.0/255.0 blue:200.0/255.0 alpha:1.0];
114 | break;
115 | }
116 | case ZBJCalendarCellStateSelectedStart: {
117 |
118 | [self.contentView addSubview:self.stateLabel];
119 |
120 | self.contentView.backgroundColor = [UIColor colorWithRed:9.0/255.0 green:9.0/255.0 blue:26.0/255.0 alpha:1.0];
121 | self.dateLabel.textColor = [UIColor whiteColor];
122 | self.stateLabel.textColor = [UIColor whiteColor];
123 | self.stateLabel.text = @"入住";
124 | break;
125 | }
126 | case ZBJCalendarCellStateSelectedMiddle: {
127 | if (self.stateLabel.superview) {
128 | [self.stateLabel removeFromSuperview];
129 | }
130 | self.contentView.backgroundColor = [UIColor colorWithRed:58.0/255.0 green:58.0/255.0 blue:72.0/255.0 alpha:1.0];
131 | self.dateLabel.textColor = [UIColor whiteColor];
132 | self.stateLabel.textColor = [UIColor whiteColor];
133 | break;
134 | }
135 | case ZBJCalendarCellStateSelectedEnd: {
136 |
137 | [self.contentView addSubview:self.stateLabel];
138 | self.contentView.backgroundColor = [UIColor colorWithRed:9.0/255.0 green:9.0/255.0 blue:26.0/255.0 alpha:1.0];
139 | self.dateLabel.textColor = [UIColor whiteColor];
140 | self.stateLabel.textColor = [UIColor whiteColor];
141 |
142 | self.stateLabel.text = @"退房";
143 | break;
144 | }
145 | case ZBJCalendarCellStateEmpty: {
146 |
147 | self.dateLabel.text = nil;
148 | self.stateLabel.text = nil;
149 | [self.stateLabel removeFromSuperview];
150 |
151 | self.contentView.backgroundColor = [UIColor clearColor];
152 | break;
153 | }
154 | default: {
155 | break;
156 | }
157 |
158 | }
159 | [self layoutSubviews];
160 | }
161 |
162 | #pragma mark - getters
163 | - (UILabel *)dateLabel {
164 | if (!_dateLabel) {
165 | _dateLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.frame), 17)];
166 | _dateLabel.textAlignment = NSTextAlignmentCenter;
167 | _dateLabel.font = [UIFont systemFontOfSize:17];
168 | _dateLabel.textColor = [UIColor darkTextColor];
169 | }
170 | return _dateLabel;
171 | }
172 |
173 | - (UILabel *)stateLabel {
174 | if (!_stateLabel) {
175 | _stateLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.frame), 10)];
176 | _stateLabel.font = [UIFont systemFontOfSize:10];
177 | _stateLabel.textAlignment = NSTextAlignmentCenter;
178 | _stateLabel.textColor = [UIColor colorWithRed:157.0/255.0 green:157.0/255.0 blue:163.0/255.0 alpha:1.0];
179 | }
180 | return _stateLabel;
181 | }
182 |
183 | @end
184 |
--------------------------------------------------------------------------------
/ZBJCalendar/RangeSelection/simple/ZBJSimpleRangeSelectionController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJSimpleRangeSelectionController.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 2/26/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJSimpleRangeSelectionController.h"
10 | #import "ZBJCalendar.h"
11 | #import "ZBJSimpleRangeSelectionCell.h"
12 | #import "ZBJCalendarSectionHeader.h"
13 | #import "ZBJCalendarSectionFooter.h"
14 |
15 | typedef CF_ENUM(NSInteger, ZBJCalendarSelectedState) {
16 | ZBJCalendarStateSelectedNone,
17 | ZBJCalendarStateSelectedStart,
18 | ZBJCalendarStateSelectedRange,
19 | };
20 |
21 | @interface ZBJSimpleRangeSelectionController ()
22 |
23 | @property (nonatomic, strong) ZBJCalendarView *calendarView;
24 | @property (nonatomic, assign) ZBJCalendarSelectedState selectedState;
25 | @property (nonatomic, assign) ZBJRangeCellStyle cellStyle;
26 |
27 | @end
28 |
29 | @implementation ZBJSimpleRangeSelectionController
30 |
31 | - (void)viewDidLoad {
32 | [super viewDidLoad];
33 |
34 | self.view.backgroundColor = [UIColor whiteColor];
35 |
36 | NSDate *firstDate = [NSDate date];
37 | NSCalendar *calendar = [NSCalendar currentCalendar];
38 | [calendar setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]];
39 | NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:firstDate];
40 | components.month = components.month + 6; //
41 | NSDate *lastDate = [calendar dateFromComponents:components];
42 |
43 | self.calendarView.delegate = self;
44 | self.calendarView.dataSource = self;
45 | self.calendarView.firstDate = firstDate;
46 | self.calendarView.lastDate = lastDate;
47 |
48 | [self.view addSubview:self.calendarView];
49 | }
50 |
51 | - (void)didReceiveMemoryWarning {
52 | [super didReceiveMemoryWarning];
53 | }
54 |
55 | - (void)pop {
56 | if (self.delegate && [self.delegate respondsToSelector:@selector(popViewController:startDate:endDate:)]) {
57 | [self.delegate popViewController:self startDate:self.startDate endDate:self.endDate];
58 | }
59 | }
60 |
61 | #pragma mark - ZBJCalendarDelegate && ZBJCalendarDataSource
62 | - (void)calendarView:(ZBJCalendarView *)calendarView configureCell:(ZBJSimpleRangeSelectionCell *)cell forDate:(NSDate *)date {
63 |
64 | cell.cellStyle = self.cellStyle;
65 |
66 | cell.date = date;
67 |
68 | ZBJCalendarCellState cellState = -1;
69 |
70 | if (date) {
71 | // 如果小于起始日期或大于结束日期,那么disabled
72 | if ([[date dateByAddingTimeInterval:86400.0 - 1] compare:calendarView.firstDate] == NSOrderedAscending ||
73 | [date compare:calendarView.lastDate] != NSOrderedAscending) { //不大于最后一天
74 | cellState = ZBJCalendarCellStateDisabled;
75 | } else {
76 |
77 | switch (self.selectedState) {
78 | case ZBJCalendarStateSelectedStart: {
79 |
80 | if ([[date dateByAddingTimeInterval:86400.0 - 1] compare:self.startDate] == NSOrderedAscending) {
81 |
82 | cellState = ZBJCalendarCellStateAvaibleDisabled;
83 | } else if ([self.startDate isEqualToDate:date]) {
84 | cellState = ZBJCalendarCellStateSelectedStart;
85 | } else {
86 | cellState = ZBJCalendarCellStateAvaible;
87 | }
88 |
89 | break;
90 | }
91 | case ZBJCalendarStateSelectedRange: {
92 |
93 | if ([self.startDate isEqualToDate:date]) {
94 | cellState = ZBJCalendarCellStateSelectedStart;
95 | } else if ([self.endDate isEqualToDate:date]) {
96 | cellState = ZBJCalendarCellStateSelectedEnd;
97 | } else if (self.startDate && self.endDate &&
98 | [[date dateByAddingTimeInterval:86400.0 - 1] compare:self.endDate] == NSOrderedAscending &&
99 | [date compare:self.startDate] == NSOrderedDescending) {
100 | cellState = ZBJCalendarCellStateSelectedMiddle;
101 | } else {
102 | cellState = ZBJCalendarCellStateAvaible;
103 | }
104 |
105 | break;
106 | }
107 | default: {
108 | cellState = ZBJCalendarCellStateAvaible;
109 | break;
110 | }
111 | }
112 | }
113 | } else {
114 | cellState = ZBJCalendarCellStateEmpty;
115 | }
116 |
117 | cell.cellState = cellState;
118 | }
119 | - (void)calendarView:(ZBJCalendarView *)calendarView didSelectDate:(NSDate *)date ofCell:(id)cell {
120 |
121 | if (calendarView.selectionMode == ZBJSelectionModeMutiple) {
122 | if (date) {
123 | if (!self.startDate) {
124 | self.startDate = date;
125 | [self setSelectedState:ZBJCalendarStateSelectedStart calendarView:calendarView];
126 | } else if (!self.endDate) {
127 | if ([self.startDate isEqualToDate:date]) {
128 | [self setSelectedState:ZBJCalendarStateSelectedNone calendarView:calendarView];
129 | return;
130 | }
131 | self.endDate = date;
132 | [self setSelectedState:ZBJCalendarStateSelectedRange calendarView:calendarView];
133 | } else {
134 | self.endDate = nil;
135 | self.startDate = date;
136 | [self setSelectedState:ZBJCalendarStateSelectedStart calendarView:calendarView];
137 | }
138 | }
139 | }
140 | }
141 |
142 | - (void)setSelectedState:(ZBJCalendarSelectedState)selectedState calendarView:(ZBJCalendarView *)calendarView {
143 |
144 | _selectedState = selectedState;
145 |
146 | switch (_selectedState) {
147 | case ZBJCalendarStateSelectedNone: {
148 | self.startDate = nil;
149 | self.endDate = nil;
150 | [calendarView reloadData];
151 | calendarView.allowsSelection = YES;
152 | break;
153 | }
154 | case ZBJCalendarStateSelectedStart: {
155 |
156 | [calendarView reloadData];
157 | break;
158 | }
159 | case ZBJCalendarStateSelectedRange: {
160 | [calendarView reloadData];
161 | // pop self
162 | [self performSelector:@selector(pop) withObject:nil afterDelay:0.4];
163 | break;
164 | }
165 | default:
166 | break;
167 | }
168 | }
169 |
170 |
171 | - (void)calendarView:(ZBJCalendarView *)calendarView configureSectionHeaderView:(ZBJCalendarSectionHeader *)headerView firstDateOfMonth:(NSDate *)firstDateOfMonth {
172 | NSCalendar *calendar = [NSDate gregorianCalendar];
173 | NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth fromDate:firstDateOfMonth];
174 | headerView.year = components.year;
175 | headerView.month = components.month;
176 | }
177 |
178 |
179 |
180 |
181 | #pragma mark -
182 | - (ZBJCalendarView *)calendarView {
183 | if (!_calendarView) {
184 | _calendarView = [[ZBJCalendarView alloc] initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame) - 64)];
185 | [_calendarView registerCellClass:[ZBJSimpleRangeSelectionCell class] withReuseIdentifier:@"cell"];
186 | [_calendarView registerSectionHeader:[ZBJCalendarSectionHeader class] withReuseIdentifier:@"sectionHeader"];
187 | [_calendarView registerSectionFooter:[ZBJCalendarSectionFooter class] withReuseIdentifier:@"sectionFooter"];
188 | _calendarView.contentInsets = UIEdgeInsetsMake(0, 14, 0, 14);
189 | _calendarView.sectionHeaderHeight = 52;
190 | _calendarView.sectionFooterHeight = 13;
191 | _calendarView.cellScale = 90.0 / 102.0;
192 |
193 | }
194 | return _calendarView;
195 | }
196 |
197 | @end
198 |
--------------------------------------------------------------------------------
/ZBJCalendar/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 15/12/8.
6 | // Copyright © 2015年 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 | #import "ZBJCalendarShowView.h"
11 | #import "ZBJSimpleRangeSelectionController.h"
12 | #import "ZBJComplexRangeSelectionController.h"
13 | #import "ZBJCalendarDates.h"
14 | #import "ZBJSingleSelectionController.h"
15 | #import "ZBJSimpleMutipleSelectionViewController.h"
16 |
17 | static NSString * const ZBJCellIdentifier = @"cell";
18 |
19 | @interface ViewController ()
20 |
21 | @property (nonatomic, strong) NSArray *tableData;
22 |
23 | @property (nonatomic, strong) NSDate *startDate;
24 | @property (nonatomic, strong) NSDate *endDate;
25 |
26 | @property (nonatomic, strong) ZBJSimpleRangeSelectionController *rangeController;
27 | @property (nonatomic, strong) ZBJComplexRangeSelectionController *advanceCalController;
28 |
29 | @property (nonatomic, strong) ZBJSimpleMutipleSelectionViewController *mutipleSelectionController;
30 | @end
31 |
32 | @implementation ViewController
33 |
34 | - (void)viewWillAppear:(BOOL)animated {
35 | [super viewWillAppear:animated];
36 |
37 | }
38 |
39 | - (void)viewDidLoad {
40 | [super viewDidLoad];
41 | self.tableView.tableFooterView = [UIView new];
42 | }
43 |
44 | - (void)didReceiveMemoryWarning {
45 | [super didReceiveMemoryWarning];
46 | }
47 |
48 |
49 | #pragma mark - UITableViewDataSource
50 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
51 | return self.tableData.count;
52 | }
53 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
54 | return [self.tableData[section][@"cells"] count];
55 | }
56 |
57 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
58 | return self.tableData[section][@"sectionTitle"];
59 | }
60 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
61 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ZBJCellIdentifier forIndexPath:indexPath];
62 |
63 | NSDictionary *cellData = self.tableData[indexPath.section][@"cells"][indexPath.row];
64 | cell.textLabel.text = cellData[@"cellTitle"];
65 | return cell;
66 | }
67 |
68 |
69 | #pragma mark - UITableViewDelegate
70 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
71 | [tableView deselectRowAtIndexPath:indexPath animated:YES];
72 |
73 | switch (indexPath.section) {
74 | case 0: {
75 | switch (indexPath.row) {
76 | case 0: {
77 | NSString *path = [[NSBundle mainBundle] pathForResource:@"calendar_dates" ofType:@"json"];
78 | NSData *data = [NSData dataWithContentsOfFile:path];
79 |
80 | NSError *error;
81 | ZBJCalendarDates *calendarDates;
82 | NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
83 | if (!error) {
84 | calendarDates = [[ZBJCalendarDates alloc] initWithDictionary:dic];
85 | }
86 |
87 | ZBJCalendarShowView *controller = [[ZBJCalendarShowView alloc] initWithFrame:[UIApplication sharedApplication].keyWindow.frame calendarDates:calendarDates];
88 | controller.alpha = 0.0;
89 |
90 | [[UIApplication sharedApplication].keyWindow addSubview:controller];
91 | [UIView animateWithDuration:0.2f animations:^{
92 | controller.alpha = 1.0;
93 | } completion:^(BOOL finished) {
94 |
95 | }];
96 | break;
97 | }
98 | default:
99 | break;
100 | }
101 | break;
102 | }
103 | case 1: {
104 | switch (indexPath.row) {
105 | case 0: {
106 | ZBJSingleSelectionController *controller = [[ZBJSingleSelectionController alloc] init];
107 | [self.navigationController pushViewController:controller animated:YES];
108 | break;
109 | }
110 | default:
111 | break;
112 | }
113 | break;
114 | }
115 | case 2: {
116 |
117 | switch (indexPath.row) {
118 | case 0: {
119 | self.rangeController.startDate = self.startDate;
120 | self.rangeController.endDate = self.endDate;
121 | [self.navigationController pushViewController:self.rangeController animated:YES];
122 | break;
123 | }
124 | case 1: {
125 | self.advanceCalController.startDate = self.startDate;
126 | self.advanceCalController.endDate = self.endDate;
127 | [self.navigationController pushViewController:self.advanceCalController animated:YES];
128 | break;
129 | }
130 | default:
131 | break;
132 | }
133 | break;
134 | }
135 | case 3: {
136 |
137 | switch (indexPath.row) {
138 | case 0:
139 | [self.navigationController pushViewController:self.mutipleSelectionController animated:YES];
140 | break;
141 |
142 | default:
143 | break;
144 | }
145 | }
146 | default:
147 | break;
148 | }
149 | }
150 |
151 | #pragma mark - range && advance delegate
152 | - (void)popViewController:(UIViewController *)viewController startDate:(NSDate *)startDate endDate:(NSDate *)endDate {
153 | [viewController.navigationController popViewControllerAnimated:YES];
154 |
155 | NSLog(@"----> startDate : %@, endDate: %@", startDate, endDate);
156 |
157 | self.startDate = startDate;
158 | self.endDate = endDate;
159 | }
160 |
161 | #pragma mark - getter
162 | - (NSArray *)tableData {
163 | if (!_tableData) {
164 | _tableData = @[@{@"sectionTitle": @"Show",
165 | @"cells": @[@{@"cellTitle": @"view"}]},
166 | @{@"sectionTitle": @"Single Selection",
167 | @"cells": @[@{@"cellTitle": @"general"}]},
168 | @{@"sectionTitle": @"Range Selection",
169 | @"cells": @[@{@"cellTitle": @"simple"}, @{@"cellTitle": @"complex"}]},
170 | @{@"sectionTitle": @"Mutiple Selection",
171 | @"cells": @[@{@"cellTitle": @"simple"}]}
172 | ];
173 | }
174 | return _tableData;
175 | }
176 |
177 | - (ZBJSimpleRangeSelectionController *)rangeController {
178 | if (!_rangeController) {
179 | _rangeController = [ZBJSimpleRangeSelectionController new];
180 | _rangeController.delegate = self;
181 | }
182 | return _rangeController;
183 | }
184 |
185 | - (ZBJComplexRangeSelectionController *)advanceCalController {
186 | if (!_advanceCalController) {
187 | _advanceCalController = [ZBJComplexRangeSelectionController new];
188 | _advanceCalController.delegate = self;
189 |
190 | NSString *path = [[NSBundle mainBundle] pathForResource:@"calendar_dates" ofType:@"json"];
191 | NSData *data = [NSData dataWithContentsOfFile:path];
192 |
193 | NSError *error;
194 | ZBJCalendarDates *calendarDates;
195 | NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
196 | if (!error) {
197 | calendarDates = [[ZBJCalendarDates alloc] initWithDictionary:dic];
198 | }
199 |
200 | _advanceCalController.firstDate = calendarDates.startDate;
201 | _advanceCalController.lastDate = calendarDates.endDate;
202 | _advanceCalController.dates = calendarDates.dates;
203 | _advanceCalController.minNights = 2;
204 | }
205 | return _advanceCalController;
206 | }
207 |
208 | - (ZBJSimpleMutipleSelectionViewController *)mutipleSelectionController {
209 | if (!_mutipleSelectionController) {
210 | _mutipleSelectionController = [[ZBJSimpleMutipleSelectionViewController alloc] init];
211 | }
212 | return _mutipleSelectionController;
213 | }
214 |
215 | @end
216 |
--------------------------------------------------------------------------------
/ZBJCalendar/MutipleSelection/ZBJSimpleMutipleSelectionViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJSimpleMutipleSelectionViewController.m
3 | // ZBJCalendar
4 | //
5 | // Created by wanggang on 7/4/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJSimpleMutipleSelectionViewController.h"
10 | #import "ZBJCalendar.h"
11 | #import "ZBJSimpleMutipleSelectionCell.h"
12 | #import "ZBJMutipleSelectionSectionHeaderView.h"
13 | #import "UINavigationBar+ZBJAddition.h"
14 |
15 | @interface ZBJSimpleMutipleSelectionViewController ()
16 |
17 | @property (nonatomic, strong) ZBJCalendarView *calendarView;
18 |
19 | @property (nonatomic, strong) NSMutableSet *selectedMonths;
20 | @property (nonatomic, strong) NSMutableSet *selectedDates;
21 | @property (nonatomic, strong) NSMutableDictionary *selectedTypes;
22 |
23 | @end
24 |
25 | @implementation ZBJSimpleMutipleSelectionViewController
26 |
27 | - (void)viewWillAppear:(BOOL)animated {
28 | [super viewWillAppear:animated];
29 | [self.navigationController.navigationBar hidenHairLine:YES];
30 | }
31 |
32 | -(void)viewWillDisappear:(BOOL)animated {
33 | [super viewWillDisappear:animated];
34 | [self.navigationController.navigationBar hidenHairLine:NO];
35 | }
36 |
37 | - (void)viewDidLoad {
38 | [super viewDidLoad];
39 | self.view.backgroundColor = [UIColor whiteColor];
40 |
41 | // 获取当前日期
42 | NSDate *today = [NSDate today];
43 |
44 | // NSDate *today = [NSDate date];
45 | // 获取6个月后的最后一天
46 | NSCalendar *calendar = [NSDate gregorianCalendar];
47 | NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:today];
48 |
49 | NSDate *firstDate = [calendar dateFromComponents:components];
50 |
51 | components.month = components.month + 6 + 1;
52 | components.day = 0;
53 | NSDate *lastDate = [calendar dateFromComponents:components];
54 |
55 | self.calendarView.firstDate = firstDate;
56 | self.calendarView.lastDate = lastDate;
57 |
58 | [self.view addSubview:self.calendarView];
59 |
60 | self.selectedDates = [NSMutableSet new];
61 | self.selectedMonths = [NSMutableSet new];
62 | self.selectedTypes = [NSMutableDictionary new];
63 | }
64 |
65 | - (void)didReceiveMemoryWarning {
66 | [super didReceiveMemoryWarning];
67 | }
68 |
69 |
70 | - (void)addDateFromMonth:(NSDate *)month {
71 |
72 | NSCalendar *calendar = [NSDate gregorianCalendar];
73 | NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitWeekday fromDate:month];
74 |
75 | NSInteger count = [NSDate numberOfDaysInMonth:month];
76 |
77 | if ([self.selectedMonths containsObject:month]) {
78 | [self.selectedMonths removeObject:month];
79 | for (int i = 1; i <= count; i++) {
80 | components.day = i;
81 | NSDate *date = [calendar dateFromComponents:components];
82 | [self.selectedDates removeObject:date];
83 | }
84 | } else {
85 | [self.selectedMonths addObject:month];
86 | NSDateComponents *todayComponents = [calendar components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
87 | NSDate *today = [calendar dateFromComponents:todayComponents];
88 | for (int i = 1; i <= count; i++) {
89 | components.day = i;
90 | NSDate *date = [calendar dateFromComponents:components];
91 | if ([date compare:today] != NSOrderedAscending) {
92 | [self.selectedDates addObject:date];
93 | }
94 | }
95 | }
96 | }
97 |
98 | #pragma mark - ZBJCalendarDataSource
99 | - (void)calendarView:(ZBJCalendarView *)calendarView configureCell:(ZBJSimpleMutipleSelectionCell *)cell forDate:(NSDate *)date {
100 |
101 | cell.date = date;
102 |
103 | if (date) {
104 | if ([[date dateByAddingTimeInterval:86400.0 - 1] compare:calendarView.firstDate] == NSOrderedAscending ||
105 | [date compare:calendarView.lastDate] == NSOrderedDescending) { //大于最后一天
106 | cell.cellState = ZBJCalendarCellStateDisabled;
107 | } else if ([self.selectedDates containsObject:date]) {
108 | NSNumber *type = self.selectedTypes[date];
109 | if (type) {
110 | cell.cellState = type.integerValue;
111 | } else {
112 | cell.cellState = ZBJCalendarCellStateSelected;
113 | }
114 | } else {
115 | cell.cellState = ZBJCalendarCellStateNormal;
116 | }
117 | } else {
118 | cell.cellState = ZBJCalendarCellStateEmpty;
119 | }
120 | }
121 |
122 | - (void)calendarView:(ZBJCalendarView *)calendarView configureSectionHeaderView:(ZBJMutipleSelectionSectionHeaderView *)headerView firstDateOfMonth:(NSDate *)firstDateOfMonth {
123 | headerView.firstDateOfMonth = firstDateOfMonth;
124 |
125 | __weak ZBJSimpleMutipleSelectionViewController *me = self;
126 | headerView.tapHandler = ^(NSDate *month) {
127 | [me addDateFromMonth:month];
128 | [me setSelectedTypes];
129 | [me.calendarView reloadData];
130 | NSLog(@"selected dates is : %@", self.selectedDates);
131 | };
132 | }
133 |
134 | - (void)calendarView:(ZBJCalendarView *)calendarView configureWeekDayLabel:(UILabel *)dayLabel atWeekDay:(NSInteger)weekDay {
135 | dayLabel.font = [UIFont systemFontOfSize:13];
136 | if (weekDay == 0 || weekDay == 6) {
137 | dayLabel.textColor = [UIColor lightGrayColor];
138 | }
139 | }
140 |
141 | #pragma mark - ZBJCalendarDelegate
142 | - (BOOL)calendarView:(ZBJCalendarView *)calendarView shouldSelectDate:(NSDate *)date {
143 | if (date) {
144 | if ([[date dateByAddingTimeInterval:86400.0 - 1] compare:calendarView.firstDate] == NSOrderedAscending ||
145 | [date compare:calendarView.lastDate] == NSOrderedDescending) {
146 | return NO;
147 | }
148 | }
149 | return YES;
150 | }
151 |
152 | - (void)calendarView:(ZBJCalendarView *)calendarView didSelectDate:(NSDate *)date ofCell:(ZBJSimpleMutipleSelectionCell *)cell {
153 |
154 | if ([self.selectedDates containsObject:date]) {
155 | [self.selectedDates removeObject:date];
156 | } else {
157 | [self.selectedDates addObject:date];
158 | }
159 |
160 | [self setSelectedTypes];
161 | [calendarView reloadData];
162 | NSLog(@"selected dates is : %@", self.selectedDates);
163 | }
164 |
165 |
166 |
167 | - (void)setSelectedTypes {
168 |
169 | for (NSDate *date in self.selectedDates) {
170 | NSCalendar *calendar = [NSDate gregorianCalendar];
171 | NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay fromDate:date];
172 |
173 | components.day = components.day + 1;
174 | NSDate *nextDate = [calendar dateFromComponents:components];
175 |
176 | components.day = components.day - 2;
177 | NSDate *preDate = [calendar dateFromComponents:components];
178 |
179 | BOOL containsNextDate = [self.selectedDates containsObject:nextDate];
180 | BOOL containsPreDate = [self.selectedDates containsObject:preDate];
181 |
182 | if (containsNextDate && containsPreDate) {
183 | self.selectedTypes[date] = @(ZBJCalendarCellStateSelectedMiddle);
184 | } else if (containsNextDate) {
185 | self.selectedTypes[date] = @(ZBJCalendarCellStateSelectedLeft);
186 | } else if (containsPreDate) {
187 | self.selectedTypes[date] = @(ZBJCalendarCellStateSelectedRight);
188 | } else {
189 | self.selectedTypes[date] = @(ZBJCalendarCellStateSelected);
190 | }
191 | }
192 | }
193 |
194 |
195 | #pragma mark -
196 | - (ZBJCalendarView *)calendarView {
197 | if (!_calendarView) {
198 | _calendarView = [[ZBJCalendarView alloc] initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame) - 64)];
199 | [_calendarView registerCellClass:[ZBJSimpleMutipleSelectionCell class] withReuseIdentifier:@"cell"];
200 | [_calendarView registerSectionHeader:[ZBJMutipleSelectionSectionHeaderView class] withReuseIdentifier:@"sectionHeader"];
201 | _calendarView.selectionMode = ZBJSelectionModeMutiple;
202 | _calendarView.dataSource = self;
203 | _calendarView.delegate = self;
204 | _calendarView.backgroundColor = [UIColor whiteColor];
205 | _calendarView.contentInsets = UIEdgeInsetsMake(0, 12.5, 0, 12.5);
206 | _calendarView.cellScale = 1;
207 | _calendarView.sectionHeaderHeight = 50;
208 | _calendarView.weekViewHeight = 20;
209 | _calendarView.weekView.backgroundColor = [UIColor colorWithRed:249.0f/255.0f green:249.0f/255.0f blue:249.0f/255.0f alpha:1.0];
210 | }
211 | return _calendarView;
212 | }
213 |
214 | @end
215 |
--------------------------------------------------------------------------------
/ZBJCalendar/RangeSelection/complex/ZBJComplexRangeSelectionCell.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJComplexRangeSelectionCell.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 2/24/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJComplexRangeSelectionCell.h"
10 | #import "NSDate+ZBJAddition.h"
11 |
12 | @interface ZBJComplexRangeSelectionCell ()
13 |
14 | @property (nonatomic, strong) UILabel *dateLabel;
15 | @property (nonatomic, strong) UILabel *priceLabel;
16 |
17 | @property (nonatomic, strong) NSCalendar *calendar;
18 | @property (nonatomic, strong) UIImageView *backgroundImageView;
19 |
20 | @end
21 |
22 | @implementation ZBJComplexRangeSelectionCell
23 |
24 | - (id)initWithFrame:(CGRect)frame {
25 | self = [super initWithFrame:frame];
26 | if (self) {
27 | [self.contentView addSubview:self.dateLabel];
28 | self.calendar = [NSDate gregorianCalendar];
29 | }
30 | return self;
31 | }
32 |
33 | - (void)layoutSubviews {
34 | [super layoutSubviews];
35 |
36 | if (![self.priceLabel superview] || !self.priceLabel.text) {
37 | self.dateLabel.frame = CGRectMake(0, (CGRectGetHeight(self.bounds) - 15) / 2, CGRectGetWidth(self.bounds), 15);
38 | } else {
39 | self.dateLabel.frame = CGRectMake(0, CGRectGetHeight(self.bounds) / 2 - CGRectGetHeight(self.dateLabel.frame) - 1, CGRectGetWidth(self.bounds), 15);
40 | self.priceLabel.frame = CGRectMake(0, CGRectGetHeight(self.frame) / 2 + 5, CGRectGetWidth(self.contentView.frame), 9);
41 | }
42 |
43 | self.backgroundImageView.frame = self.bounds;
44 | }
45 |
46 | #pragma mark - setters
47 | - (void)setDay:(NSDate *)day {
48 | _day = day;
49 | if (_day) {
50 | self.dateLabel.text = [NSString stringWithFormat:@"%ld", [self.calendar component:NSCalendarUnitDay fromDate:_day]];
51 | } else {
52 | self.dateLabel.text = nil;
53 | }
54 | }
55 |
56 | - (void)setPrice:(NSNumber *)price {
57 | _price = price;
58 | if (_price) {
59 | self.priceLabel.text = [NSString stringWithFormat:@"¥%@", _price];;
60 | } else {
61 | self.priceLabel.text = nil;
62 | [self.priceLabel removeFromSuperview];
63 | }
64 | }
65 |
66 |
67 | - (void)setIsToday:(BOOL)isToday {
68 | _isToday = isToday;
69 | }
70 |
71 | - (void)setCellState:(ZBJCalendarCellState)cellState {
72 | _cellState = cellState;
73 | switch (_cellState) {
74 | case ZBJCalendarCellStateDisabled: {
75 | // layout
76 | [self.priceLabel removeFromSuperview];
77 | self.backgroundView = nil;
78 |
79 | // style
80 | self.contentView.backgroundColor = [UIColor whiteColor];
81 | self.dateLabel.textColor = [UIColor colorWithRed:192.0/255.0 green:192.0/255.0 blue:200.0/255.0 alpha:1.0];
82 | break;
83 | }
84 | case ZBJCalendarCellStateUnavaible: {
85 | // layout
86 | if (![self.priceLabel superview]) {
87 | [self.contentView addSubview:self.priceLabel];
88 | }
89 | self.backgroundView = self.backgroundImageView;
90 |
91 | // style
92 | self.contentView.backgroundColor = [UIColor clearColor];
93 | self.dateLabel.textColor = [UIColor colorWithRed:192.0/255.0 green:192.0/255.0 blue:200.0/255.0 alpha:1.0];
94 | self.priceLabel.textColor = [UIColor colorWithRed:192.0/255.0 green:192.0/255.0 blue:200.0/255.0 alpha:1.0];
95 |
96 | self.priceLabel.text = @"已租";
97 | break;
98 | }
99 | case ZBJCalendarCellStateAvaible: {
100 | // layout
101 | if (![self.priceLabel superview]) {
102 | [self.contentView addSubview:self.priceLabel];
103 | }
104 | self.backgroundView = nil;
105 |
106 | // style
107 | self.contentView.backgroundColor = [UIColor whiteColor];
108 | self.dateLabel.textColor = [UIColor colorWithRed:9.0/255.0 green:9.0/255.0 blue:26.0/255.0 alpha:1.0];
109 | self.priceLabel.textColor = [UIColor colorWithRed:157.0/255.0 green:157.0/255.0 blue:163.0/255.0 alpha:1.0];
110 | break;
111 | }
112 | case ZBJCalendarCellStateAvaibleDisabled: {
113 | // layout
114 | if (![self.priceLabel superview]) {
115 | [self.contentView addSubview:self.priceLabel];
116 | }
117 | self.backgroundView = nil;
118 |
119 | // style
120 | self.contentView.backgroundColor = [UIColor whiteColor];
121 | self.dateLabel.textColor = [UIColor colorWithRed:192.0/255.0 green:192.0/255.0 blue:200.0/255.0 alpha:1.0];
122 | self.priceLabel.textColor = [UIColor colorWithRed:192.0/255.0 green:192.0/255.0 blue:200.0/255.0 alpha:1.0];
123 | break;
124 | }
125 |
126 |
127 | case ZBJCalendarCellStateSelectedStart: {
128 | // layout
129 | if (![self.priceLabel superview]) {
130 | [self.contentView addSubview:self.priceLabel];
131 | }
132 | self.backgroundView = nil;
133 |
134 | // style
135 | self.contentView.backgroundColor = [UIColor colorWithRed:9.0/255.0 green:9.0/255.0 blue:26.0/255.0 alpha:1.0];
136 | self.dateLabel.textColor = [UIColor whiteColor];
137 | self.priceLabel.textColor = [UIColor whiteColor];
138 |
139 | self.priceLabel.text = @"入住";
140 | break;
141 | }
142 | case ZBJCalendarCellStateSelectedMiddle: {
143 | // layout
144 | if (![self.priceLabel superview]) {
145 | [self.contentView addSubview:self.priceLabel];
146 | }
147 | self.backgroundView = nil;
148 |
149 | // style
150 | self.contentView.backgroundColor = [UIColor colorWithRed:58.0/255.0 green:58.0/255.0 blue:72.0/255.0 alpha:1.0];
151 | self.dateLabel.textColor = [UIColor whiteColor];
152 | self.priceLabel.textColor = [UIColor whiteColor];
153 | break;
154 | }
155 | case ZBJCalendarCellStateSelectedEnd: {
156 | // layout
157 | if (![self.priceLabel superview]) {
158 | [self.contentView addSubview:self.priceLabel];
159 | }
160 | self.backgroundView = nil;
161 |
162 | // style
163 | self.contentView.backgroundColor = [UIColor colorWithRed:9.0/255.0 green:9.0/255.0 blue:26.0/255.0 alpha:1.0];
164 | self.dateLabel.textColor = [UIColor whiteColor];
165 | self.priceLabel.textColor = [UIColor whiteColor];
166 |
167 | self.priceLabel.text = @"退房";
168 | break;
169 | }
170 | case ZBJCalendarCellStateSelectedTempEnd: {
171 | // layout
172 | if (![self.priceLabel superview]) {
173 | [self.contentView addSubview:self.priceLabel];
174 | }
175 | self.backgroundView = nil;
176 |
177 | // style
178 | self.contentView.backgroundColor = [UIColor whiteColor];
179 | self.dateLabel.textColor = [UIColor colorWithRed:9.0/255.0 green:9.0/255.0 blue:26.0/255.0 alpha:1.0];
180 | self.priceLabel.textColor = [UIColor colorWithRed:157.0/255.0 green:157.0/255.0 blue:163.0/255.0 alpha:1.0];
181 |
182 | self.priceLabel.text = @"仅退房";
183 | break;
184 | }
185 | case ZBJCalendarCellStateEmpty: {
186 |
187 | self.dateLabel.text = nil;
188 | self.priceLabel.text = nil;
189 | [self.priceLabel removeFromSuperview];
190 | self.backgroundView = nil;
191 | self.contentView.backgroundColor = [UIColor whiteColor];
192 |
193 | break;
194 | }
195 | default: {
196 |
197 | break;
198 | }
199 |
200 | }
201 | [self layoutSubviews];
202 |
203 | }
204 |
205 | #pragma mark - getters
206 | - (UILabel *)dateLabel {
207 | if (!_dateLabel) {
208 | _dateLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), 15)];
209 | _dateLabel.textAlignment = NSTextAlignmentCenter;
210 | _dateLabel.font = [UIFont systemFontOfSize:15];
211 | _dateLabel.textColor = [UIColor darkTextColor];
212 | }
213 | return _dateLabel;
214 | }
215 |
216 | - (UILabel *)priceLabel {
217 | if (!_priceLabel) {
218 | _priceLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.frame), 9)];
219 | _priceLabel.font = [UIFont systemFontOfSize:9];
220 | _priceLabel.textAlignment = NSTextAlignmentCenter;
221 | _priceLabel.textColor = [UIColor colorWithRed:157.0/255.0 green:157.0/255.0 blue:163.0/255.0 alpha:1.0];
222 | }
223 | return _priceLabel;
224 | }
225 |
226 | - (UIImageView *)backgroundImageView {
227 | if (!_backgroundImageView) {
228 | _backgroundImageView = [[UIImageView alloc] initWithFrame:self.contentView.bounds];
229 | _backgroundImageView.image = [UIImage imageNamed:@"unavaible"];
230 | _backgroundImageView.contentMode = UIViewContentModeScaleAspectFill;
231 | }
232 | return _backgroundImageView;
233 | }
234 |
235 |
236 |
237 | @end
238 |
--------------------------------------------------------------------------------
/ZBJCalendar/ZBJCalendar/ZBJCalendarView.h:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJCalendarView.h
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 2/24/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import
10 | #import "ZBJCalendarWeekView.h"
11 |
12 | typedef CF_ENUM(NSInteger, ZBJSelectionMode) {
13 | ZBJSelectionModeDisable = 0, // Can not select
14 | ZBJSelectionModeSingle, // Single selection mode
15 | ZBJSelectionModeMutiple, // Mutile selection mode
16 | };
17 |
18 | typedef CF_ENUM(NSInteger, ZBJCalendarViewHeadStyle) {
19 | ZBJCalendarViewHeadStyleCurrentMonth = 0, // Show current month of the first day.
20 | ZBJCalendarViewHeadStyleCurrentWeek, // Show current week of the first day, the days before current will hiden.
21 | };
22 |
23 | @protocol ZBJCalendarDataSource, ZBJCalendarDelegate;
24 |
25 | /**
26 | * `ZBJCalendarView` provide a convenience way to write a calendar view. The concept of `ZBJCalendarView` is `UICollectionView` or `UITableView`, some properties contains `dataSource` which to used to custom cells or headers and `delegate` which used to handle the display and behaviour of the day cells.
27 | *
28 | * The structure of `ZBJCalendarView` is simple, it contains a `weekView` as public and a `collectionView` as private.
29 | - The `weekView` is an instance of `ZBJCalendarWeekView` that you can implements the methods in `dataSource` about week view.
30 | - The `collectionView` is an instance of `UICollectionView`, the UICollectionView cell correspond the day of the calendar.
31 | *
32 | * The usage of `ZBJCalendarView` is simple, is familiar like `UITableView` or `UICollectionView`
33 | - first, you should point the `firstDate` and `lastDate`,
34 | - second, like `UITableView` or `UICollectionView`, it must registe a cell through `- (void)registerCellClass:(id)clazz withReuseIdentifier:(NSString *)identifier;`,
35 | - finally, conform the `ZBJCalendarDataSource` protocol and must implement `- (void)calendarView:(ZBJCalendarView *)calendarView configureCell:(id)cell forDate:(NSDate *)date;` as `@required`.
36 | *
37 | */
38 | @interface ZBJCalendarView : UIView
39 |
40 | /**
41 | * A reference of `ZBJCalendarDataSource` used to custom calendar day cells.
42 | */
43 | @property (nonatomic, weak) id dataSource;
44 |
45 | /**
46 | * A reference of `ZBJCalendarDelegate` used to handle the calendar day cells's display and behaviours.
47 | */
48 | @property (nonatomic, weak) id delegate;
49 |
50 | /**
51 | * The tow properties `firstDate` and `lastDate` are necessary for calendar.
52 | - `firstDate` is the start date of the calendar
53 | - `lastDate` is the end date of the calendar
54 | */
55 | @property (nonatomic, strong) NSDate *firstDate;
56 | @property (nonatomic, strong) NSDate *lastDate;
57 |
58 | /**
59 | * `weekView` is used to display the week days.
60 | * It's a public property that means you can define the style as you like.
61 | */
62 | @property (nonatomic, strong) ZBJCalendarWeekView *weekView;
63 |
64 | /**
65 | * `ZBJCalendarView` has three selection mode, it's defined as a enum `ZBJSelectionMode`.
66 | * The concept of selection mode is to control the `collectionView`'s `allowsSelection` and `allowsMultipleSelection`.
67 | * Default value is `ZBJSelectionModeRange`
68 | */
69 | @property (nonatomic, assign) ZBJSelectionMode selectionMode;
70 |
71 | /**
72 | * This property used to control whether the calendar view is selectable or not directly.
73 | * As `selectionMode`, it controler the collectionView's `allowsSelection` property.
74 | */
75 | @property (nonatomic, assign) BOOL allowsSelection;
76 |
77 | /**
78 | * This `headStyle` is the style of the current month display style.
79 | */
80 | @property (nonatomic, assign) ZBJCalendarViewHeadStyle headStyle;
81 |
82 | ///-------------------------------
83 | /// @name layout properties
84 | ///-------------------------------
85 |
86 | /**
87 | * The calendarView inner padding.
88 | */
89 | @property (nonatomic, assign) UIEdgeInsets contentInsets;
90 | @property (nonatomic, assign) CGFloat minimumLineSpacing;
91 | @property (nonatomic, assign) CGFloat weekViewHeight;
92 | @property (nonatomic, assign) CGFloat sectionHeaderHeight;
93 | @property (nonatomic, assign) CGFloat sectionFooterHeight;
94 |
95 | /**
96 | * Calendar offset which is not contains contentInset
97 | * `contentOffset.x` = `collectionView.contentOffset.x` + `collectionView.contentInset.left`
98 | * `contentOffset.y` = `collectionView.contentOffset.y` + `collectionView.contentInset.top`
99 | */
100 | @property (nonatomic, assign) CGPoint contentOffset;
101 |
102 | /**
103 | * Calendar content size which is not contains weekHeight in vertical.
104 | */
105 | @property (nonatomic, assign, readonly) CGSize contentSize;
106 |
107 | /**
108 | * In calendar view, the cell width is calculated as by this expression, `cellWidth = (calendar.width - contentInsets.left - contentInsets.right) / 7`
109 | cellWidth is variable with the screen changing,
110 | So, we define a scale to calculate cellHeight is convenient, `cellScale = cellHeight / cellWidth`.
111 | */
112 | @property (nonatomic, assign) CGFloat cellScale;
113 |
114 | /**
115 | * Registe a class for calendar day cell.
116 | *
117 | * @param clazz Calendar day cell, it should be a subclass of `UICollectionViewCell`
118 | * @param identifier The cell's reuse identifier.
119 | */
120 | - (void)registerCellClass:(id)clazz withReuseIdentifier:(NSString *)identifier;
121 |
122 | /**
123 | * This two methods used to registe a class for calendar section header or footer view.
124 | *
125 | * @param clazz Calendar section header or footer view, it should be a subclass of `UICollectionReusableView`
126 | * @param identifier The view's reuse identifier.
127 | */
128 | - (void)registerSectionHeader:(id)clazz withReuseIdentifier:(NSString *)identifier;
129 | - (void)registerSectionFooter:(id)clazz withReuseIdentifier:(NSString *)identifier;
130 |
131 | /**
132 | * Reloads everything from scratch, redisplays visible cells.
133 | */
134 | - (void)reloadData;
135 |
136 | /**
137 | * Get corresponding cell with `date`
138 | *
139 | * @param date
140 | *
141 | * @return The corresponding cell.
142 | */
143 | - (id)cellAtDate:(NSDate *)date;
144 |
145 | /**
146 | * Reload cell with `NSDate` set.
147 | *
148 | * @param dates
149 | */
150 | - (void)reloadItemsAtDates:(NSSet *)dates;
151 |
152 | /**
153 | * Reload month section with `NSDate` set
154 | *
155 | * @param months month element in this set should contains year and month
156 | */
157 | - (void)reloadItemsAtMonths:(NSSet *)months;
158 |
159 | /**
160 | * Set content offset of calendar view
161 | *
162 | * @param contentOffset
163 | * @param animated
164 | */
165 | - (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated;
166 |
167 | @end
168 | /**
169 | * This protocol represents the cell data model object.
170 | * As such, it supplies the cell's information about appearance and data.
171 | */
172 | @protocol ZBJCalendarDataSource
173 |
174 | @required
175 | /**
176 | * This method is used for configure the day cell with current `date`.
177 | * Implementers can setup `date` to cell and custom appearance for cell by this method.
178 | *
179 | * @param calendarView self
180 | * @param cell current reuse cell
181 | * @param date current date
182 | */
183 | - (void)calendarView:(ZBJCalendarView *)calendarView configureCell:(id)cell forDate:(NSDate *)date;
184 |
185 | @optional
186 | /**
187 | * If you registe a section header or footer, you should configure them by them two methods, calendar will provide current `year` and `month` for you.
188 | *
189 | * @param calendarView self
190 | * @param headerView current reuse section header or footer view
191 | * @param firstDateOfMonth & lastDateOfMonth
192 | */
193 | - (void)calendarView:(ZBJCalendarView *)calendarView configureSectionHeaderView:(id)headerView firstDateOfMonth:(NSDate *)firstDateOfMonth;
194 | - (void)calendarView:(ZBJCalendarView *)calendarView configureSectionFooterView:(id)headerView lastDateOfMonth:(NSDate *)lastDateOfMonth;
195 |
196 | /**
197 | * This method is used for configure the cell of the week view with the `weekDay`
198 | *
199 | * @param calendarView self
200 | * @param dayLabel week day label
201 | * @param weekDay current week day
202 | */
203 | - (void)calendarView:(ZBJCalendarView *)calendarView configureWeekDayLabel:(UILabel *)dayLabel atWeekDay:(NSInteger)weekDay;
204 | @end
205 |
206 | @protocol ZBJCalendarDelegate
207 |
208 | @optional
209 | /**
210 | * Return whether the date is selectable
211 | *
212 | * @param calendarView self
213 | * @param date current date
214 | *
215 | * @return selectable of the calendarView cell
216 | */
217 | - (BOOL)calendarView:(ZBJCalendarView *)calendarView shouldSelectDate:(NSDate *)date;
218 |
219 | /**
220 | * Correspond the selection event of the calendarView with current `date`.
221 | *
222 | * @param calendarView self
223 | * @param date current date
224 | */
225 | - (void)calendarView:(ZBJCalendarView *)calendarView didSelectDate:(NSDate *)date ofCell:(id)cell;
226 |
227 | /**
228 | * ScrollView delegate methods
229 | *
230 | * @param scrollView UICollectionView
231 | */
232 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView;
233 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
234 | - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
235 | - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView;
236 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
237 |
238 | @end
239 |
--------------------------------------------------------------------------------
/ZBJCalendar.xcodeproj/xcuserdata/wanggang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
20 |
21 |
22 |
24 |
36 |
37 |
38 |
40 |
52 |
53 |
54 |
56 |
68 |
69 |
70 |
72 |
84 |
85 |
86 |
88 |
100 |
101 |
102 |
104 |
116 |
117 |
118 |
120 |
132 |
133 |
134 |
136 |
148 |
149 |
150 |
152 |
164 |
165 |
166 |
168 |
180 |
181 |
182 |
184 |
196 |
197 |
198 |
200 |
212 |
213 |
214 |
216 |
228 |
229 |
230 |
231 |
232 |
--------------------------------------------------------------------------------
/ZBJCalendar/RangeSelection/complex/ZBJComplexRangeSelectionController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ZBJComplexRangeSelectionController.m
3 | // ZBJCalendar
4 | //
5 | // Created by gumpwang on 3/10/16.
6 | // Copyright © 2016 ZBJ. All rights reserved.
7 | //
8 |
9 | #import "ZBJComplexRangeSelectionController.h"
10 | #import "ZBJCalendar.h"
11 | #import "ZBJComplexRangeSelectionCell.h"
12 | #import "ZBJCalendarSectionHeader.h"
13 | #import "ZBJCalendarSectionFooter.h"
14 |
15 | typedef CF_ENUM(NSInteger, ZBJCalendarSelectedState) {
16 | ZBJCalendarStateSelectedNone,
17 | ZBJCalendarStateSelectedStart,
18 | ZBJCalendarStateSelectedRange,
19 | };
20 |
21 | @interface ZBJComplexRangeSelectionController ()
22 |
23 | @property (nonatomic, strong) ZBJCalendarView *calendarView;
24 |
25 | @property (nonatomic, assign) ZBJCalendarSelectedState selectedState;
26 |
27 | @property (nonatomic, strong) NSMutableSet *tempUnavaibleDates;
28 | @property (nonatomic, strong) NSDate *nearestUnavaibleDate;
29 |
30 | @end
31 |
32 | @implementation ZBJComplexRangeSelectionController
33 |
34 | - (void)viewDidLoad {
35 | [super viewDidLoad];
36 |
37 | self.view.backgroundColor = [UIColor whiteColor];
38 | self.title = [NSString stringWithFormat:@"选择起始日期(至少%ld天)", self.minNights];
39 |
40 | self.tempUnavaibleDates = [[NSMutableSet alloc] init];
41 | self.calendarView.firstDate = self.firstDate;
42 | self.calendarView.lastDate = self.lastDate;
43 |
44 | [self.view addSubview:self.calendarView];
45 | }
46 |
47 | - (void)viewWillAppear:(BOOL)animated {
48 | [super viewWillAppear:animated];
49 | if (self.startDate && self.endDate) {
50 | self.selectedState = ZBJCalendarStateSelectedRange;
51 | } else {
52 | self.selectedState = ZBJCalendarStateSelectedNone;
53 | }
54 | }
55 |
56 |
57 | - (void)didReceiveMemoryWarning {
58 | [super didReceiveMemoryWarning];
59 | }
60 |
61 | - (void)pop {
62 | if (self.delegate && [self.delegate respondsToSelector:@selector(popViewController:startDate:endDate:)]) {
63 | [self.delegate popViewController:self startDate:self.startDate endDate:self.endDate];
64 | }
65 | }
66 |
67 | #pragma mark - private methods
68 | - (ZBJCalendarDate *)offerDateWithDate:(NSDate *)date {
69 | for (ZBJCalendarDate *day in self.dates) {
70 | if ([day.date isEqualToDate:date]) {
71 | return day;
72 | break;
73 | }
74 | }
75 | return nil;
76 | }
77 |
78 | - (void)reset {
79 | self.startDate = nil;
80 | self.endDate = nil;
81 | [self.calendarView reloadData];
82 | self.calendarView.allowsSelection = YES;
83 | }
84 |
85 | // 计算开始日期之后最近的不可选日期
86 | - (NSDate *)findTheNearestUnavaibleDateByStartDate:(NSDate *)date {
87 | NSDate *nextDate = [date dateByAddingTimeInterval:86400.0];
88 | ZBJCalendarDate *theDay = [self offerDateWithDate:nextDate];
89 | if (theDay) {
90 | if (![theDay.available boolValue]) {
91 | return nextDate;
92 | } else {
93 | return [self findTheNearestUnavaibleDateByStartDate:nextDate];
94 | }
95 | }
96 | return nil;
97 | }
98 |
99 |
100 | #pragma mark - ZBJCalendarDelegate
101 | - (BOOL)calendarView:(ZBJCalendarView *)calendarView shouldSelectDate:(NSDate *)date {
102 |
103 | // if (self.selectionMode == ZBJSelectionModeRange) {
104 | if (date) {
105 | // 日期在今天之前
106 | // 先取到当天的最后一秒: xxxx-xx-xx 23:59:59
107 | if ([[date dateByAddingTimeInterval:86400.0 - 1] compare:calendarView.firstDate] == NSOrderedAscending ||
108 | [date compare:calendarView.lastDate] == NSOrderedDescending) {
109 | return NO;
110 | }
111 | switch (self.selectedState) {
112 | case ZBJCalendarStateSelectedStart: {
113 | // self.startDate && !self.endDate && 结束日期 < 起始日期
114 | if ([date compare:self.startDate] == NSOrderedAscending) {
115 | return NO;
116 | }
117 |
118 | // 如果最近的不可选日期等于此日期,那么可选
119 | if ([self.nearestUnavaibleDate isEqualToDate:date]) {
120 | return YES;
121 | }
122 |
123 | // 暂时不可选集合包涵次日期,那么不可选
124 | if ([self.tempUnavaibleDates containsObject:date]) {
125 | return NO;
126 | }
127 |
128 | if (self.nearestUnavaibleDate &&
129 | [date compare:self.nearestUnavaibleDate] == NSOrderedDescending) {
130 | return NO;
131 | }
132 |
133 | // 如果不满足上面的条件,那么根据data中的avaible来判断是否可选
134 | ZBJCalendarDate *day = [self offerDateWithDate:date];
135 | if (day) {
136 | return [day.available boolValue];
137 | }
138 | break;
139 | }
140 | case ZBJCalendarStateSelectedRange: {
141 | // 如果不满足上面的条件,那么根据data中的avaible来判断是否可选
142 | ZBJCalendarDate *day = [self offerDateWithDate:date];
143 | if (day) {
144 | return [day.available boolValue];
145 | }
146 | break;
147 | }
148 | default:
149 | break;
150 | }
151 |
152 | } else {
153 | return NO;
154 | }
155 | // }
156 |
157 | return YES;
158 | }
159 |
160 |
161 | - (void)calendarView:(ZBJCalendarView *)calendarView configureCell:(ZBJComplexRangeSelectionCell *)cell forDate:(NSDate *)date {
162 |
163 | cell.day = date;
164 |
165 | NSNumber *price = nil;
166 | ZBJCalendarCellState cellState = -1;
167 |
168 | if (date) {
169 | // 如果小于起始日期或大于结束日期,那么disabled
170 | if ([[date dateByAddingTimeInterval:86400.0 - 1] compare:calendarView.firstDate] == NSOrderedAscending ||
171 | [date compare:calendarView.lastDate] == NSOrderedDescending) { //大于最后一天
172 |
173 | cellState = ZBJCalendarCellStateDisabled;
174 | } else {
175 |
176 | ZBJCalendarDate *day = [self offerDateWithDate:date];
177 | price = day.price;
178 |
179 | BOOL isAvaible = day.available.boolValue;
180 |
181 | switch (self.selectedState) {
182 | case ZBJCalendarStateSelectedStart: {
183 |
184 | if ([[date dateByAddingTimeInterval:86400.0 - 1] compare:self.startDate] == NSOrderedAscending &&
185 | [date compare:calendarView.firstDate] == NSOrderedDescending) {
186 |
187 | if (isAvaible) {
188 | cellState = ZBJCalendarCellStateAvaibleDisabled;
189 | } else {
190 | cellState = ZBJCalendarCellStateUnavaible;
191 | }
192 | } else if ([self.startDate isEqualToDate:date]) {
193 | cellState = ZBJCalendarCellStateSelectedStart;
194 | } else if ([self.tempUnavaibleDates containsObject:date]) {
195 | cellState = ZBJCalendarCellStateAvaibleDisabled;
196 | } else if (self.nearestUnavaibleDate && [self.nearestUnavaibleDate isEqualToDate:date]) {
197 | cellState = ZBJCalendarCellStateSelectedTempEnd;
198 | } else if (self.nearestUnavaibleDate &&
199 | [date compare:self.nearestUnavaibleDate] == NSOrderedDescending &&
200 | [[date dateByAddingTimeInterval:86400.0 - 1] compare:calendarView.lastDate] == NSOrderedAscending
201 | ) {
202 | if (isAvaible) {
203 | cellState = ZBJCalendarCellStateAvaibleDisabled;
204 | } else {
205 | cellState = ZBJCalendarCellStateUnavaible;
206 | }
207 | } else {
208 |
209 | if (isAvaible) {
210 | cellState = ZBJCalendarCellStateAvaible;
211 | } else {
212 | cellState = ZBJCalendarCellStateUnavaible;
213 | }
214 | }
215 |
216 | break;
217 | }
218 | case ZBJCalendarStateSelectedRange: {
219 |
220 | if ([self.startDate isEqualToDate:date]) {
221 | cellState = ZBJCalendarCellStateSelectedStart;
222 | } else if ([self.endDate isEqualToDate:date]) {
223 | cellState = ZBJCalendarCellStateSelectedEnd;
224 | } else if (self.startDate && self.endDate &&
225 | [[date dateByAddingTimeInterval:86400.0 - 1] compare:self.endDate] == NSOrderedAscending &&
226 | [date compare:self.startDate] == NSOrderedDescending) {
227 |
228 | cellState = ZBJCalendarCellStateSelectedMiddle;
229 | } else {
230 | if (isAvaible) {
231 | cellState = ZBJCalendarCellStateAvaible;
232 | } else {
233 | cellState = ZBJCalendarCellStateUnavaible;
234 | }
235 | }
236 | break;
237 | }
238 | default: {
239 |
240 | if (isAvaible) {
241 | cellState = ZBJCalendarCellStateAvaible;
242 | } else {
243 | cellState = ZBJCalendarCellStateUnavaible;
244 | }
245 | break;
246 | }
247 |
248 |
249 | }
250 | }
251 | } else {
252 | cellState = ZBJCalendarCellStateEmpty;
253 | }
254 |
255 | cell.price = price;
256 | cell.cellState = cellState;
257 |
258 | }
259 | - (void)calendarView:(ZBJCalendarView *)calendarView didSelectDate:(NSDate *)date ofCell:(id)cell {
260 | if (calendarView.selectionMode == ZBJSelectionModeMutiple) {
261 | if (date) {
262 | if (!self.startDate) {
263 | self.startDate = date;
264 | self.selectedState = ZBJCalendarStateSelectedStart;
265 | } else if (!self.endDate) {
266 |
267 | if ([self.startDate isEqualToDate:date]) {
268 | self.selectedState = ZBJCalendarStateSelectedNone;
269 | return;
270 | }
271 |
272 | self.endDate = date;
273 | self.selectedState = ZBJCalendarStateSelectedRange;
274 |
275 | // pop self
276 | [self performSelector:@selector(pop) withObject:nil afterDelay:0.4];
277 | } else {
278 | self.startDate = date;
279 | self.selectedState = ZBJCalendarStateSelectedStart;
280 | }
281 | }
282 | }
283 | }
284 |
285 | - (void)calendarView:(ZBJCalendarView *)calendarView configureSectionHeaderView:(ZBJCalendarSectionHeader *)headerView firstDateOfMonth:(NSDate *)firstDateOfMonth {
286 | NSCalendar *calendar = [NSDate gregorianCalendar];
287 | NSDateComponents *components = [calendar components:NSCalendarUnitYear | NSCalendarUnitMonth fromDate:firstDateOfMonth];
288 | headerView.year = components.year;
289 | headerView.month = components.month;
290 | }
291 |
292 | #pragma mark - getters
293 | - (ZBJCalendarView *)calendarView {
294 | if (!_calendarView) {
295 | _calendarView = [[ZBJCalendarView alloc] initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame) - 64)];
296 | _calendarView.delegate = self;
297 | _calendarView.dataSource = self;
298 | [_calendarView registerCellClass:[ZBJComplexRangeSelectionCell class] withReuseIdentifier:@"cell"];
299 | [_calendarView registerSectionHeader:[ZBJCalendarSectionHeader class] withReuseIdentifier:@"sectionHeader"];
300 | [_calendarView registerSectionFooter:[ZBJCalendarSectionFooter class] withReuseIdentifier:@"sectionFooter"];
301 | _calendarView.contentInsets = UIEdgeInsetsMake(0, 14, 0, 14);
302 | _calendarView.sectionHeaderHeight = 52;
303 | _calendarView.sectionFooterHeight = 13;
304 | _calendarView.minimumLineSpacing = 0.5;
305 | _calendarView.cellScale = 100.0 / 104.0;
306 | }
307 | return _calendarView;
308 | }
309 |
310 |
311 | #pragma mark - setters
312 | - (void)setSelectedState:(ZBJCalendarSelectedState)selectedState {
313 | _selectedState = selectedState;
314 | switch (_selectedState) {
315 | case ZBJCalendarStateSelectedNone: {
316 |
317 | self.title = [NSString stringWithFormat:@"选择起始日期(至少%ld天)", self.minNights];
318 |
319 | [self reset];
320 | break;
321 | }
322 | case ZBJCalendarStateSelectedStart: {
323 |
324 | self.endDate = nil;
325 | [self.tempUnavaibleDates removeAllObjects];
326 | self.nearestUnavaibleDate = nil;
327 |
328 | [self.calendarView reloadData];
329 |
330 | // calculate avaible `endDate` based `startDate`.
331 | // - the days in `minNights` from `startDate` has days unavaible.
332 | for (int i = 1; i < self.minNights; i++) {
333 | NSDate *theDate = [self.startDate dateByAddingTimeInterval:(i * 24 * 60 * 60)];
334 | // find the data about `theDate` and deal.
335 | ZBJCalendarDate *day = [self offerDateWithDate:theDate];
336 | if (!day.available.boolValue) {
337 | self.calendarView.allowsSelection = NO;
338 | [self performSelector:@selector(reset) withObject:nil afterDelay:0.8];
339 | return;
340 | }
341 | }
342 |
343 | self.title = @"选择退房日期";
344 |
345 | // - set the day between and `startDate` and `minNights` unavaible.
346 | for (int i = 1; i < self.minNights; i++) {
347 | NSDate *theDate = [self.startDate dateByAddingTimeInterval:(i * 24 * 60 * 60)];
348 | [self.tempUnavaibleDates addObject:theDate];
349 | }
350 | // - 计算起始日期之后最近的不可选日期
351 | self.nearestUnavaibleDate = [self findTheNearestUnavaibleDateByStartDate:self.startDate];
352 | [self.calendarView reloadData];
353 | break;
354 | }
355 | case ZBJCalendarStateSelectedRange: {
356 | [self.calendarView reloadData];
357 | self.title = [NSString stringWithFormat:@"选择起始日期(至少%ld天)", self.minNights];
358 | break;
359 | }
360 | default:
361 | break;
362 | }
363 | }
364 | @end
365 |
--------------------------------------------------------------------------------
/ZBJCalendar/Model/calendar_dates.json:
--------------------------------------------------------------------------------
1 | {"start_date":"2016-03-10","end_date":"2017-03-10","dates":[{"date":"2016-03-10","available":false,"price":1000},{"date":"2016-03-11","available":false,"price":1099},{"date":"2016-03-12","available":false,"price":1092},{"date":"2016-03-13","available":false,"price":1092},{"date":"2016-03-14","available":false,"price":992},{"date":"2016-03-15","available":false,"price":992},{"date":"2016-03-16","available":true,"price":1096},{"date":"2016-03-17","available":false,"price":1130},{"date":"2016-03-18","available":false,"price":1130},{"date":"2016-03-19","available":false,"price":1130},{"date":"2016-03-20","available":false,"price":809},{"date":"2016-03-21","available":false,"price":809},{"date":"2016-03-22","available":false,"price":809},{"date":"2016-03-23","available":false,"price":910},{"date":"2016-03-24","available":false,"price":1021},{"date":"2016-03-25","available":false,"price":1021},{"date":"2016-03-26","available":false,"price":1021},{"date":"2016-03-27","available":false,"price":1021},{"date":"2016-03-28","available":false,"price":1074},{"date":"2016-03-29","available":false,"price":810},{"date":"2016-03-30","available":false,"price":810},{"date":"2016-03-31","available":false,"price":810},{"date":"2016-04-01","available":true,"price":1096},{"date":"2016-04-02","available":false,"price":809},{"date":"2016-04-03","available":false,"price":809},{"date":"2016-04-04","available":false,"price":809},{"date":"2016-04-05","available":false,"price":809},{"date":"2016-04-06","available":false,"price":809},{"date":"2016-04-07","available":false,"price":809},{"date":"2016-04-08","available":false,"price":809},{"date":"2016-04-09","available":false,"price":809},{"date":"2016-04-10","available":false,"price":809},{"date":"2016-04-11","available":false,"price":809},{"date":"2016-04-12","available":true,"price":1298},{"date":"2016-04-13","available":false,"price":1305},{"date":"2016-04-14","available":false,"price":1305},{"date":"2016-04-15","available":false,"price":1638},{"date":"2016-04-16","available":false,"price":1638},{"date":"2016-04-17","available":false,"price":1229},{"date":"2016-04-18","available":false,"price":1210},{"date":"2016-04-19","available":false,"price":1210},{"date":"2016-04-20","available":false,"price":807},{"date":"2016-04-21","available":false,"price":807},{"date":"2016-04-22","available":true,"price":1096},{"date":"2016-04-23","available":false,"price":1132},{"date":"2016-04-24","available":false,"price":1132},{"date":"2016-04-25","available":false,"price":1132},{"date":"2016-04-26","available":false,"price":1132},{"date":"2016-04-27","available":false,"price":1132},{"date":"2016-04-28","available":true,"price":1096},{"date":"2016-04-29","available":true,"price":1096},{"date":"2016-04-30","available":false,"price":816},{"date":"2016-05-01","available":false,"price":1440},{"date":"2016-05-02","available":false,"price":1440},{"date":"2016-05-03","available":true,"price":1096},{"date":"2016-05-04","available":true,"price":1096},{"date":"2016-05-05","available":true,"price":1096},{"date":"2016-05-06","available":true,"price":1096},{"date":"2016-05-07","available":true,"price":1096},{"date":"2016-05-08","available":true,"price":1096},{"date":"2016-05-09","available":true,"price":1096},{"date":"2016-05-10","available":true,"price":1096},{"date":"2016-05-11","available":true,"price":1096},{"date":"2016-05-12","available":true,"price":1096},{"date":"2016-05-13","available":true,"price":1096},{"date":"2016-05-14","available":true,"price":1096},{"date":"2016-05-15","available":true,"price":1096},{"date":"2016-05-16","available":true,"price":1096},{"date":"2016-05-17","available":true,"price":1096},{"date":"2016-05-18","available":true,"price":1096},{"date":"2016-05-19","available":true,"price":1096},{"date":"2016-05-20","available":true,"price":1096},{"date":"2016-05-21","available":true,"price":1096},{"date":"2016-05-22","available":true,"price":1096},{"date":"2016-05-23","available":true,"price":1096},{"date":"2016-05-24","available":true,"price":1096},{"date":"2016-05-25","available":true,"price":1096},{"date":"2016-05-26","available":true,"price":1096},{"date":"2016-05-27","available":true,"price":1096},{"date":"2016-05-28","available":true,"price":1096},{"date":"2016-05-29","available":true,"price":1096},{"date":"2016-05-30","available":true,"price":1096},{"date":"2016-05-31","available":true,"price":1096},{"date":"2016-06-01","available":true,"price":1096},{"date":"2016-06-02","available":true,"price":1096},{"date":"2016-06-03","available":true,"price":1096},{"date":"2016-06-04","available":true,"price":1096},{"date":"2016-06-05","available":true,"price":1096},{"date":"2016-06-06","available":true,"price":1096},{"date":"2016-06-07","available":true,"price":1096},{"date":"2016-06-08","available":true,"price":1096},{"date":"2016-06-09","available":true,"price":1096},{"date":"2016-06-10","available":true,"price":1096},{"date":"2016-06-11","available":true,"price":1096},{"date":"2016-06-12","available":true,"price":1096},{"date":"2016-06-13","available":true,"price":1096},{"date":"2016-06-14","available":true,"price":1096},{"date":"2016-06-15","available":true,"price":1096},{"date":"2016-06-16","available":true,"price":1096},{"date":"2016-06-17","available":false,"price":1095},{"date":"2016-06-18","available":false,"price":1095},{"date":"2016-06-19","available":false,"price":1095},{"date":"2016-06-20","available":true,"price":1096},{"date":"2016-06-21","available":true,"price":1096},{"date":"2016-06-22","available":false,"price":1464},{"date":"2016-06-23","available":false,"price":1464},{"date":"2016-06-24","available":false,"price":1464},{"date":"2016-06-25","available":true,"price":1096},{"date":"2016-06-26","available":true,"price":1096},{"date":"2016-06-27","available":true,"price":1096},{"date":"2016-06-28","available":true,"price":1096},{"date":"2016-06-29","available":true,"price":1096},{"date":"2016-06-30","available":true,"price":1096},{"date":"2016-07-01","available":true,"price":2061},{"date":"2016-07-02","available":true,"price":2061},{"date":"2016-07-03","available":true,"price":2061},{"date":"2016-07-04","available":true,"price":2061},{"date":"2016-07-05","available":true,"price":2061},{"date":"2016-07-06","available":true,"price":2061},{"date":"2016-07-07","available":true,"price":2061},{"date":"2016-07-08","available":true,"price":2061},{"date":"2016-07-09","available":true,"price":2061},{"date":"2016-07-10","available":true,"price":2061},{"date":"2016-07-11","available":true,"price":2061},{"date":"2016-07-12","available":true,"price":2061},{"date":"2016-07-13","available":true,"price":2061},{"date":"2016-07-14","available":true,"price":2061},{"date":"2016-07-15","available":true,"price":2061},{"date":"2016-07-16","available":true,"price":2061},{"date":"2016-07-17","available":true,"price":2061},{"date":"2016-07-18","available":true,"price":2061},{"date":"2016-07-19","available":true,"price":2061},{"date":"2016-07-20","available":true,"price":2061},{"date":"2016-07-21","available":true,"price":2061},{"date":"2016-07-22","available":true,"price":2061},{"date":"2016-07-23","available":true,"price":2061},{"date":"2016-07-24","available":true,"price":2061},{"date":"2016-07-25","available":true,"price":2061},{"date":"2016-07-26","available":true,"price":2061},{"date":"2016-07-27","available":true,"price":2061},{"date":"2016-07-28","available":true,"price":2061},{"date":"2016-07-29","available":true,"price":2061},{"date":"2016-07-30","available":true,"price":2061},{"date":"2016-07-31","available":true,"price":2061},{"date":"2016-08-01","available":false,"price":2093},{"date":"2016-08-02","available":false,"price":2093},{"date":"2016-08-03","available":false,"price":2093},{"date":"2016-08-04","available":false,"price":2093},{"date":"2016-08-05","available":false,"price":2093},{"date":"2016-08-06","available":false,"price":2093},{"date":"2016-08-07","available":false,"price":2093},{"date":"2016-08-08","available":false,"price":2093},{"date":"2016-08-09","available":false,"price":2093},{"date":"2016-08-10","available":false,"price":2093},{"date":"2016-08-11","available":false,"price":2093},{"date":"2016-08-12","available":false,"price":2093},{"date":"2016-08-13","available":false,"price":2093},{"date":"2016-08-14","available":false,"price":2093},{"date":"2016-08-15","available":false,"price":2093},{"date":"2016-08-16","available":false,"price":2093},{"date":"2016-08-17","available":false,"price":2093},{"date":"2016-08-18","available":false,"price":2093},{"date":"2016-08-19","available":false,"price":2093},{"date":"2016-08-20","available":false,"price":2094},{"date":"2016-08-21","available":true,"price":2061},{"date":"2016-08-22","available":true,"price":2061},{"date":"2016-08-23","available":true,"price":2061},{"date":"2016-08-24","available":true,"price":2061},{"date":"2016-08-25","available":true,"price":2061},{"date":"2016-08-26","available":true,"price":2061},{"date":"2016-08-27","available":true,"price":2061},{"date":"2016-08-28","available":true,"price":2061},{"date":"2016-08-29","available":true,"price":2061},{"date":"2016-08-30","available":true,"price":2061},{"date":"2016-08-31","available":true,"price":2061},{"date":"2016-09-01","available":true,"price":1096},{"date":"2016-09-02","available":true,"price":1096},{"date":"2016-09-03","available":true,"price":1096},{"date":"2016-09-04","available":true,"price":1096},{"date":"2016-09-05","available":true,"price":1096},{"date":"2016-09-06","available":true,"price":1096},{"date":"2016-09-07","available":true,"price":1096},{"date":"2016-09-08","available":true,"price":1096},{"date":"2016-09-09","available":true,"price":1096},{"date":"2016-09-10","available":true,"price":1096},{"date":"2016-09-11","available":true,"price":1096},{"date":"2016-09-12","available":true,"price":1096},{"date":"2016-09-13","available":true,"price":1096},{"date":"2016-09-14","available":true,"price":1096},{"date":"2016-09-15","available":true,"price":1096},{"date":"2016-09-16","available":true,"price":1096},{"date":"2016-09-17","available":true,"price":1096},{"date":"2016-09-18","available":true,"price":1096},{"date":"2016-09-19","available":true,"price":1096},{"date":"2016-09-20","available":true,"price":1096},{"date":"2016-09-21","available":true,"price":1096},{"date":"2016-09-22","available":true,"price":1096},{"date":"2016-09-23","available":true,"price":1096},{"date":"2016-09-24","available":true,"price":1096},{"date":"2016-09-25","available":true,"price":1096},{"date":"2016-09-26","available":true,"price":1096},{"date":"2016-09-27","available":true,"price":1096},{"date":"2016-09-28","available":true,"price":1096},{"date":"2016-09-29","available":true,"price":1096},{"date":"2016-09-30","available":true,"price":1096},{"date":"2016-10-01","available":true,"price":1096},{"date":"2016-10-02","available":true,"price":1096},{"date":"2016-10-03","available":true,"price":1096},{"date":"2016-10-04","available":true,"price":1096},{"date":"2016-10-05","available":true,"price":1096},{"date":"2016-10-06","available":true,"price":1096},{"date":"2016-10-07","available":true,"price":1096},{"date":"2016-10-08","available":true,"price":1096},{"date":"2016-10-09","available":true,"price":1096},{"date":"2016-10-10","available":true,"price":1096},{"date":"2016-10-11","available":true,"price":1096},{"date":"2016-10-12","available":true,"price":1096},{"date":"2016-10-13","available":true,"price":1096},{"date":"2016-10-14","available":true,"price":1096},{"date":"2016-10-15","available":true,"price":1096},{"date":"2016-10-16","available":true,"price":1096},{"date":"2016-10-17","available":true,"price":1096},{"date":"2016-10-18","available":true,"price":1096},{"date":"2016-10-19","available":true,"price":1096},{"date":"2016-10-20","available":true,"price":1096},{"date":"2016-10-21","available":true,"price":1096},{"date":"2016-10-22","available":true,"price":1096},{"date":"2016-10-23","available":true,"price":1096},{"date":"2016-10-24","available":true,"price":1096},{"date":"2016-10-25","available":true,"price":1096},{"date":"2016-10-26","available":true,"price":1096},{"date":"2016-10-27","available":true,"price":1096},{"date":"2016-10-28","available":true,"price":1096},{"date":"2016-10-29","available":true,"price":1096},{"date":"2016-10-30","available":true,"price":1096},{"date":"2016-10-31","available":true,"price":1096},{"date":"2016-11-01","available":true,"price":1096},{"date":"2016-11-02","available":true,"price":1096},{"date":"2016-11-03","available":true,"price":1096},{"date":"2016-11-04","available":true,"price":1096},{"date":"2016-11-05","available":true,"price":1096},{"date":"2016-11-06","available":true,"price":1096},{"date":"2016-11-07","available":true,"price":1096},{"date":"2016-11-08","available":true,"price":1096},{"date":"2016-11-09","available":true,"price":1096},{"date":"2016-11-10","available":true,"price":1096},{"date":"2016-11-11","available":true,"price":1096},{"date":"2016-11-12","available":true,"price":1096},{"date":"2016-11-13","available":true,"price":1096},{"date":"2016-11-14","available":true,"price":1096},{"date":"2016-11-15","available":true,"price":1096},{"date":"2016-11-16","available":true,"price":1096},{"date":"2016-11-17","available":true,"price":1096},{"date":"2016-11-18","available":true,"price":1096},{"date":"2016-11-19","available":true,"price":1096},{"date":"2016-11-20","available":true,"price":1096},{"date":"2016-11-21","available":true,"price":1096},{"date":"2016-11-22","available":true,"price":1096},{"date":"2016-11-23","available":true,"price":1096},{"date":"2016-11-24","available":true,"price":1096},{"date":"2016-11-25","available":true,"price":1096},{"date":"2016-11-26","available":true,"price":1096},{"date":"2016-11-27","available":true,"price":1096},{"date":"2016-11-28","available":true,"price":1096},{"date":"2016-11-29","available":true,"price":1096},{"date":"2016-11-30","available":true,"price":1096},{"date":"2016-12-01","available":true,"price":1096},{"date":"2016-12-02","available":true,"price":1096},{"date":"2016-12-03","available":true,"price":1096},{"date":"2016-12-04","available":true,"price":1096},{"date":"2016-12-05","available":true,"price":1096},{"date":"2016-12-06","available":true,"price":1096},{"date":"2016-12-07","available":true,"price":1096},{"date":"2016-12-08","available":true,"price":1096},{"date":"2016-12-09","available":true,"price":1096},{"date":"2016-12-10","available":true,"price":1096},{"date":"2016-12-11","available":true,"price":1096},{"date":"2016-12-12","available":true,"price":1096},{"date":"2016-12-13","available":true,"price":1096},{"date":"2016-12-14","available":true,"price":1096},{"date":"2016-12-15","available":true,"price":2426},{"date":"2016-12-16","available":true,"price":2426},{"date":"2016-12-17","available":true,"price":2426},{"date":"2016-12-18","available":true,"price":2426},{"date":"2016-12-19","available":true,"price":2426},{"date":"2016-12-20","available":true,"price":2426},{"date":"2016-12-21","available":true,"price":2426},{"date":"2016-12-22","available":true,"price":2426},{"date":"2016-12-23","available":true,"price":2426},{"date":"2016-12-24","available":true,"price":2426},{"date":"2016-12-25","available":true,"price":2426},{"date":"2016-12-26","available":false,"price":1126},{"date":"2016-12-27","available":false,"price":1126},{"date":"2016-12-28","available":false,"price":1126},{"date":"2016-12-29","available":false,"price":1126},{"date":"2016-12-30","available":false,"price":1126},{"date":"2016-12-31","available":false,"price":1126},{"date":"2017-01-01","available":false,"price":1126},{"date":"2017-01-02","available":false,"price":1126},{"date":"2017-01-03","available":false,"price":1126},{"date":"2017-01-04","available":false,"price":1126},{"date":"2017-01-05","available":true,"price":2426},{"date":"2017-01-06","available":true,"price":2426},{"date":"2017-01-07","available":true,"price":2426},{"date":"2017-01-08","available":true,"price":2426},{"date":"2017-01-09","available":true,"price":2426},{"date":"2017-01-10","available":true,"price":2426},{"date":"2017-01-11","available":true,"price":2426},{"date":"2017-01-12","available":true,"price":2426},{"date":"2017-01-13","available":true,"price":2426},{"date":"2017-01-14","available":true,"price":2426},{"date":"2017-01-15","available":true,"price":2426},{"date":"2017-01-16","available":true,"price":2426},{"date":"2017-01-17","available":true,"price":2426},{"date":"2017-01-18","available":true,"price":2426},{"date":"2017-01-19","available":true,"price":2426},{"date":"2017-01-20","available":true,"price":2426},{"date":"2017-01-21","available":true,"price":2426},{"date":"2017-01-22","available":true,"price":2426},{"date":"2017-01-23","available":true,"price":2426},{"date":"2017-01-24","available":true,"price":2426},{"date":"2017-01-25","available":true,"price":2426},{"date":"2017-01-26","available":true,"price":2426},{"date":"2017-01-27","available":true,"price":2426},{"date":"2017-01-28","available":true,"price":2426},{"date":"2017-01-29","available":true,"price":1615},{"date":"2017-01-30","available":true,"price":1615},{"date":"2017-01-31","available":true,"price":1615},{"date":"2017-02-01","available":true,"price":1615},{"date":"2017-02-02","available":true,"price":1615},{"date":"2017-02-03","available":true,"price":1615},{"date":"2017-02-04","available":true,"price":1615},{"date":"2017-02-05","available":true,"price":1615},{"date":"2017-02-06","available":true,"price":1615},{"date":"2017-02-07","available":true,"price":1615},{"date":"2017-02-08","available":true,"price":1615},{"date":"2017-02-09","available":true,"price":1615},{"date":"2017-02-10","available":true,"price":1615},{"date":"2017-02-11","available":true,"price":1615},{"date":"2017-02-12","available":true,"price":1615},{"date":"2017-02-13","available":true,"price":1615},{"date":"2017-02-14","available":true,"price":1615},{"date":"2017-02-15","available":true,"price":1615},{"date":"2017-02-16","available":true,"price":1615},{"date":"2017-02-17","available":true,"price":1615},{"date":"2017-02-18","available":true,"price":1615},{"date":"2017-02-19","available":true,"price":1615},{"date":"2017-02-20","available":true,"price":1615},{"date":"2017-02-21","available":true,"price":1615},{"date":"2017-02-22","available":true,"price":1615},{"date":"2017-02-23","available":true,"price":1615},{"date":"2017-02-24","available":true,"price":1615},{"date":"2017-02-25","available":true,"price":1615},{"date":"2017-02-26","available":true,"price":1615},{"date":"2017-02-27","available":true,"price":1615},{"date":"2017-02-28","available":true,"price":1615},{"date":"2017-03-01","available":true,"price":1615},{"date":"2017-03-02","available":true,"price":1615},{"date":"2017-03-03","available":true,"price":1615},{"date":"2017-03-04","available":true,"price":1615},{"date":"2017-03-05","available":true,"price":1615},{"date":"2017-03-06","available":true,"price":1615},{"date":"2017-03-07","available":true,"price":1615},{"date":"2017-03-08","available":true,"price":1615},{"date":"2017-03-09","available":true,"price":1615},{"date":"2017-03-10","available":true,"price":1615}]}
2 |
--------------------------------------------------------------------------------
/calendar_dates.json:
--------------------------------------------------------------------------------
1 | {"offer_id":17313,"start_date":"2016-03-10","end_date":"2017-03-10","dates":[{"date":"2016-03-10","available":false,"price":1000},{"date":"2016-03-11","available":false,"price":1099},{"date":"2016-03-12","available":false,"price":1092},{"date":"2016-03-13","available":false,"price":1092},{"date":"2016-03-14","available":false,"price":992},{"date":"2016-03-15","available":false,"price":992},{"date":"2016-03-16","available":true,"price":1096},{"date":"2016-03-17","available":false,"price":1130},{"date":"2016-03-18","available":false,"price":1130},{"date":"2016-03-19","available":false,"price":1130},{"date":"2016-03-20","available":false,"price":809},{"date":"2016-03-21","available":false,"price":809},{"date":"2016-03-22","available":false,"price":809},{"date":"2016-03-23","available":false,"price":910},{"date":"2016-03-24","available":false,"price":1021},{"date":"2016-03-25","available":false,"price":1021},{"date":"2016-03-26","available":false,"price":1021},{"date":"2016-03-27","available":false,"price":1021},{"date":"2016-03-28","available":false,"price":1074},{"date":"2016-03-29","available":false,"price":810},{"date":"2016-03-30","available":false,"price":810},{"date":"2016-03-31","available":false,"price":810},{"date":"2016-04-01","available":true,"price":1096},{"date":"2016-04-02","available":false,"price":809},{"date":"2016-04-03","available":false,"price":809},{"date":"2016-04-04","available":false,"price":809},{"date":"2016-04-05","available":false,"price":809},{"date":"2016-04-06","available":false,"price":809},{"date":"2016-04-07","available":false,"price":809},{"date":"2016-04-08","available":false,"price":809},{"date":"2016-04-09","available":false,"price":809},{"date":"2016-04-10","available":false,"price":809},{"date":"2016-04-11","available":false,"price":809},{"date":"2016-04-12","available":true,"price":1298},{"date":"2016-04-13","available":false,"price":1305},{"date":"2016-04-14","available":false,"price":1305},{"date":"2016-04-15","available":false,"price":1638},{"date":"2016-04-16","available":false,"price":1638},{"date":"2016-04-17","available":false,"price":1229},{"date":"2016-04-18","available":false,"price":1210},{"date":"2016-04-19","available":false,"price":1210},{"date":"2016-04-20","available":false,"price":807},{"date":"2016-04-21","available":false,"price":807},{"date":"2016-04-22","available":true,"price":1096},{"date":"2016-04-23","available":false,"price":1132},{"date":"2016-04-24","available":false,"price":1132},{"date":"2016-04-25","available":false,"price":1132},{"date":"2016-04-26","available":false,"price":1132},{"date":"2016-04-27","available":false,"price":1132},{"date":"2016-04-28","available":true,"price":1096},{"date":"2016-04-29","available":true,"price":1096},{"date":"2016-04-30","available":false,"price":816},{"date":"2016-05-01","available":false,"price":1440},{"date":"2016-05-02","available":false,"price":1440},{"date":"2016-05-03","available":true,"price":1096},{"date":"2016-05-04","available":true,"price":1096},{"date":"2016-05-05","available":true,"price":1096},{"date":"2016-05-06","available":true,"price":1096},{"date":"2016-05-07","available":true,"price":1096},{"date":"2016-05-08","available":true,"price":1096},{"date":"2016-05-09","available":true,"price":1096},{"date":"2016-05-10","available":true,"price":1096},{"date":"2016-05-11","available":true,"price":1096},{"date":"2016-05-12","available":true,"price":1096},{"date":"2016-05-13","available":true,"price":1096},{"date":"2016-05-14","available":true,"price":1096},{"date":"2016-05-15","available":true,"price":1096},{"date":"2016-05-16","available":true,"price":1096},{"date":"2016-05-17","available":true,"price":1096},{"date":"2016-05-18","available":true,"price":1096},{"date":"2016-05-19","available":true,"price":1096},{"date":"2016-05-20","available":true,"price":1096},{"date":"2016-05-21","available":true,"price":1096},{"date":"2016-05-22","available":true,"price":1096},{"date":"2016-05-23","available":true,"price":1096},{"date":"2016-05-24","available":true,"price":1096},{"date":"2016-05-25","available":true,"price":1096},{"date":"2016-05-26","available":true,"price":1096},{"date":"2016-05-27","available":true,"price":1096},{"date":"2016-05-28","available":true,"price":1096},{"date":"2016-05-29","available":true,"price":1096},{"date":"2016-05-30","available":true,"price":1096},{"date":"2016-05-31","available":true,"price":1096},{"date":"2016-06-01","available":true,"price":1096},{"date":"2016-06-02","available":true,"price":1096},{"date":"2016-06-03","available":true,"price":1096},{"date":"2016-06-04","available":true,"price":1096},{"date":"2016-06-05","available":true,"price":1096},{"date":"2016-06-06","available":true,"price":1096},{"date":"2016-06-07","available":true,"price":1096},{"date":"2016-06-08","available":true,"price":1096},{"date":"2016-06-09","available":true,"price":1096},{"date":"2016-06-10","available":true,"price":1096},{"date":"2016-06-11","available":true,"price":1096},{"date":"2016-06-12","available":true,"price":1096},{"date":"2016-06-13","available":true,"price":1096},{"date":"2016-06-14","available":true,"price":1096},{"date":"2016-06-15","available":true,"price":1096},{"date":"2016-06-16","available":true,"price":1096},{"date":"2016-06-17","available":false,"price":1095},{"date":"2016-06-18","available":false,"price":1095},{"date":"2016-06-19","available":false,"price":1095},{"date":"2016-06-20","available":true,"price":1096},{"date":"2016-06-21","available":true,"price":1096},{"date":"2016-06-22","available":false,"price":1464},{"date":"2016-06-23","available":false,"price":1464},{"date":"2016-06-24","available":false,"price":1464},{"date":"2016-06-25","available":true,"price":1096},{"date":"2016-06-26","available":true,"price":1096},{"date":"2016-06-27","available":true,"price":1096},{"date":"2016-06-28","available":true,"price":1096},{"date":"2016-06-29","available":true,"price":1096},{"date":"2016-06-30","available":true,"price":1096},{"date":"2016-07-01","available":true,"price":2061},{"date":"2016-07-02","available":true,"price":2061},{"date":"2016-07-03","available":true,"price":2061},{"date":"2016-07-04","available":true,"price":2061},{"date":"2016-07-05","available":true,"price":2061},{"date":"2016-07-06","available":true,"price":2061},{"date":"2016-07-07","available":true,"price":2061},{"date":"2016-07-08","available":true,"price":2061},{"date":"2016-07-09","available":true,"price":2061},{"date":"2016-07-10","available":true,"price":2061},{"date":"2016-07-11","available":true,"price":2061},{"date":"2016-07-12","available":true,"price":2061},{"date":"2016-07-13","available":true,"price":2061},{"date":"2016-07-14","available":true,"price":2061},{"date":"2016-07-15","available":true,"price":2061},{"date":"2016-07-16","available":true,"price":2061},{"date":"2016-07-17","available":true,"price":2061},{"date":"2016-07-18","available":true,"price":2061},{"date":"2016-07-19","available":true,"price":2061},{"date":"2016-07-20","available":true,"price":2061},{"date":"2016-07-21","available":true,"price":2061},{"date":"2016-07-22","available":true,"price":2061},{"date":"2016-07-23","available":true,"price":2061},{"date":"2016-07-24","available":true,"price":2061},{"date":"2016-07-25","available":true,"price":2061},{"date":"2016-07-26","available":true,"price":2061},{"date":"2016-07-27","available":true,"price":2061},{"date":"2016-07-28","available":true,"price":2061},{"date":"2016-07-29","available":true,"price":2061},{"date":"2016-07-30","available":true,"price":2061},{"date":"2016-07-31","available":true,"price":2061},{"date":"2016-08-01","available":false,"price":2093},{"date":"2016-08-02","available":false,"price":2093},{"date":"2016-08-03","available":false,"price":2093},{"date":"2016-08-04","available":false,"price":2093},{"date":"2016-08-05","available":false,"price":2093},{"date":"2016-08-06","available":false,"price":2093},{"date":"2016-08-07","available":false,"price":2093},{"date":"2016-08-08","available":false,"price":2093},{"date":"2016-08-09","available":false,"price":2093},{"date":"2016-08-10","available":false,"price":2093},{"date":"2016-08-11","available":false,"price":2093},{"date":"2016-08-12","available":false,"price":2093},{"date":"2016-08-13","available":false,"price":2093},{"date":"2016-08-14","available":false,"price":2093},{"date":"2016-08-15","available":false,"price":2093},{"date":"2016-08-16","available":false,"price":2093},{"date":"2016-08-17","available":false,"price":2093},{"date":"2016-08-18","available":false,"price":2093},{"date":"2016-08-19","available":false,"price":2093},{"date":"2016-08-20","available":false,"price":2094},{"date":"2016-08-21","available":true,"price":2061},{"date":"2016-08-22","available":true,"price":2061},{"date":"2016-08-23","available":true,"price":2061},{"date":"2016-08-24","available":true,"price":2061},{"date":"2016-08-25","available":true,"price":2061},{"date":"2016-08-26","available":true,"price":2061},{"date":"2016-08-27","available":true,"price":2061},{"date":"2016-08-28","available":true,"price":2061},{"date":"2016-08-29","available":true,"price":2061},{"date":"2016-08-30","available":true,"price":2061},{"date":"2016-08-31","available":true,"price":2061},{"date":"2016-09-01","available":true,"price":1096},{"date":"2016-09-02","available":true,"price":1096},{"date":"2016-09-03","available":true,"price":1096},{"date":"2016-09-04","available":true,"price":1096},{"date":"2016-09-05","available":true,"price":1096},{"date":"2016-09-06","available":true,"price":1096},{"date":"2016-09-07","available":true,"price":1096},{"date":"2016-09-08","available":true,"price":1096},{"date":"2016-09-09","available":true,"price":1096},{"date":"2016-09-10","available":true,"price":1096},{"date":"2016-09-11","available":true,"price":1096},{"date":"2016-09-12","available":true,"price":1096},{"date":"2016-09-13","available":true,"price":1096},{"date":"2016-09-14","available":true,"price":1096},{"date":"2016-09-15","available":true,"price":1096},{"date":"2016-09-16","available":true,"price":1096},{"date":"2016-09-17","available":true,"price":1096},{"date":"2016-09-18","available":true,"price":1096},{"date":"2016-09-19","available":true,"price":1096},{"date":"2016-09-20","available":true,"price":1096},{"date":"2016-09-21","available":true,"price":1096},{"date":"2016-09-22","available":true,"price":1096},{"date":"2016-09-23","available":true,"price":1096},{"date":"2016-09-24","available":true,"price":1096},{"date":"2016-09-25","available":true,"price":1096},{"date":"2016-09-26","available":true,"price":1096},{"date":"2016-09-27","available":true,"price":1096},{"date":"2016-09-28","available":true,"price":1096},{"date":"2016-09-29","available":true,"price":1096},{"date":"2016-09-30","available":true,"price":1096},{"date":"2016-10-01","available":true,"price":1096},{"date":"2016-10-02","available":true,"price":1096},{"date":"2016-10-03","available":true,"price":1096},{"date":"2016-10-04","available":true,"price":1096},{"date":"2016-10-05","available":true,"price":1096},{"date":"2016-10-06","available":true,"price":1096},{"date":"2016-10-07","available":true,"price":1096},{"date":"2016-10-08","available":true,"price":1096},{"date":"2016-10-09","available":true,"price":1096},{"date":"2016-10-10","available":true,"price":1096},{"date":"2016-10-11","available":true,"price":1096},{"date":"2016-10-12","available":true,"price":1096},{"date":"2016-10-13","available":true,"price":1096},{"date":"2016-10-14","available":true,"price":1096},{"date":"2016-10-15","available":true,"price":1096},{"date":"2016-10-16","available":true,"price":1096},{"date":"2016-10-17","available":true,"price":1096},{"date":"2016-10-18","available":true,"price":1096},{"date":"2016-10-19","available":true,"price":1096},{"date":"2016-10-20","available":true,"price":1096},{"date":"2016-10-21","available":true,"price":1096},{"date":"2016-10-22","available":true,"price":1096},{"date":"2016-10-23","available":true,"price":1096},{"date":"2016-10-24","available":true,"price":1096},{"date":"2016-10-25","available":true,"price":1096},{"date":"2016-10-26","available":true,"price":1096},{"date":"2016-10-27","available":true,"price":1096},{"date":"2016-10-28","available":true,"price":1096},{"date":"2016-10-29","available":true,"price":1096},{"date":"2016-10-30","available":true,"price":1096},{"date":"2016-10-31","available":true,"price":1096},{"date":"2016-11-01","available":true,"price":1096},{"date":"2016-11-02","available":true,"price":1096},{"date":"2016-11-03","available":true,"price":1096},{"date":"2016-11-04","available":true,"price":1096},{"date":"2016-11-05","available":true,"price":1096},{"date":"2016-11-06","available":true,"price":1096},{"date":"2016-11-07","available":true,"price":1096},{"date":"2016-11-08","available":true,"price":1096},{"date":"2016-11-09","available":true,"price":1096},{"date":"2016-11-10","available":true,"price":1096},{"date":"2016-11-11","available":true,"price":1096},{"date":"2016-11-12","available":true,"price":1096},{"date":"2016-11-13","available":true,"price":1096},{"date":"2016-11-14","available":true,"price":1096},{"date":"2016-11-15","available":true,"price":1096},{"date":"2016-11-16","available":true,"price":1096},{"date":"2016-11-17","available":true,"price":1096},{"date":"2016-11-18","available":true,"price":1096},{"date":"2016-11-19","available":true,"price":1096},{"date":"2016-11-20","available":true,"price":1096},{"date":"2016-11-21","available":true,"price":1096},{"date":"2016-11-22","available":true,"price":1096},{"date":"2016-11-23","available":true,"price":1096},{"date":"2016-11-24","available":true,"price":1096},{"date":"2016-11-25","available":true,"price":1096},{"date":"2016-11-26","available":true,"price":1096},{"date":"2016-11-27","available":true,"price":1096},{"date":"2016-11-28","available":true,"price":1096},{"date":"2016-11-29","available":true,"price":1096},{"date":"2016-11-30","available":true,"price":1096},{"date":"2016-12-01","available":true,"price":1096},{"date":"2016-12-02","available":true,"price":1096},{"date":"2016-12-03","available":true,"price":1096},{"date":"2016-12-04","available":true,"price":1096},{"date":"2016-12-05","available":true,"price":1096},{"date":"2016-12-06","available":true,"price":1096},{"date":"2016-12-07","available":true,"price":1096},{"date":"2016-12-08","available":true,"price":1096},{"date":"2016-12-09","available":true,"price":1096},{"date":"2016-12-10","available":true,"price":1096},{"date":"2016-12-11","available":true,"price":1096},{"date":"2016-12-12","available":true,"price":1096},{"date":"2016-12-13","available":true,"price":1096},{"date":"2016-12-14","available":true,"price":1096},{"date":"2016-12-15","available":true,"price":2426},{"date":"2016-12-16","available":true,"price":2426},{"date":"2016-12-17","available":true,"price":2426},{"date":"2016-12-18","available":true,"price":2426},{"date":"2016-12-19","available":true,"price":2426},{"date":"2016-12-20","available":true,"price":2426},{"date":"2016-12-21","available":true,"price":2426},{"date":"2016-12-22","available":true,"price":2426},{"date":"2016-12-23","available":true,"price":2426},{"date":"2016-12-24","available":true,"price":2426},{"date":"2016-12-25","available":true,"price":2426},{"date":"2016-12-26","available":false,"price":1126},{"date":"2016-12-27","available":false,"price":1126},{"date":"2016-12-28","available":false,"price":1126},{"date":"2016-12-29","available":false,"price":1126},{"date":"2016-12-30","available":false,"price":1126},{"date":"2016-12-31","available":false,"price":1126},{"date":"2017-01-01","available":false,"price":1126},{"date":"2017-01-02","available":false,"price":1126},{"date":"2017-01-03","available":false,"price":1126},{"date":"2017-01-04","available":false,"price":1126},{"date":"2017-01-05","available":true,"price":2426},{"date":"2017-01-06","available":true,"price":2426},{"date":"2017-01-07","available":true,"price":2426},{"date":"2017-01-08","available":true,"price":2426},{"date":"2017-01-09","available":true,"price":2426},{"date":"2017-01-10","available":true,"price":2426},{"date":"2017-01-11","available":true,"price":2426},{"date":"2017-01-12","available":true,"price":2426},{"date":"2017-01-13","available":true,"price":2426},{"date":"2017-01-14","available":true,"price":2426},{"date":"2017-01-15","available":true,"price":2426},{"date":"2017-01-16","available":true,"price":2426},{"date":"2017-01-17","available":true,"price":2426},{"date":"2017-01-18","available":true,"price":2426},{"date":"2017-01-19","available":true,"price":2426},{"date":"2017-01-20","available":true,"price":2426},{"date":"2017-01-21","available":true,"price":2426},{"date":"2017-01-22","available":true,"price":2426},{"date":"2017-01-23","available":true,"price":2426},{"date":"2017-01-24","available":true,"price":2426},{"date":"2017-01-25","available":true,"price":2426},{"date":"2017-01-26","available":true,"price":2426},{"date":"2017-01-27","available":true,"price":2426},{"date":"2017-01-28","available":true,"price":2426},{"date":"2017-01-29","available":true,"price":1615},{"date":"2017-01-30","available":true,"price":1615},{"date":"2017-01-31","available":true,"price":1615},{"date":"2017-02-01","available":true,"price":1615},{"date":"2017-02-02","available":true,"price":1615},{"date":"2017-02-03","available":true,"price":1615},{"date":"2017-02-04","available":true,"price":1615},{"date":"2017-02-05","available":true,"price":1615},{"date":"2017-02-06","available":true,"price":1615},{"date":"2017-02-07","available":true,"price":1615},{"date":"2017-02-08","available":true,"price":1615},{"date":"2017-02-09","available":true,"price":1615},{"date":"2017-02-10","available":true,"price":1615},{"date":"2017-02-11","available":true,"price":1615},{"date":"2017-02-12","available":true,"price":1615},{"date":"2017-02-13","available":true,"price":1615},{"date":"2017-02-14","available":true,"price":1615},{"date":"2017-02-15","available":true,"price":1615},{"date":"2017-02-16","available":true,"price":1615},{"date":"2017-02-17","available":true,"price":1615},{"date":"2017-02-18","available":true,"price":1615},{"date":"2017-02-19","available":true,"price":1615},{"date":"2017-02-20","available":true,"price":1615},{"date":"2017-02-21","available":true,"price":1615},{"date":"2017-02-22","available":true,"price":1615},{"date":"2017-02-23","available":true,"price":1615},{"date":"2017-02-24","available":true,"price":1615},{"date":"2017-02-25","available":true,"price":1615},{"date":"2017-02-26","available":true,"price":1615},{"date":"2017-02-27","available":true,"price":1615},{"date":"2017-02-28","available":true,"price":1615},{"date":"2017-03-01","available":true,"price":1615},{"date":"2017-03-02","available":true,"price":1615},{"date":"2017-03-03","available":true,"price":1615},{"date":"2017-03-04","available":true,"price":1615},{"date":"2017-03-05","available":true,"price":1615},{"date":"2017-03-06","available":true,"price":1615},{"date":"2017-03-07","available":true,"price":1615},{"date":"2017-03-08","available":true,"price":1615},{"date":"2017-03-09","available":true,"price":1615},{"date":"2017-03-10","available":true,"price":1615}]}
2 |
--------------------------------------------------------------------------------