Skip to content

Commit

Permalink
fix(ics): fixes all-day timestamps #157 (#158)
Browse files Browse the repository at this point in the history
Updates DTSTART and DTEND params in iCalendar such that the dates are
formatted as dates with times omitted for all-day events. This works
around the issue of timestamps interpreted differently in some calendar
apps.
  • Loading branch information
jshor authored Aug 28, 2021
1 parent 4dd9273 commit 25b8b7b
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 10 deletions.
16 changes: 12 additions & 4 deletions src/ICalendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,24 @@ export default class ICalendar extends CalendarBase {
.setMeta('UID', ics.getUid())
.setMeta('DTSTAMP', time.getTimeCreated())
.setMeta('PRODID', ics.getProdId())

this
.addProperty('CLASS', 'PUBLIC')
.addProperty('DESCRIPTION', ics.formatText(this.description))
.addProperty('DTSTART', time.formatDate(this.start, FORMAT.FULL))
.addProperty('DTEND', time.formatDate(this.end, FORMAT.FULL))
.addProperty('LOCATION', ics.formatText(this.location))
.addProperty('SUMMARY', ics.formatText(this.title))
.addProperty('TRANSP', 'TRANSPARENT')

if (this.isAllDay) {
// for all-day events, omit the time and just place dates
this
.addProperty('DTSTART;VALUE=DATE', time.formatDateNoUtc(this.start, FORMAT.DATE))
.addProperty('DTEND;VALUE=DATE', time.formatDateNoUtc(time.incrementDate(this.start, 1), FORMAT.DATE))
} else {
// otherwise, set the full start and end dates
this
.addProperty('DTSTART', time.formatDate(this.start, FORMAT.FULL))
.addProperty('DTEND', time.formatDate(this.end, FORMAT.FULL))
}

if (this.recurrence) {
this.addProperty('RRULE', ics.getRrule(this.recurrence))
}
Expand Down
26 changes: 20 additions & 6 deletions src/__tests__/ICalendar.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,20 @@ describe('ICalendar', () => {
expect(result).toBeInstanceOf(CalendarBase)
})

it('should render just the date for an all-day event', () => {
const obj = new ICalendar({
title: 'Fun Party',
description: 'BYOB',
location: 'New York',
start: new Date('2019-07-04T19:00:00.000')
})

expect(obj.render()).toContain([
`DTSTART;VALUE=DATE:${time.formatDateNoUtc(baseOpts.start, FORMAT.DATE)}`,
`DTEND;VALUE=DATE:${time.formatDateNoUtc(time.incrementDate(baseOpts.start, 1), FORMAT.DATE)}`
].join('\n'))
})

describe('addAlarm()', () => {
let obj: ICalendar

Expand Down Expand Up @@ -242,11 +256,11 @@ describe('ICalendar', () => {
'BEGIN:VEVENT',
'CLASS:PUBLIC',
`DESCRIPTION:${baseOpts.description}`,
`DTSTART:${time.formatDate(baseOpts.start, FORMAT.FULL)}`,
`DTEND:${time.formatDate(baseOpts.end, FORMAT.FULL)}`,
`LOCATION:${baseOpts.location}`,
`SUMMARY:${baseOpts.title}`,
'TRANSP:TRANSPARENT',
`DTSTART:${time.formatDate(baseOpts.start, FORMAT.FULL)}`,
`DTEND:${time.formatDate(baseOpts.end, FORMAT.FULL)}`,
'END:VEVENT',
'END:VCALENDAR',
`UID:${mockUuid}`,
Expand Down Expand Up @@ -281,22 +295,22 @@ describe('ICalendar', () => {
'BEGIN:VEVENT',
'CLASS:PUBLIC',
`DESCRIPTION:${secondEventOpts.description}`,
`DTSTART:${time.formatDate(secondEventOpts.start, FORMAT.FULL)}`,
`DTEND:${time.formatDate(baseOpts.end, FORMAT.FULL)}`,
`LOCATION:${secondEventOpts.location}`,
`SUMMARY:${secondEventOpts.title}`,
'TRANSP:TRANSPARENT',
`DTSTART:${time.formatDate(secondEventOpts.start, FORMAT.FULL)}`,
`DTEND:${time.formatDate(baseOpts.end, FORMAT.FULL)}`,
'END:VEVENT',

// base event
'BEGIN:VEVENT',
'CLASS:PUBLIC',
`DESCRIPTION:${baseOpts.description}`,
`DTSTART:${time.formatDate(baseOpts.start, FORMAT.FULL)}`,
`DTEND:${time.formatDate(baseOpts.end, FORMAT.FULL)}`,
`LOCATION:${baseOpts.location}`,
`SUMMARY:${baseOpts.title}`,
'TRANSP:TRANSPARENT',
`DTSTART:${time.formatDate(baseOpts.start, FORMAT.FULL)}`,
`DTEND:${time.formatDate(baseOpts.end, FORMAT.FULL)}`,
'END:VEVENT',

'END:VCALENDAR',
Expand Down

0 comments on commit 25b8b7b

Please sign in to comment.