Skip to content

Commit

Permalink
add different time zone support
Browse files Browse the repository at this point in the history
  • Loading branch information
acro5piano committed Apr 28, 2021
1 parent d9c644e commit 334647f
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 21 deletions.
38 changes: 21 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,45 @@
# rrule-contrib
# rrule-duration

[![npm version](https://badge.fury.io/js/rrule-contrib.svg)](https://badge.fury.io/js/rrule-contrib)
[![npm version](https://badge.fury.io/js/rrule-duration.svg)](https://badge.fury.io/js/rrule-duration)

[RRule](https://github.com/jakubroztocil/rrule) related utilities.
Add duration feature and time zone support to [RRule](https://github.com/jakubroztocil/rrule).

# Features

- Create events with duration and represent it with RRule
- Time zone support, even separate start/end time
- Dump duration as natural language

# Install

```
npm install --save rrule rrule-contrib
npm install --save rrule rrule-duration
```

Or if you use Yarn:

```
yarn add rrule rrule-contrib
yarn add rrule rrule-duration
```

# Usage

Currently the following classes are exported:

- CalendarEvent

TODO: add more functionality.

## `CalendarEvent`
# Basic Usage

`CalendarEvent` class is intended to use `RRule` with calendar events. Basically an `event` is represented by `start`, `end` and `RRule`. Let's see an example event.

```typescript
import { RRule } from 'rrule'
import { CalendarEvent } from 'rrule-contrib'
import { CalendarEvent } from 'rrule-duration'

const event = new CalendarEvent({
start: {
hour: 10,
minute: 0,
tz: 'UTC',
},
end: {
hour: 13,
hour: 22,
minute: 30,
tz: 'Asia/Tokyo',
},
recurrences: [
new RRule({
Expand Down Expand Up @@ -72,14 +72,18 @@ It will return the following array:
],
```

Note it includes start and end in plain `Date` type.

# Natural Language

You can also get event text as natural language (currently only in English) text.

```typescript
event.toText()
// => 10:00 AM to 13:30 AM every day on Monday, Friday and every month on the 25th
```

**Time zone support**
# Time Zone Support

The most powerful feature of `CalendarEvent` is strong time zone support. We, Remotehour, provides our service globally so this feature has been developed. In the above example, you can pass a `tz` option to `toText` method.

Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "rrule-contrib",
"version": "0.0.4",
"description": "RRule related utilities with timezone NLP support",
"name": "rrule-duration",
"version": "0.0.5",
"description": "RRule related utility with timezone NLP support",
"repository": "[email protected]:remotehour/rrule-duration",
"author": "gosho-kazuya <[email protected]>",
"license": "MIT",
Expand Down
38 changes: 38 additions & 0 deletions src/CalendarEvent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,44 @@ test('CalendarEvent - init with hour and minute, occurences', (t) => {
)
})

test('CalendarEvent - different time zone between start and end', (t) => {
const event = new CalendarEvent({
start: {
hour: 10,
minute: 0,
tz: 'UTC',
},
end: {
hour: 19,
minute: 30,
tz: 'Asia/Tokyo',
},
recurrences: [
new RRule({
freq: RRule.MONTHLY,
dtstart: new Date('2020-09-27T09:08:24.000Z'),
bymonthday: [],
byweekday: [RRule.FR.nth(3)],
}),
],
})

t.is(event.toText(), '10:00 AM to 10:30 AM every month on the 3rd Friday')

MockDate.set(SUMMER)
t.deepEqual(
event.occurences({
between: [new Date('2020-05-01T00:00:00'), new Date('2020-12-31T00:00:00')],
}),
// FIXME: is it broken?
[
[new Date('2020-10-16T10:00:00Z'), new Date('2020-10-16T10:30:00Z')],
[new Date('2020-11-20T10:00:00Z'), new Date('2020-11-20T10:30:00Z')],
[new Date('2020-12-18T10:00:00Z'), new Date('2020-12-18T10:30:00Z')],
],
)
})

test('CalendarEvent - toText format & time zone', (t) => {
const event = new CalendarEvent({
start: {
Expand Down
21 changes: 20 additions & 1 deletion src/CalendarEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,27 @@ function validateCalendarEventDef(e: CalendarEventDef, name: string) {
}
}

function hasMinuteHour(e: CalendarEventDef): e is { hour: number; minute: number } {
function hasMinuteHour(e: CalendarEventDef): e is { hour: number; minute: number; tz?: string } {
return Number.isInteger(e.hour) && Number.isInteger(e.minute)
}

// TODO: Better implementation?
function getOffsetFromTimeZone(d: dayjs.Dayjs) {
try {
const diffString = d.format('Z')
if (!diffString.includes('+')) {
return 0
}
const [hour, minute] = diffString
.replace('+', '')
.split(':')
.map((x) => parseInt(x))
return -1 * (hour * 60 + minute)
} catch {
return 0
}
}

export class CalendarEvent {
private start: dayjs.Dayjs
private end: dayjs.Dayjs
Expand Down Expand Up @@ -74,13 +91,15 @@ export class CalendarEvent {
.utc(date)
.hour(this.start.hour())
.minute(this.start.minute())
.add(getOffsetFromTimeZone(this.start), 'minute')
.second(0)
.millisecond(0)
.toDate()
const end = dayjs
.utc(date)
.hour(this.end.hour())
.minute(this.end.minute())
.add(getOffsetFromTimeZone(this.end), 'minute')
.second(0)
.millisecond(0)
.toDate()
Expand Down

0 comments on commit 334647f

Please sign in to comment.