Skip to content

Commit c147827

Browse files
author
Matt Lewis
committed
feat: replace the moment dependency with the date-fns library
BREAKING CHANGE: 1/ The `dayModifier` and `hourSegmentModifier` output objects now return pure date objects instead of moments 2/ If using the `CalendarMomentDateFormatter` you must now also provide moment to the calendar like so ``` import * as moment from 'moment'; import { CalendarMomentDateFormatter, CalendarDateFormatter, MOMENT } from './../angular2-calendar'; ... providers: [ {provide: CalendarDateFormatter, useClass: CalendarMomentDateFormatter}, {provide: MOMENT, useValue: moment} ] ``` 3/ The week start day is now no longer determined by moment. You must manually pass it to the month and week view components like so ``` // the first day of the week is Monday [weekStartsOn]="1" ``` 4/ If using this library without a module bundler you must make sure the date-fns library is included in a script tag Closes #48
1 parent dc12621 commit c147827

15 files changed

+181
-97
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ A calendar component that can display events on a month, week or day view. The s
2525

2626
Install through npm:
2727
```
28-
npm install --save angular2-calendar moment
28+
npm install --save angular2-calendar
2929
```
3030

3131
For a full e2e example see the [demo source](https://github.com/mattlewis92/angular2-calendar/blob/master/demo/demo.component.ts). Better docs to follow in the future!

demo/demo.component.ts

+41-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
import {Component} from '@angular/core';
2-
import * as moment from 'moment';
3-
import {UnitOfTime, Moment} from 'moment';
2+
import {
3+
startOfDay,
4+
subDays,
5+
addDays,
6+
endOfMonth,
7+
isSameDay,
8+
isSameMonth,
9+
addWeeks,
10+
subWeeks,
11+
addMonths,
12+
subMonths
13+
} from 'date-fns';
414
import {
515
CalendarEvent,
616
CalendarEventAction
@@ -83,7 +93,7 @@ const colors: any = {
8393
})
8494
export class Demo {
8595

86-
private view: UnitOfTime = 'month';
96+
private view: string = 'month';
8797

8898
private viewDate: Date = new Date();
8999

@@ -100,47 +110,64 @@ export class Demo {
100110
}];
101111

102112
private events: CalendarEvent[] = [{
103-
start: moment().startOf('day').subtract(1, 'day').toDate(),
104-
end: moment().add(1, 'day').toDate(),
113+
start: subDays(startOfDay(new Date()), 1),
114+
end: addDays(new Date(), 1),
105115
title: 'A 3 day event',
106116
color: colors.red,
107117
actions: this.actions
108118
}, {
109-
start: moment().startOf('day').toDate(),
119+
start: startOfDay(new Date()),
110120
title: 'An event with no end date',
111121
color: colors.yellow,
112122
actions: this.actions
113123
}, {
114-
start: moment().endOf('month').subtract(3, 'days').toDate(),
115-
end: moment().endOf('month').add(3, 'days').toDate(),
124+
start: subDays(endOfMonth(new Date()), 3),
125+
end: addDays(endOfMonth(new Date()), 3),
116126
title: 'A long event that spans 2 months',
117127
color: colors.blue
118128
}];
119129

120130
private activeDayIsOpen: boolean = true;
121131

122132
increment(): void {
123-
this.viewDate = moment(this.viewDate).add(1, this.view).toDate();
133+
134+
const addFn: any = {
135+
day: addDays,
136+
week: addWeeks,
137+
month: addMonths
138+
}[this.view];
139+
140+
this.viewDate = addFn(this.viewDate, 1);
141+
124142
}
125143

126144
decrement(): void {
127-
this.viewDate = moment(this.viewDate).subtract(1, this.view).toDate();
145+
146+
const subFn: any = {
147+
day: subDays,
148+
week: subWeeks,
149+
month: subMonths
150+
}[this.view];
151+
152+
this.viewDate = subFn(this.viewDate, 1);
153+
128154
}
129155

130156
today(): void {
131157
this.viewDate = new Date();
132158
}
133159

134-
dayClicked({date, events}: {date: Moment, events: CalendarEvent[]}): void {
135-
if (moment(date).startOf('month').isSame(moment(this.viewDate).startOf('month'))) {
160+
dayClicked({date, events}: {date: Date, events: CalendarEvent[]}): void {
161+
162+
if (isSameMonth(date, this.viewDate)) {
136163
if (
137-
(moment(this.viewDate).startOf('day').isSame(date.clone().startOf('day')) && this.activeDayIsOpen === true) ||
164+
(isSameDay(this.viewDate, date) && this.activeDayIsOpen === true) ||
138165
events.length === 0
139166
) {
140167
this.activeDayIsOpen = false;
141168
} else {
142169
this.activeDayIsOpen = true;
143-
this.viewDate = date.toDate();
170+
this.viewDate = date;
144171
}
145172
}
146173
}

package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"@ng-bootstrap/ng-bootstrap": "~1.0.0-alpha.1",
5050
"@types/chai": "~3.4.30",
5151
"@types/core-js": "~0.9.32",
52+
"@types/date-fns": "0.0.1",
5253
"@types/jasmine": "~2.2.33",
5354
"@types/sinon": "~1.16.27",
5455
"@types/sinon-chai": "~2.7.26",
@@ -105,8 +106,7 @@
105106
"peerDependencies": {
106107
"@angular/core": "^2.0.0-rc.5",
107108
"@angular/common": "^2.0.0-rc.5",
108-
"@angular/platform-browser": "^2.0.0-rc.5",
109-
"moment": "^2.0.0"
109+
"@angular/platform-browser": "^2.0.0-rc.5"
110110
},
111111
"files": [
112112
"dist",
@@ -121,6 +121,7 @@
121121
}
122122
},
123123
"dependencies": {
124-
"calendar-utils": "0.0.25"
124+
"calendar-utils": "0.0.26",
125+
"date-fns": "~1.3.0"
125126
}
126127
}

src/components/day/calendarDayView.component.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const SEGMENT_HEIGHT: number = 30;
3838
*ngFor="let segment of hour.segments"
3939
[segment]="segment"
4040
[locale]="locale"
41-
(click)="hourSegmentClicked.emit({date: segment.date.toDate()})">
41+
(click)="hourSegmentClicked.emit({date: segment.date})">
4242
</mwl-calendar-day-view-hour-segment>
4343
</div>
4444
</div>

src/components/month/calendarMonthView.component.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
LOCALE_ID,
1212
Inject
1313
} from '@angular/core';
14-
import * as moment from 'moment';
14+
import * as isSameDay from 'date-fns/is_same_day';
1515
import {
1616
CalendarEvent,
1717
WeekDay,
@@ -95,6 +95,11 @@ export class CalendarMonthView implements OnChanges, OnInit, OnDestroy {
9595
*/
9696
@Input() tooltipPlacement: string = 'top';
9797

98+
/**
99+
* The start number of the week
100+
*/
101+
@Input() weekStartsOn: number;
102+
98103
/**
99104
* Called when the day cell is clicked
100105
*/
@@ -148,14 +153,16 @@ export class CalendarMonthView implements OnChanges, OnInit, OnDestroy {
148153

149154
private refreshHeader(): void {
150155
this.columnHeaders = getWeekViewHeader({
151-
viewDate: this.viewDate
156+
viewDate: this.viewDate,
157+
weekStartsOn: this.weekStartsOn
152158
});
153159
}
154160

155161
private refreshBody(): void {
156162
this.view = getMonthView({
157163
events: this.events,
158-
viewDate: this.viewDate
164+
viewDate: this.viewDate,
165+
weekStartsOn: this.weekStartsOn
159166
});
160167
if (this.dayModifier) {
161168
this.view.days.forEach(day => this.dayModifier(day));
@@ -164,7 +171,7 @@ export class CalendarMonthView implements OnChanges, OnInit, OnDestroy {
164171

165172
private checkActiveDayIsOpen(): void {
166173
if (this.activeDayIsOpen === true) {
167-
this.openDay = this.view.days.find(day => day.date.isSame(moment(this.viewDate).startOf('day')));
174+
this.openDay = this.view.days.find(day => isSameDay(day.date, this.viewDate));
168175
const index: number = this.view.days.indexOf(this.openDay);
169176
this.openRowIndex = Math.floor(index / 7) * 7;
170177
} else {

src/components/week/calendarWeekView.component.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import {
3131
*ngFor="let day of days"
3232
[day]="day"
3333
[locale]="locale"
34-
(click)="dayClicked.emit({date: day.date.toDate()})">
34+
(click)="dayClicked.emit({date: day.date})">
3535
</mwl-calendar-week-view-header>
3636
</div>
3737
<div *ngFor="let eventRow of eventRows">
@@ -77,6 +77,11 @@ export class CalendarWeekView implements OnChanges, OnInit, OnDestroy {
7777
*/
7878
@Input() tooltipPlacement: string = 'bottom';
7979

80+
/**
81+
* The start number of the week
82+
*/
83+
@Input() weekStartsOn: number;
84+
8085
/**
8186
* Called when a header week day is clicked
8287
*/
@@ -124,14 +129,16 @@ export class CalendarWeekView implements OnChanges, OnInit, OnDestroy {
124129

125130
private refreshHeader(): void {
126131
this.days = getWeekViewHeader({
127-
viewDate: this.viewDate
132+
viewDate: this.viewDate,
133+
weekStartsOn: this.weekStartsOn
128134
});
129135
}
130136

131137
private refreshBody(): void {
132138
this.eventRows = getWeekView({
133139
events: this.events,
134-
viewDate: this.viewDate
140+
viewDate: this.viewDate,
141+
weekStartsOn: this.weekStartsOn
135142
});
136143
}
137144

src/pipes/calendarDate.pipe.ts

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import {Pipe, PipeTransform, LOCALE_ID, Inject} from '@angular/core';
2-
import * as moment from 'moment';
3-
import {Moment} from 'moment';
42
import {CalendarDateFormatter} from './../providers/calendarDateFormatter.provider';
53

64
@Pipe({
@@ -10,11 +8,8 @@ export class CalendarDate implements PipeTransform {
108

119
constructor(private dateFormatter: CalendarDateFormatter, @Inject(LOCALE_ID) private locale: string) {}
1210

13-
transform(date: Date | Moment, method: string, locale: string = this.locale): string {
14-
15-
date = moment(date).toDate();
11+
transform(date: Date, method: string, locale: string = this.locale): string {
1612
return this.dateFormatter[method]({date, locale});
17-
1813
}
1914

2015
}
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,42 @@
1-
import * as moment from 'moment';
1+
import {OpaqueToken, Inject} from '@angular/core';
22
import {CalendarDateFormatterInterface, DateFormatterParams} from './../interfaces/calendarDateFormatter.interface';
33

4+
export const MOMENT: OpaqueToken = new OpaqueToken('Moment');
5+
46
export class CalendarMomentDateFormatter implements CalendarDateFormatterInterface {
57

8+
constructor(@Inject(MOMENT) private moment: any) {}
9+
610
public monthViewColumnHeader({date, locale}: DateFormatterParams): string {
7-
return moment(date).locale(locale).format('dddd');
11+
return this.moment(date).locale(locale).format('dddd');
812
}
913

1014
public monthViewDayNumber({date, locale}: DateFormatterParams): string {
11-
return moment(date).locale(locale).format('D');
15+
return this.moment(date).locale(locale).format('D');
1216
}
1317

1418
public monthViewTitle({date, locale}: DateFormatterParams): string {
15-
return moment(date).locale(locale).format('MMMM YYYY');
19+
return this.moment(date).locale(locale).format('MMMM YYYY');
1620
}
1721

1822
public weekViewColumnHeader({date, locale}: DateFormatterParams): string {
19-
return moment(date).locale(locale).format('dddd');
23+
return this.moment(date).locale(locale).format('dddd');
2024
}
2125

2226
public weekViewColumnSubHeader({date, locale}: DateFormatterParams): string {
23-
return moment(date).locale(locale).format('D MMM');
27+
return this.moment(date).locale(locale).format('D MMM');
2428
}
2529

2630
public weekViewTitle({date, locale}: DateFormatterParams): string {
27-
return moment(date).locale(locale).format('[Week] W [of] YYYY');
31+
return this.moment(date).locale(locale).format('[Week] W [of] YYYY');
2832
}
2933

3034
public dayViewHour({date, locale}: DateFormatterParams): string {
31-
return moment(date).locale(locale).format('ha');
35+
return this.moment(date).locale(locale).format('ha');
3236
}
3337

3438
public dayViewTitle({date, locale}: DateFormatterParams): string {
35-
return moment(date).locale(locale).format('dddd, D MMMM, YYYY');
39+
return this.moment(date).locale(locale).format('dddd, D MMMM, YYYY');
3640
}
3741

3842
}

src/providers/calendarNativeDateFormatter.provider.ts

+2-11
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
1+
import * as getISOWeek from 'date-fns/get_iso_week';
12
import {CalendarDateFormatterInterface, DateFormatterParams} from './../interfaces/calendarDateFormatter.interface';
23

3-
// TODO - move this into its own module that people can re-use
4-
const getWeekNumber: Function = (date: Date): number => {
5-
// source: https://weeknumber.net/how-to/javascript
6-
const dateClone: Date = new Date(date.getTime());
7-
dateClone.setHours(0, 0, 0, 0);
8-
dateClone.setDate(dateClone.getDate() + 3 - (dateClone.getDay() + 6) % 7);
9-
const week1: Date = new Date(dateClone.getFullYear(), 0, 4);
10-
return 1 + Math.round(((dateClone.getTime() - week1.getTime()) / 86400000 - 3 + (week1.getDay() + 6) % 7) / 7);
11-
};
12-
134
export class CalendarNativeDateFormatter implements CalendarDateFormatterInterface {
145

156
public monthViewColumnHeader({date, locale}: DateFormatterParams): string {
@@ -37,7 +28,7 @@ export class CalendarNativeDateFormatter implements CalendarDateFormatterInterfa
3728

3829
public weekViewTitle({date, locale}: DateFormatterParams): string {
3930
const year: string = new Intl.DateTimeFormat(locale, {year: 'numeric'}).format(date);
40-
const weekNumber: number = getWeekNumber(date);
31+
const weekNumber: number = getISOWeek(date);
4132
return `Week ${weekNumber} of ${year}`;
4233
}
4334

test/calendarDate.pipe.spec.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import {
66
} from '@angular/core/testing';
77
import {expect} from 'chai';
88
import {spy} from 'sinon';
9+
import * as moment from 'moment';
910
import {
1011
CalendarModule,
1112
CalendarMomentDateFormatter,
12-
CalendarDateFormatter
13+
CalendarDateFormatter,
14+
MOMENT
1315
} from './../angular2-calendar';
1416

1517
@Component({
@@ -29,7 +31,8 @@ describe('calendarDate pipe', () => {
2931
TestBed.configureTestingModule({imports: [CalendarModule], declarations: [TestCmp]});
3032
TestBed.configureCompiler({
3133
providers: [
32-
{provide: CalendarDateFormatter, useClass: CalendarMomentDateFormatter}
34+
{provide: CalendarDateFormatter, useClass: CalendarMomentDateFormatter},
35+
{provide: MOMENT, useValue: moment}
3336
]
3437
});
3538
});

0 commit comments

Comments
 (0)