UNPKG

fugitsit

Version:

Small library that wraps ICAL.js and provide more convenient means for editing

462 lines (415 loc) 11.7 kB
/** * @copyright Copyright (c) 2019 Georg Ehrke * * @author Georg Ehrke <georg-nextcloud@ehrke.email> * * @license GNU AGPL version 3 or any later version * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ import AbstractValue from './abstractValue.js' import DurationValue from './durationValue.js' import ICAL from 'ical.js' /** * @class DateTimeValue * @classdesc Wrapper for ICAL.Time * * @url https://tools.ietf.org/html/rfc5545#section-3.3.4 * @url https://tools.ietf.org/html/rfc5545#section-3.3.5 * @url https://tools.ietf.org/html/rfc5545#section-3.3.12 * @url https://github.com/mozilla-comm/ical.js/blob/master/lib/ical/time.js */ export default class DateTimeValue extends AbstractValue { /** * Gets the year of the stored date-time-value * * @returns {Number} */ get year() { return this._innerValue.year } /** * Sets the year of the stored date-time-value * * @throws {ModificationNotAllowedError} if value is locked for modification * @param {Number} year Number of years to set */ set year(year) { this._modifyContent() this._innerValue.year = year } /** * Gets the month of the stored date-time-value * * @returns {Number} */ get month() { return this._innerValue.month } /** * Sets the month of the stored date-time-value * * @throws {ModificationNotAllowedError} if value is locked for modification * @param {Number} month Number of months to set */ set month(month) { this._modifyContent() if (month < 1 || month > 12) { throw new TypeError('Month out of range') } this._innerValue.month = month } /** * Gets the day of the stored date-time-value * * @returns {Number} */ get day() { return this._innerValue.day } /** * Sets the day of the stored date-time-value * * @throws {ModificationNotAllowedError} if value is locked for modification * @throws {TypeError} if out of range * @param {Number} day Number of days to set */ set day(day) { this._modifyContent() if (day < 1 || day > 31) { throw new TypeError('Day out of range') } this._innerValue.day = day } /** * Gets the hour of the stored date-time-value * * @returns {Number} */ get hour() { return this._innerValue.hour } /** * Sets the hour of the stored date-time-value * * @throws {ModificationNotAllowedError} if value is locked for modification * @throws {TypeError} if out of range * @param {Number} hour Number of hours to set */ set hour(hour) { this._modifyContent() if (hour < 0 || hour > 23) { throw new TypeError('Hour out of range') } this._innerValue.hour = hour } /** * Gets the minute of the stored date-time-value * * @returns {Number} */ get minute() { return this._innerValue.minute } /** * Sets the minute of the stored date-time-value * * @throws {ModificationNotAllowedError} if value is locked for modification * @throws {TypeError} if out of range * @param {Number} minute Number of minutes to set */ set minute(minute) { this._modifyContent() if (minute < 0 || minute > 59) { throw new TypeError('Minute out of range') } this._innerValue.minute = minute } /** * Gets the second of the stored date-time-value * * @returns {Number} */ get second() { return this._innerValue.second } /** * Sets the second of the stored date-time-value * * @throws {ModificationNotAllowedError} if value is locked for modification * @throws {TypeError} if out of range * @param {Number} second Number of seconds to set */ set second(second) { this._modifyContent() if (second < 0 || second > 59) { throw new TypeError('Second out of range') } this._innerValue.second = second } /** * Gets the timezone of this date-time-value * * @returns {String|null} */ get timezoneId() { // If zone.tzid is set and it's not 'floating' nor 'UTC', then it's a proper // timezone that we also have a timezone id for if (this._innerValue.zone.tzid && this._innerValue.zone.tzid !== 'floating' && this._innerValue.zone.tzid === 'UTC') { return this._innerValue.zone.tzid } // If there is a timezone set, but we didn't have a zone.tzid in the previous if, // this means that the tzid does not have a definition stored along it. // we will keep this information anyway to not lose it if (this._innerValue.timezone) { return this._innerValue.timezone } // this is the case when it's floating / UTC return this._innerValue.zone.tzid || null } /** * Gets whether this date-time-value is a date or date-time * * @returns {boolean} */ get isDate() { return this._innerValue.isDate } /** * Sets whether this date-time-value is a date or date-time * * @throws {ModificationNotAllowedError} if value is locked for modification * @param {boolean} isDate Whether this is a date or date-time value */ set isDate(isDate) { this._modifyContent() this._innerValue.isDate = !!isDate if (isDate) { this._innerValue.hour = 0 this._innerValue.minute = 0 this._innerValue.second = 0 } } /** * Gets the unix-time * * @returns {Number} */ get unixTime() { return this._innerValue.toUnixTime() } /** * returns vanilla javascript date object * * @returns {Date} */ get jsDate() { return this._innerValue.toJSDate() } /** * Adds a duration to this date-time-value * * @param {DurationValue} duration The duration to ad */ addDuration(duration) { this._innerValue.addDuration(duration.toICALJs()) } /** * Subtract another date excluding timezones * * @param {DateTimeValue} other The date-time value to subtract * @returns {DurationValue} */ subtractDateWithoutTimezone(other) { const icalDuration = this._innerValue.subtractDate(other.toICALJs()) return DurationValue.fromICALJs(icalDuration) } /** * Subtract another date, taking timezones into account * * @param {DateTimeValue} other The date-time value to subtract * @returns {DurationValue} */ subtractDateWithTimezone(other) { const icalDuration = this._innerValue.subtractDateTz(other.toICALJs()) return DurationValue.fromICALJs(icalDuration) } /** * Compares this DateTimeValue object with another one * * @param {DateTimeValue} other The date-time to compare to * @returns {Number} -1, 0 or 1 for less/equal/greater */ compare(other) { return this._innerValue.compare(other.toICALJs()) } /** * Compares only the date part in a given timezone * * @param {DateTimeValue} other The date-time to compare to * @param {Timezone} timezone The timezone to compare in * @returns {Number} -1, 0 or 1 for less/equal/greater */ compareDateOnlyInGivenTimezone(other, timezone) { return this._innerValue.compareDateOnlyTz(other.toICALJs(), timezone.toICALTimezone()) } /** * Returns a clone of this object which was converted to a different timezone * * @param {Timezone} timezone TimezoneId to convert to * @returns {DateTimeValue} */ getInTimezone(timezone) { const clonedICALTime = this._innerValue.convertToZone(timezone.toICALTimezone()) return DateTimeValue.fromICALJs(clonedICALTime) } /** * Get the inner ICAL.Timezone * * @returns {ICAL.Timezone} * @package */ getICALTimezone() { return this._innerValue.zone } /** * Returns a clone of this object which was converted to a different timezone * * @param {ICAL.Timezone} timezone TimezoneId to convert to * @returns {DateTimeValue} * @package */ getInICALTimezone(timezone) { const clonedICALTime = this._innerValue.convertToZone(timezone) return DateTimeValue.fromICALJs(clonedICALTime) } /** * Returns a clone of this object which was converted to UTC * * @returns {DateTimeValue} */ getInUTC() { const clonedICALTime = this._innerValue.convertToZone(ICAL.Timezone.utcTimezone) return DateTimeValue.fromICALJs(clonedICALTime) } /** * This silently replaces the inner timezone without converting the actual time * * @param {ICAL.Timezone} timezone The timezone to replace with * @package */ silentlyReplaceTimezone(timezone) { this._modify() this._innerValue = new ICAL.Time({ year: this.year, month: this.month, day: this.day, hour: this.hour, minute: this.minute, second: this.second, isDate: this.isDate, timezone, }) } /** * Replaces the inner timezone without converting the actual time * * @param {Timezone} timezone The timezone to replace with */ replaceTimezone(timezone) { this._modifyContent() this._innerValue = ICAL.Time.fromData({ year: this.year, month: this.month, day: this.day, hour: this.hour, minute: this.minute, second: this.second, isDate: this.isDate, }, timezone.toICALTimezone()) } /** * Calculates the UTC offset of the date-time-value in its timezone * * @returns {Number} */ utcOffset() { return this._innerValue.utcOffset() } /** * Check if this is an event with floating time * * @returns {boolean} */ isFloatingTime() { return this._innerValue.zone.tzid === 'floating' } /** * clones this value * * @returns {DateTimeValue} */ clone() { return DateTimeValue.fromICALJs(this._innerValue.clone()) } /** * Create a new DateTimeValue object from an ICAL.Time object * * @param {ICAL.Time} icalValue The ical.js Date value to initialise from * @returns {DateTimeValue} */ static fromICALJs(icalValue) { return new DateTimeValue(icalValue) } /** * Creates a new DateTimeValue object based on a vanilla javascript object * * @param {Date} jsDate The JavaScript date to initialise from * @param {Boolean=} useUTC Whether or not to treat it as UTC * @returns {DateTimeValue} */ static fromJSDate(jsDate, useUTC = false) { const icalValue = ICAL.Time.fromJSDate(jsDate, useUTC) return DateTimeValue.fromICALJs(icalValue) } /** * Creates a new DateTimeValue object based on simple parameters * * @param {Object} data The destructuring object * @param {Number=} data.year Amount of years to set * @param {Number=} data.month Amount of month to set (1-based) * @param {Number=} data.day Amount of days to set * @param {Number=} data.hour Amount of hours to set * @param {Number=} data.minute Amount of minutes to set * @param {Number=} data.second Amount of seconds to set * @param {Boolean=} data.isDate Whether this is a date or date-time * @param {Timezone=} timezone The timezone of the DateTimeValue * @returns {DateTimeValue} */ static fromData(data, timezone) { const icalValue = ICAL.Time.fromData(data, timezone ? timezone.toICALTimezone() : undefined) return DateTimeValue.fromICALJs(icalValue) } } DateTimeValue.SUNDAY = ICAL.Time.SUNDAY DateTimeValue.MONDAY = ICAL.Time.MONDAY DateTimeValue.TUESDAY = ICAL.Time.TUESDAY DateTimeValue.WEDNESDAY = ICAL.Time.WEDNESDAY DateTimeValue.THURSDAY = ICAL.Time.THURSDAY DateTimeValue.FRIDAY = ICAL.Time.FRIDAY DateTimeValue.SATURDAY = ICAL.Time.SATURDAY DateTimeValue.DEFAULT_WEEK_START = DateTimeValue.MONDAY