184 lines
5.9 KiB
JavaScript
184 lines
5.9 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 UtcOffset from "./utc_offset.js";
|
|
import Time from "./time.js";
|
|
import Timezone from "./timezone.js";
|
|
import design from "./design.js";
|
|
import { pad2, strictParseInt } from "./helpers.js";
|
|
|
|
/**
|
|
* Describes a vCard time, which has slight differences to the ICAL.Time.
|
|
* Properties can be null if not specified, for example for dates with
|
|
* reduced accuracy or truncation.
|
|
*
|
|
* Note that currently not all methods are correctly re-implemented for
|
|
* VCardTime. For example, comparison will have undefined results when some
|
|
* members are null.
|
|
*
|
|
* Also, normalization is not yet implemented for this class!
|
|
*
|
|
* @memberof ICAL
|
|
* @extends {Time}
|
|
*/
|
|
class VCardTime extends Time {
|
|
/**
|
|
* Returns a new ICAL.VCardTime instance from a date and/or time string.
|
|
*
|
|
* @param {String} aValue The string to create from
|
|
* @param {String} aIcalType The type for this instance, e.g. date-and-or-time
|
|
* @return {VCardTime} The date/time instance
|
|
*/
|
|
static fromDateAndOrTimeString(aValue, aIcalType) {
|
|
function part(v, s, e) {
|
|
return v ? strictParseInt(v.slice(s, s + e)) : null;
|
|
}
|
|
let parts = aValue.split('T');
|
|
let dt = parts[0], tmz = parts[1];
|
|
let splitzone = tmz ? design.vcard.value.time._splitZone(tmz) : [];
|
|
let zone = splitzone[0], tm = splitzone[1];
|
|
|
|
let dtlen = dt ? dt.length : 0;
|
|
let tmlen = tm ? tm.length : 0;
|
|
|
|
let hasDashDate = dt && dt[0] == '-' && dt[1] == '-';
|
|
let hasDashTime = tm && tm[0] == '-';
|
|
|
|
let o = {
|
|
year: hasDashDate ? null : part(dt, 0, 4),
|
|
month: hasDashDate && (dtlen == 4 || dtlen == 7) ? part(dt, 2, 2) : dtlen == 7 ? part(dt, 5, 2) : dtlen == 10 ? part(dt, 5, 2) : null,
|
|
day: dtlen == 5 ? part(dt, 3, 2) : dtlen == 7 && hasDashDate ? part(dt, 5, 2) : dtlen == 10 ? part(dt, 8, 2) : null,
|
|
|
|
hour: hasDashTime ? null : part(tm, 0, 2),
|
|
minute: hasDashTime && tmlen == 3 ? part(tm, 1, 2) : tmlen > 4 ? hasDashTime ? part(tm, 1, 2) : part(tm, 3, 2) : null,
|
|
second: tmlen == 4 ? part(tm, 2, 2) : tmlen == 6 ? part(tm, 4, 2) : tmlen == 8 ? part(tm, 6, 2) : null
|
|
};
|
|
|
|
if (zone == 'Z') {
|
|
zone = Timezone.utcTimezone;
|
|
} else if (zone && zone[3] == ':') {
|
|
zone = UtcOffset.fromString(zone);
|
|
} else {
|
|
zone = null;
|
|
}
|
|
|
|
return new VCardTime(o, zone, aIcalType);
|
|
}
|
|
|
|
|
|
/**
|
|
* Creates a new ICAL.VCardTime instance.
|
|
*
|
|
* @param {Object} data The data for the time instance
|
|
* @param {Number=} data.year The year for this date
|
|
* @param {Number=} data.month The month for this date
|
|
* @param {Number=} data.day The day for this date
|
|
* @param {Number=} data.hour The hour for this date
|
|
* @param {Number=} data.minute The minute for this date
|
|
* @param {Number=} data.second The second for this date
|
|
* @param {Timezone|UtcOffset} zone The timezone to use
|
|
* @param {String} icaltype The type for this date/time object
|
|
*/
|
|
constructor(data, zone, icaltype) {
|
|
super(data, zone);
|
|
this.icaltype = icaltype || "date-and-or-time";
|
|
}
|
|
|
|
/**
|
|
* The class identifier.
|
|
* @constant
|
|
* @type {String}
|
|
* @default "vcardtime"
|
|
*/
|
|
icalclass = "vcardtime";
|
|
|
|
/**
|
|
* The type name, to be used in the jCal object.
|
|
* @type {String}
|
|
* @default "date-and-or-time"
|
|
*/
|
|
icaltype = "date-and-or-time";
|
|
|
|
/**
|
|
* Returns a clone of the vcard date/time object.
|
|
*
|
|
* @return {VCardTime} The cloned object
|
|
*/
|
|
clone() {
|
|
return new VCardTime(this._time, this.zone, this.icaltype);
|
|
}
|
|
|
|
_normalize() {
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
utcOffset() {
|
|
if (this.zone instanceof UtcOffset) {
|
|
return this.zone.toSeconds();
|
|
} else {
|
|
return Time.prototype.utcOffset.apply(this, arguments);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns an RFC 6350 compliant representation of this object.
|
|
*
|
|
* @return {String} vcard date/time string
|
|
*/
|
|
toICALString() {
|
|
return design.vcard.value[this.icaltype].toICAL(this.toString());
|
|
}
|
|
|
|
/**
|
|
* The string representation of this date/time, in jCard form
|
|
* (including : and - separators).
|
|
* @return {String}
|
|
*/
|
|
toString() {
|
|
let y = this.year, m = this.month, d = this.day;
|
|
let h = this.hour, mm = this.minute, s = this.second;
|
|
|
|
let hasYear = y !== null, hasMonth = m !== null, hasDay = d !== null;
|
|
let hasHour = h !== null, hasMinute = mm !== null, hasSecond = s !== null;
|
|
|
|
let datepart = (hasYear ? pad2(y) + (hasMonth || hasDay ? '-' : '') : (hasMonth || hasDay ? '--' : '')) +
|
|
(hasMonth ? pad2(m) : '') +
|
|
(hasDay ? '-' + pad2(d) : '');
|
|
let timepart = (hasHour ? pad2(h) : '-') + (hasHour && hasMinute ? ':' : '') +
|
|
(hasMinute ? pad2(mm) : '') + (!hasHour && !hasMinute ? '-' : '') +
|
|
(hasMinute && hasSecond ? ':' : '') +
|
|
(hasSecond ? pad2(s) : '');
|
|
|
|
let zone;
|
|
if (this.zone === Timezone.utcTimezone) {
|
|
zone = 'Z';
|
|
} else if (this.zone instanceof UtcOffset) {
|
|
zone = this.zone.toString();
|
|
} else if (this.zone === Timezone.localTimezone) {
|
|
zone = '';
|
|
} else if (this.zone instanceof Timezone) {
|
|
let offset = UtcOffset.fromSeconds(this.zone.utcOffset(this));
|
|
zone = offset.toString();
|
|
} else {
|
|
zone = '';
|
|
}
|
|
|
|
switch (this.icaltype) {
|
|
case "time":
|
|
return timepart + zone;
|
|
case "date-and-or-time":
|
|
case "date-time":
|
|
return datepart + (timepart == '--' ? '' : 'T' + timepart + zone);
|
|
case "date":
|
|
return datepart;
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
export default VCardTime;
|