Javascript parser for ics (rfc5545) and vcard (rfc6350) data
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Comprehensive timezone handling with support for VTIMEZONE components, UTC offset calculations, and timezone conversions. These classes enable proper timezone-aware date and time operations in compliance with RFC 5545.
Timezone representation providing offset calculations and conversion utilities for iCalendar timezone handling.
/**
* Timezone handling
* @param data - Timezone initialization data
*/
class Timezone {
constructor(data?: object);
// Properties
tzid: string; // Timezone identifier
component: Component; // VTIMEZONE component
expandedUntilYear: number; // Year until which timezone is expanded
// Static methods
static convert_time(tt: Time, from_zone: Timezone, to_zone: Timezone): Time;
static fromData(aData: object): Timezone;
static get utcTimezone(): Timezone;
static get localTimezone(): Timezone;
// Instance methods
fromData(aData: object): void;
utcOffset(tt: Time): number;
toString(): string;
}Usage Examples:
import ICAL from "ical.js";
// Get built-in timezones
const utc = ICAL.Timezone.utcTimezone;
const local = ICAL.Timezone.localTimezone;
console.log(utc.tzid); // "UTC"
console.log(local.tzid); // System timezone ID
// Create timezone from VTIMEZONE component
const timezoneData = `BEGIN:VTIMEZONE
TZID:America/New_York
BEGIN:DAYLIGHT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
TZNAME:EDT
DTSTART:20070311T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
TZNAME:EST
DTSTART:20071104T020000
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
END:STANDARD
END:VTIMEZONE`;
const tzComponent = ICAL.Component.fromString(timezoneData);
const nyTimezone = new ICAL.Timezone(tzComponent);
console.log(nyTimezone.tzid); // "America/New_York"
// Get UTC offset for specific time
const summerTime = ICAL.Time.fromString("20230715T120000");
const winterTime = ICAL.Time.fromString("20231215T120000");
const summerOffset = nyTimezone.utcOffset(summerTime); // -14400 (EDT: -4 hours)
const winterOffset = nyTimezone.utcOffset(winterTime); // -18000 (EST: -5 hours)
console.log(`Summer offset: ${summerOffset / 3600} hours`); // -4
console.log(`Winter offset: ${winterOffset / 3600} hours`); // -5
// Convert time between timezones
const utcTime = ICAL.Time.fromString("20230715T160000Z");
const nyTime = ICAL.Timezone.convert_time(utcTime, utc, nyTimezone);
console.log(`UTC: ${utcTime.toString()}`); // "2023-07-15T16:00:00Z"
console.log(`NY: ${nyTime.toString()}`); // "2023-07-15T12:00:00"
// Convert back to UTC
const backToUtc = ICAL.Timezone.convert_time(nyTime, nyTimezone, utc);
console.log(`Back to UTC: ${backToUtc.toString()}`); // "2023-07-15T16:00:00Z"
// Create timezone from data
const customTz = ICAL.Timezone.fromData({
tzid: "Custom/Example",
// Additional timezone data
});Singleton timezone registry for managing and accessing timezone definitions across the application.
/**
* Timezone registry singleton
*/
const TimezoneService: {
// Properties
readonly count: number; // Number of registered timezones
// Methods
reset(): void;
has(tzid: string): boolean;
get(tzid: string): Timezone | null;
register(timezone: Timezone | Component, name?: string): void;
remove(tzid: string): boolean;
};Usage Examples:
import ICAL from "ical.js";
// Check available timezones
console.log(ICAL.TimezoneService.count); // Number of registered timezones
// Check if timezone exists
const hasNY = ICAL.TimezoneService.has("America/New_York");
console.log(hasNY); // true/false
// Get timezone by ID
const nyTimezone = ICAL.TimezoneService.get("America/New_York");
if (nyTimezone) {
console.log(nyTimezone.tzid); // "America/New_York"
}
// Register new timezone from component
const timezoneComponent = ICAL.Component.fromString(`BEGIN:VTIMEZONE
TZID:Europe/London
BEGIN:DAYLIGHT
TZOFFSETFROM:+0000
TZOFFSETTO:+0100
TZNAME:BST
DTSTART:20070325T010000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:+0100
TZOFFSETTO:+0000
TZNAME:GMT
DTSTART:20071028T020000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
END:STANDARD
END:VTIMEZONE`);
ICAL.TimezoneService.register(timezoneComponent);
// Verify registration
console.log(ICAL.TimezoneService.has("Europe/London")); // true
console.log(ICAL.TimezoneService.count); // Increased by 1
// Register timezone object with custom name
const customTimezone = new ICAL.Timezone(timezoneComponent);
ICAL.TimezoneService.register(customTimezone, "Custom/London");
// Remove timezone
const removed = ICAL.TimezoneService.remove("Custom/London");
console.log(removed); // true if successfully removed
// Reset to default timezones
ICAL.TimezoneService.reset();
console.log(ICAL.TimezoneService.count); // Back to default count
// Working with calendar components and timezones
const vcalendar = new ICAL.Component("vcalendar");
vcalendar.addSubcomponent(timezoneComponent);
// Register all timezones from a calendar
const allSubcomponents = vcalendar.getAllSubcomponents("vtimezone");
allSubcomponents.forEach(tzComponent => {
ICAL.TimezoneService.register(tzComponent);
});
// Use timezone service with events
const event = new ICAL.Component("vevent");
event.addPropertyWithValue("dtstart", ICAL.Time.fromString("20230715T120000"));
const startProp = event.getFirstProperty("dtstart");
startProp.setParameter("tzid", "Europe/London");
// Get timezone for the event
const eventTimezone = ICAL.TimezoneService.get("Europe/London");
if (eventTimezone) {
const startTime = startProp.getFirstValue();
startTime.zone = eventTimezone;
console.log(`Event starts at ${startTime.toString()} in ${eventTimezone.tzid}`);
}UTC offset representation for handling timezone offsets in hours and minutes.
/**
* UTC offset representation
* @param aData - Offset initialization data
*/
class UtcOffset {
constructor(aData?: object);
// Properties
hours: number; // Offset hours
minutes: number; // Offset minutes
factor: number; // Sign factor (+1 or -1)
// Static methods
static fromString(aString: string): UtcOffset;
static fromSeconds(aSeconds: number): UtcOffset;
// Instance methods
clone(): UtcOffset;
fromData(aData: object): void;
fromSeconds(aSeconds: number): void;
toSeconds(): number;
compare(other: UtcOffset): number;
toICALString(): string;
toString(): string;
}Usage Examples:
import ICAL from "ical.js";
// Create offset from string
const offset1 = ICAL.UtcOffset.fromString("-0500"); // -5 hours
const offset2 = ICAL.UtcOffset.fromString("+0230"); // +2 hours 30 minutes
console.log(offset1.hours); // 5
console.log(offset1.minutes); // 0
console.log(offset1.factor); // -1
console.log(offset2.hours); // 2
console.log(offset2.minutes); // 30
console.log(offset2.factor); // 1
// Create from seconds
const offset3 = ICAL.UtcOffset.fromSeconds(-18000); // -5 hours
console.log(offset3.toICALString()); // "-0500"
// Create from data
const offset4 = new ICAL.UtcOffset({
hours: 3,
minutes: 45,
factor: 1
});
// Convert to seconds
console.log(offset1.toSeconds()); // -18000 (-5 hours)
console.log(offset2.toSeconds()); // 9000 (+2.5 hours)
// Compare offsets
console.log(offset1.compare(offset2)); // -1 (offset1 < offset2)
console.log(offset2.compare(offset1)); // 1 (offset2 > offset1)
// String representations
console.log(offset1.toICALString()); // "-0500"
console.log(offset1.toString()); // "-0500"
console.log(offset2.toICALString()); // "+0230"
console.log(offset2.toString()); // "+0230"
// Clone offset
const offsetCopy = offset1.clone();
console.log(offsetCopy.toICALString()); // "-0500"
// Modify offset
offset4.fromSeconds(7200); // Change to +2 hours
console.log(offset4.toICALString()); // "+0200"
// Working with timezone components
const vtimezone = new ICAL.Component("vtimezone");
vtimezone.addPropertyWithValue("tzid", "Custom/Offset");
const standard = new ICAL.Component("standard");
standard.addPropertyWithValue("tzoffsetfrom", offset2);
standard.addPropertyWithValue("tzoffsetto", offset1);
standard.addPropertyWithValue("dtstart", ICAL.Time.fromString("20231029T020000"));
vtimezone.addSubcomponent(standard);
// Extract offsets from properties
const offsetFromProp = standard.getFirstProperty("tzoffsetfrom");
const offsetToProp = standard.getFirstProperty("tzoffsetto");
console.log(offsetFromProp.getFirstValue().toICALString()); // "+0230"
console.log(offsetToProp.getFirstValue().toICALString()); // "-0500"import ICAL from "ical.js";
// Helper function to update timezones in a calendar
ICAL.helpers.updateTimezones(vcalendar);
// Example: Processing calendar with timezone definitions
const calendarString = `BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example//Example//EN
BEGIN:VTIMEZONE
TZID:America/New_York
BEGIN:STANDARD
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
TZNAME:EST
DTSTART:20071104T020000
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
END:STANDARD
BEGIN:DAYLIGHT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
TZNAME:EDT
DTSTART:20070311T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
END:DAYLIGHT
END:VTIMEZONE
BEGIN:VEVENT
UID:event@example.com
DTSTART;TZID=America/New_York:20230715T120000
DTEND;TZID=America/New_York:20230715T130000
SUMMARY:Meeting in NY timezone
END:VEVENT
END:VCALENDAR`;
const calendar = ICAL.Component.fromString(calendarString);
// Update timezones processes VTIMEZONE components
ICAL.helpers.updateTimezones(calendar);
// Now events can use the timezone
const event = calendar.getFirstSubcomponent("vevent");
const startTime = event.getFirstPropertyValue("dtstart");
console.log(startTime.zone.tzid); // "America/New_York"
console.log(startTime.toString()); // Local time in NY timezoneimport ICAL from "ical.js";
// Convert event times to different timezones
function convertEventTimezone(event, targetTimezone) {
const startTime = event.startDate;
const endTime = event.endDate;
const newStart = ICAL.Timezone.convert_time(startTime, startTime.zone, targetTimezone);
const newEnd = ICAL.Timezone.convert_time(endTime, endTime.zone, targetTimezone);
event.startDate = newStart;
event.endDate = newEnd;
return event;
}
// Get timezone offset for display
function getTimezoneDisplay(timezone, time) {
const offset = timezone.utcOffset(time);
const offsetObj = ICAL.UtcOffset.fromSeconds(offset);
return `${timezone.tzid} (UTC${offsetObj.toString()})`;
}
// Check if time is in daylight saving time
function isDST(timezone, time) {
// Compare with standard time offset
const winterTime = new ICAL.Time({
year: time.year,
month: 12, // December
day: 15,
hour: 12
});
const currentOffset = timezone.utcOffset(time);
const winterOffset = timezone.utcOffset(winterTime);
return currentOffset !== winterOffset;
}