@rschedule/luxon-date-adapter
Version:
An rSchedule DateAdapter for "luxon" DateTime objects.
137 lines (134 loc) • 4.13 kB
JavaScript
import { DateAdapterBase, ArgumentError, InvalidDateAdapterError } from '@rschedule/core';
import { LocalZone, DateTime } from 'luxon';
/**
* The `LuxonDateAdapter` is a DateAdapter for `luxon` DateTime
* objects.
*
* It supports timezone handling in so far as luxon supports
* timezone handling. Note: that, if able, luxon always adds
* a timezone to a DateTime (i.e. timezone may never be undefined).
*
* At the moment, that means that serializing to/from iCal will
* always apply a specific timezone (which may or may not be what
* you want). If this is a problem for you, you can try opening
* an issue in the rSchedule monorepo.
*/
class LuxonDateAdapter extends DateAdapterBase {
constructor(date, options = {}) {
super(undefined, options);
this.date = date;
this.timezone = date.zone instanceof LocalZone ? null : date.zoneName;
if (options.metadata) {
Object.assign(this.metadata, options.metadata);
}
this.assertIsValid();
}
/**
* Checks if object is an instance of `LuxonDateTime`
*/
static isDate(object) {
return DateTime.isDateTime(object);
}
static fromDate(date, options) {
return new LuxonDateAdapter(date, options);
}
static fromJSON(json) {
const zone = json.timezone === null ? 'local' : json.timezone === 'UTC' ? 'utc' : json.timezone;
const date = new LuxonDateAdapter(
DateTime.fromObject({
zone,
year: json.year,
month: json.month,
day: json.day,
hour: json.hour,
minute: json.minute,
second: json.second,
millisecond: json.millisecond,
}),
{ duration: json.duration },
);
if (json.metadata) {
Object.assign(date.metadata, json.metadata);
}
return date;
}
/**
* ### Important!!!
*
* This method expects an *rSchedule* `DateTime` object which bares
* *no relation* to a luxon `DateTime` object. This method is largely
* meant for private, internal rSchedule use.
*
* @param datetime rSchedule DateTime object
*/
static fromDateTime(datetime) {
const date = LuxonDateAdapter.fromJSON(datetime.toJSON());
date.generators.push(...datetime.generators);
if (datetime.metadata) {
Object.assign(date.metadata, datetime.metadata);
}
return date;
}
get end() {
if (!this.duration) return;
if (this._end) return this._end;
this._end = LuxonDateAdapter.fromDateTime(
this.toDateTime().add(this.duration, 'millisecond'),
).date;
return this._end;
}
set(prop, value) {
if (prop === 'timezone') {
if (this.timezone === value) return this;
else if (value === null) {
return new LuxonDateAdapter(this.date.toLocal(), {
duration: this.duration,
generators: this.generators,
});
} else {
return new LuxonDateAdapter(this.date.setZone(value), {
duration: this.duration,
generators: this.generators,
});
}
} else if (prop === 'duration') {
if (this.duration === value) return this;
else {
return new LuxonDateAdapter(this.date, {
duration: value,
generators: this.generators,
});
}
}
throw new ArgumentError(`Unknown prop "${prop}" for LuxonDateAdapter#set()`);
}
valueOf() {
return this.date.valueOf();
}
toJSON() {
const json = {
timezone: this.timezone,
year: this.date.get('year'),
month: this.date.get('month'),
day: this.date.get('day'),
hour: this.date.get('hour'),
minute: this.date.get('minute'),
second: this.date.get('second'),
millisecond: this.date.get('millisecond'),
};
if (this.duration) {
json.duration = this.duration;
}
return json;
}
assertIsValid() {
if (!this.date.isValid) {
throw new InvalidDateAdapterError();
} else if (this.duration && this.duration <= 0) {
throw new InvalidDateAdapterError('If provided, duration must be greater than 0.');
}
return true;
}
}
LuxonDateAdapter.hasTimezoneSupport = true;
export { LuxonDateAdapter };