UNPKG

@rschedule/luxon-date-adapter

Version:

An rSchedule DateAdapter for "luxon" DateTime objects.

137 lines (134 loc) 4.13 kB
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 };