188 lines
4.8 KiB
JavaScript
188 lines
4.8 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
* Portions Copyright (C) Philipp Kewisch */
|
|
|
|
import { strictParseInt, trunc, pad2 } from "./helpers.js";
|
|
// needed for typescript type resolution
|
|
// eslint-disable-next-line no-unused-vars
|
|
import Duration from "./duration.js";
|
|
import design from "./design.js";
|
|
|
|
/**
|
|
* This class represents the "utc-offset" value type, with various calculation and manipulation
|
|
* methods.
|
|
*
|
|
* @memberof ICAL
|
|
*/
|
|
class UtcOffset {
|
|
/**
|
|
* Creates a new {@link ICAL.UtcOffset} instance from the passed string.
|
|
*
|
|
* @param {String} aString The string to parse
|
|
* @return {Duration} The created utc-offset instance
|
|
*/
|
|
static fromString(aString) {
|
|
// -05:00
|
|
let options = {};
|
|
//TODO: support seconds per rfc5545 ?
|
|
options.factor = (aString[0] === '+') ? 1 : -1;
|
|
options.hours = strictParseInt(aString.slice(1, 3));
|
|
options.minutes = strictParseInt(aString.slice(4, 6));
|
|
|
|
return new UtcOffset(options);
|
|
}
|
|
|
|
/**
|
|
* Creates a new {@link ICAL.UtcOffset} instance from the passed seconds
|
|
* value.
|
|
*
|
|
* @param {Number} aSeconds The number of seconds to convert
|
|
*/
|
|
static fromSeconds(aSeconds) {
|
|
let instance = new UtcOffset();
|
|
instance.fromSeconds(aSeconds);
|
|
return instance;
|
|
}
|
|
|
|
/**
|
|
* Creates a new ICAL.UtcOffset instance.
|
|
*
|
|
* @param {Object} aData An object with members of the utc offset
|
|
* @param {Number=} aData.hours The hours for the utc offset
|
|
* @param {Number=} aData.minutes The minutes in the utc offset
|
|
* @param {Number=} aData.factor The factor for the utc-offset, either -1 or 1
|
|
*/
|
|
constructor(aData) {
|
|
this.fromData(aData);
|
|
}
|
|
|
|
/**
|
|
* The hours in the utc-offset
|
|
* @type {Number}
|
|
*/
|
|
hours = 0;
|
|
|
|
/**
|
|
* The minutes in the utc-offset
|
|
* @type {Number}
|
|
*/
|
|
minutes = 0;
|
|
|
|
/**
|
|
* The sign of the utc offset, 1 for positive offset, -1 for negative
|
|
* offsets.
|
|
* @type {Number}
|
|
*/
|
|
factor = 1;
|
|
|
|
/**
|
|
* The type name, to be used in the jCal object.
|
|
* @constant
|
|
* @type {String}
|
|
* @default "utc-offset"
|
|
*/
|
|
icaltype = "utc-offset";
|
|
|
|
/**
|
|
* Returns a clone of the utc offset object.
|
|
*
|
|
* @return {UtcOffset} The cloned object
|
|
*/
|
|
clone() {
|
|
return UtcOffset.fromSeconds(this.toSeconds());
|
|
}
|
|
|
|
/**
|
|
* Sets up the current instance using members from the passed data object.
|
|
*
|
|
* @param {Object} aData An object with members of the utc offset
|
|
* @param {Number=} aData.hours The hours for the utc offset
|
|
* @param {Number=} aData.minutes The minutes in the utc offset
|
|
* @param {Number=} aData.factor The factor for the utc-offset, either -1 or 1
|
|
*/
|
|
fromData(aData) {
|
|
if (aData) {
|
|
for (let [key, value] of Object.entries(aData)) {
|
|
this[key] = value;
|
|
}
|
|
}
|
|
this._normalize();
|
|
}
|
|
|
|
/**
|
|
* Sets up the current instance from the given seconds value. The seconds
|
|
* value is truncated to the minute. Offsets are wrapped when the world
|
|
* ends, the hour after UTC+14:00 is UTC-12:00.
|
|
*
|
|
* @param {Number} aSeconds The seconds to convert into an offset
|
|
*/
|
|
fromSeconds(aSeconds) {
|
|
let secs = Math.abs(aSeconds);
|
|
|
|
this.factor = aSeconds < 0 ? -1 : 1;
|
|
this.hours = trunc(secs / 3600);
|
|
|
|
secs -= (this.hours * 3600);
|
|
this.minutes = trunc(secs / 60);
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Convert the current offset to a value in seconds
|
|
*
|
|
* @return {Number} The offset in seconds
|
|
*/
|
|
toSeconds() {
|
|
return this.factor * (60 * this.minutes + 3600 * this.hours);
|
|
}
|
|
|
|
/**
|
|
* Compare this utc offset with another one.
|
|
*
|
|
* @param {UtcOffset} other The other offset to compare with
|
|
* @return {Number} -1, 0 or 1 for less/equal/greater
|
|
*/
|
|
compare(other) {
|
|
let a = this.toSeconds();
|
|
let b = other.toSeconds();
|
|
return (a > b) - (b > a);
|
|
}
|
|
|
|
_normalize() {
|
|
// Range: 97200 seconds (with 1 hour inbetween)
|
|
let secs = this.toSeconds();
|
|
let factor = this.factor;
|
|
while (secs < -43200) { // = UTC-12:00
|
|
secs += 97200;
|
|
}
|
|
while (secs > 50400) { // = UTC+14:00
|
|
secs -= 97200;
|
|
}
|
|
|
|
this.fromSeconds(secs);
|
|
|
|
// Avoid changing the factor when on zero seconds
|
|
if (secs == 0) {
|
|
this.factor = factor;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The iCalendar string representation of this utc-offset.
|
|
* @return {String}
|
|
*/
|
|
toICALString() {
|
|
return design.icalendar.value['utc-offset'].toICAL(this.toString());
|
|
}
|
|
|
|
/**
|
|
* The string representation of this utc-offset.
|
|
* @return {String}
|
|
*/
|
|
toString() {
|
|
return (this.factor == 1 ? "+" : "-") + pad2(this.hours) + ':' + pad2(this.minutes);
|
|
}
|
|
}
|
|
export default UtcOffset;
|