diff --git a/node-calendar/node-calendar-tests.ts b/node-calendar/node-calendar-tests.ts new file mode 100644 index 0000000000..b57cd9f845 --- /dev/null +++ b/node-calendar/node-calendar-tests.ts @@ -0,0 +1,153 @@ +/// + +import node_calendar = require('node-calendar'); + +var cal = new node_calendar.Calendar(node_calendar.SUNDAY); + +assert(cal.getfirstweekday() == node_calendar.SUNDAY); + +cal.setfirstweekday(node_calendar.MONDAY); + +assert(cal.getfirstweekday() == node_calendar.MONDAY); + +assert(node_calendar.MONDAY == 0); +assert(node_calendar.TUESDAY == 1); +assert(node_calendar.WEDNESDAY == 2); +assert(node_calendar.THURSDAY == 3); +assert(node_calendar.FRIDAY == 4); +assert(node_calendar.SATURDAY == 5); +assert(node_calendar.SUNDAY == 6); + +assert(node_calendar.day_name[node_calendar.MONDAY] == 'Monday'); +assert(node_calendar.day_name[node_calendar.TUESDAY] == 'Tuesday'); +assert(node_calendar.day_name[node_calendar.WEDNESDAY] == 'Wednesday'); +assert(node_calendar.day_name[node_calendar.THURSDAY] == 'Thursday'); +assert(node_calendar.day_name[node_calendar.FRIDAY] == 'Friday'); +assert(node_calendar.day_name[node_calendar.SATURDAY] == 'Saturday'); +assert(node_calendar.day_name[node_calendar.SUNDAY] == 'Sunday'); + +assert(node_calendar.day_abbr[node_calendar.MONDAY] == 'Mon'); +assert(node_calendar.day_abbr[node_calendar.TUESDAY] == 'Tue'); +assert(node_calendar.day_abbr[node_calendar.WEDNESDAY] == 'Wed'); +assert(node_calendar.day_abbr[node_calendar.THURSDAY] == 'Thu'); +assert(node_calendar.day_abbr[node_calendar.FRIDAY] == 'Fri'); +assert(node_calendar.day_abbr[node_calendar.SATURDAY] == 'Sat'); +assert(node_calendar.day_abbr[node_calendar.SUNDAY] == 'Sun'); + +assert(node_calendar.JANUARY == 1); +assert(node_calendar.FEBRUARY == 2); +assert(node_calendar.MARCH == 3); +assert(node_calendar.APRIL == 4); +assert(node_calendar.MAY == 5); +assert(node_calendar.JUNE == 6); +assert(node_calendar.JULY == 7); +assert(node_calendar.AUGUST == 8); +assert(node_calendar.SEPTEMBER == 9); +assert(node_calendar.OCTOBER == 10); +assert(node_calendar.NOVEMBER == 11); +assert(node_calendar.DECEMBER == 12); + +assert(node_calendar.month_name[0] == ''); +assert(node_calendar.month_name[node_calendar.JANUARY] == 'January'); +assert(node_calendar.month_name[node_calendar.FEBRUARY] == 'February'); +assert(node_calendar.month_name[node_calendar.MARCH] == 'March'); +assert(node_calendar.month_name[node_calendar.APRIL] == 'April'); +assert(node_calendar.month_name[node_calendar.MAY] == 'May'); +assert(node_calendar.month_name[node_calendar.JUNE] == 'June'); +assert(node_calendar.month_name[node_calendar.JULY] == 'July'); +assert(node_calendar.month_name[node_calendar.AUGUST] == 'August'); +assert(node_calendar.month_name[node_calendar.SEPTEMBER] == 'September'); +assert(node_calendar.month_name[node_calendar.OCTOBER] == 'October'); +assert(node_calendar.month_name[node_calendar.NOVEMBER] == 'November'); +assert(node_calendar.month_name[node_calendar.DECEMBER] == 'December'); + +assert(node_calendar.month_abbr[0] == ''); +assert(node_calendar.month_abbr[node_calendar.JANUARY] == 'Jan'); +assert(node_calendar.month_abbr[node_calendar.FEBRUARY] == 'Feb'); +assert(node_calendar.month_abbr[node_calendar.MARCH] == 'Mar'); +assert(node_calendar.month_abbr[node_calendar.APRIL] == 'Apr'); +assert(node_calendar.month_abbr[node_calendar.MAY] == 'May'); +assert(node_calendar.month_abbr[node_calendar.JUNE] == 'Jun'); +assert(node_calendar.month_abbr[node_calendar.JULY] == 'Jul'); +assert(node_calendar.month_abbr[node_calendar.AUGUST] == 'Aug'); +assert(node_calendar.month_abbr[node_calendar.SEPTEMBER] == 'Sep'); +assert(node_calendar.month_abbr[node_calendar.OCTOBER] == 'Oct'); +assert(node_calendar.month_abbr[node_calendar.NOVEMBER] == 'Nov'); +assert(node_calendar.month_abbr[node_calendar.DECEMBER] == 'Dec'); + +cal.itermonthdates(2015, node_calendar.JANUARY).forEach(assertIsDate); +cal.itermonthdays(2014, node_calendar.FEBRUARY).forEach(assertIsNumber); +cal.itermonthdays2(2013, node_calendar.MARCH).forEach(assertDayOfWeekMonth); +cal.iterweekdays().forEach(assertIsNumber); + +assertMonthGrid(cal.monthdatescalendar(2012, node_calendar.APRIL), assertIsDate); +assertMonthGrid(cal.monthdays2calendar(2011, node_calendar.MAY), assertDayOfWeekMonth); +assertMonthGrid(cal.monthdayscalendar(2010, node_calendar.JUNE), assertIsNumber); + +assertYearGrid(cal.yeardatescalendar(2009, 3), assertIsDate); +assertYearGrid(cal.yeardays2calendar(2008, 2), assertDayOfWeekMonth); +assertYearGrid(cal.yeardayscalendar(2007, 4), assertIsNumber); + +node_calendar.setlocale('en_US'); + +assertIsError(new node_calendar.IllegalDayError()); +assertIsError(new node_calendar.IllegalLocaleError()); +assertIsError(new node_calendar.IllegalMonthError()); +assertIsError(new node_calendar.IllegalTimeError); +assertIsError(new node_calendar.IllegalWeekdayError()); + +assertIsBoolean(node_calendar.isleap(2000)); +assertIsNumber(node_calendar.weekday(2015, node_calendar.JULY, 7)); +assertIsNumber(node_calendar.leapdays(2000, 2010)); + +node_calendar.monthrange(2015, node_calendar.JANUARY).forEach(assertIsNumber); + +var timegmt:[number,number,number,number,number,number] = [2014, node_calendar.JULY, 7, 12, 41, 59]; +assertIsNumber(node_calendar.timegm(timegmt)); + + +// FUNCTIONS ------------------------------------------------------------------ +function assertIsDate(d: Date) { + assert(d instanceof Date, 'Should be a date'); +} + +function assertIsNumber(n: number) { + assert(typeof n == 'number', 'Should be a number'); +} + +function assertIsBoolean(b: boolean) { + assert(typeof b == 'boolean', 'Should be a boolean'); +} + +function assertDayOfWeekMonth(d: [number, number]) { + assert(d instanceof Array, 'Day of weak/month should be an array'); + assert(d.length == 2, 'Day of weak/month array should contain 2 items'); + assert(typeof d[0] == 'number', 'Day of month should be a number'); + assert(typeof d[1] == 'number', 'Day of week should be a number'); +} + +function assertWeekRow(row: IWeekRow, assertItemType: (item: T) => void) { + row.forEach(assertItemType); +} + +function assertMonthGrid(grid: IMonthGrid, assertItemType: (item: T) => void) { + grid.forEach(wr => assertWeekRow(wr, assertItemType)); +} + +function assertMonthRow(row: IMonthRow, assertItemType: (item: T) => void) { + row.forEach(mg => assertMonthGrid(mg, assertItemType)); +} + +function assertYearGrid(grid: IYearGrid, assertItemType: (item: T) => void) { + grid.forEach(mr => assertMonthRow(mr, assertItemType)); +} + +function assert(condition: boolean, msg?: string): void { + if (condition) return; + throw new Error(msg); +} + +function assertIsError(error: Error) { + assert(typeof error.name == 'string', 'Error name should exist and be a string'); + assert(typeof error.message == 'string', 'Error message should exist and be a string'); +} \ No newline at end of file diff --git a/node-calendar/node-calendar.d.ts b/node-calendar/node-calendar.d.ts new file mode 100755 index 0000000000..204ec69216 --- /dev/null +++ b/node-calendar/node-calendar.d.ts @@ -0,0 +1,402 @@ +// Type definitions for node-calendar v0.1.4 +// Project: https://www.npmjs.com/package/node-calendar +// Definitions by: Luzian Zagadinow +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +interface IWeekRow extends Array { + [dayIndex: number]: T; +} + +interface IMonthGrid extends Array> { + [weekRowIndex: number]: IWeekRow; +} + +interface IMonthRow extends Array> { + [monthColumnIndex: number]: IMonthGrid; +} + +interface IYearGrid extends Array> { + [monthRowIndex: number]: IMonthRow; +} + +/** + * This module allows you to output calendars like the Unix cal program, and provides + * additional useful functions related to the calendar. By default, these calendars + * have Monday as the first day of the week, and Sunday as the last (the European + * convention). Use setfirstweekday() to set the first day of the week to Sunday + * (6) or to any other weekday. Parameters that specify dates are given as integers. + */ +declare module 'node-calendar' { + /** 0 */ + export var MONDAY: number; + + /** 1 */ + export var TUESDAY: number; + + /** 2 */ + export var WEDNESDAY: number; + + /** 3 */ + export var THURSDAY: number; + + /** 4 */ + export var FRIDAY: number; + + /** 5 */ + export var SATURDAY: number; + + /** 6 */ + export var SUNDAY: number; + + + /** 1 */ + export var JANUARY: number; + + /** 2 */ + export var FEBRUARY: number; + + /** 3 */ + export var MARCH: number; + + /** 4 */ + export var APRIL: number; + + /** 5 */ + export var MAY: number; + + /** 6 */ + export var JUNE: number; + + /** 7 */ + export var JULY: number; + + /** 8 */ + export var AUGUST: number; + + /** 9 */ + export var SEPTEMBER: number; + + /** 10 */ + export var OCTOBER: number; + + /** 11 */ + export var NOVEMBER: number; + + /** 12 */ + export var DECEMBER: number; + + /** + * [ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ] + */ + export var day_name: string[]; + + /** + * [ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' ] + */ + export var day_abbr: string[]; + + /** + * [ '', 'January', 'February', 'March', + * 'April', 'May', 'June', 'July', 'August', + * 'September', 'October', 'November', 'December' ] + */ + export var month_name: string[]; + + /** + * [ '', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', + * 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ] + */ + export var month_abbr: string[]; + + /** + * Base calendar class. This class doesn't do any formatting. It simply provides + * data to subclasses. + */ + export class Calendar { + /** + * @param {number} firstweekday + * Numerical day of the week the calendar weeks should start. + * (0=MON, 1=TUE, ...) Default: 0 + */ + constructor(firstweekday?: number); + + /** + * Numerical day of the week the calendar weeks should start. + * (0=MON, 1=TUE, ...) + * + * @method getfirstweekday + */ + getfirstweekday(): number; + + /** + * Numerical day of the week the calendar weeks should start. + * (0=MON, 1=TUE, ...) + * + * @param {number} firstweekday + * Numerical day of the week the calendar weeks should start. + * (0=MON, 1=TUE, ...) Default: 0 + */ + setfirstweekday(firstweekday: number): void; + + /** + * One week of weekday numbers starting with the configured first one. + */ + iterweekdays(): number[]; + + /** + * Dates for one month. The array will contain Date values and will always + * iterate through complete weeks, so it will yield dates outside the + * specified month. + * + * @param {number} year + * Year for which the calendar should be generated. + * + * @param {number} month + * Month for which the calendar should be generated. + */ + itermonthdates(year: number, month: number): Date[]; + + /** + * Like itermonthdates(), but will yield day numbers. For days outside + * the specified month the day number is 0. + * + * @param {number} year + * Year for which the calendar should be generated. + * + * @param {number} month + * Month for which the calendar should be generated. + */ + itermonthdays(year: number, month: number): number[]; + + /** + * Like itermonthdates(), but will yield [day number, weekday number] + * arrays. For days outside the specified month the day number is 0. + * + * @param {number} year + * Year for which the calendar should be generated. + * + * @param {number} month + * Month for which the calendar should be generated. + */ + itermonthdays2(year: number, month: number): [number, number][]; + + /** + * A matrix (array of array) representing a month's calendar. + * Each row represents a week; week entries are Date values. + * + * @param {number} year + * Year for which the calendar should be generated. + * + * @param {number} month + * Month for which the calendar should be generated. + */ + monthdatescalendar(year: number, month: number): IMonthGrid; + + /** + * A matrix representing a month's calendar. Each row represents a week; + * days outside this month are zero. + * + * @param {number} year + * Year for which the calendar should be generated. + * + * @param {number} month + * Month for which the calendar should be generated. + */ + monthdayscalendar(year: number, month: number): IMonthGrid; + + /** + * Return a matrix representing a month's calendar. Each row represents + * a week; week entries are [day number, weekday number] arrays. Day numbers + * outside this month are zero. + * + * @param {number} year + * Year for which the calendar should be generated. + * + * @param {number} month + * Month for which the calendar should be generated. + */ + monthdays2calendar(year: number, month: number): IMonthGrid<[number, number]>; + + /** + * The specified year ready for formatting. The return value is an array + * of month rows. Each month row contains up to width months. Each month + * contains between 4 and 6 weeks and each week contains 1-7 days. Days + * are Date objects. + * + * @param {number} year + * Year for which the calendar should be generated. + * + * @param {number} width + * The number of months to include in each row. Default: 3 + */ + yeardatescalendar(year: number, width?: number): IYearGrid; + + /** + * the specified year ready for formatting (similar to yeardatescalendar()). + * Entries in the week arrays are day numbers. Day numbers outside this + * month are zero. + * + * @param {number} year + * Year for which the calendar should be generated + * + * @param {number} width + * The number of months to include in each row. Default: 3 + */ + yeardayscalendar(year: number, width?: number): IYearGrid; + + /** + * The specified year ready for formatting (similar to yeardatescalendar()). + * Entries in the week arrays are [day number, weekday number] arrays. + * Day numbers outside this month are zero. + * + * @param {number} year + * Year for which the calendar should be generated + * + * @param {number} width + * The number of months to include in each row. Default: 3 + */ + yeardays2calendar(year: number, width?: number): IYearGrid<[number, number]>; + } + + /** + * @param {number} year + * Year to test. + * + * @return {boolean} + * true for leap years, false for non-leap years. + */ + export function isleap(year: number): boolean; + + /** + * @param {number} y1 + * Beginning year in the range to test. + * + * @param {number} y2 + * Ending year in the range to test. + * + * @return {number} + * Number of leap years in range (y1...y2). Assumes y1 <= y2. + */ + export function leapdays(y1: number, y2: number): number; + + /** + * @param {number} year + * Year for which the range should be calculated. + * + * @param {number} month + * Month for which the range should be calculated. + * + * @throws {IllegalMonthError} if the provided month is invalid. + * + * @return {[number, number]} + * starting weekday (0-6 ~ Mon-Sun) and number of days (28-31) for year, month. + */ + export function monthrange(year: number, month: number): [number, number]; + + /** + * Sets the locale for use in extracting month and weekday names. + * + * @param {string} locale + * Locale to set on the calendar object. Default: en_US + * + * @throws {IllegalLocaleError} if the provided locale is invalid. + */ + export function setlocale(locale?: string): void; + + /** + * Unrelated but handy function to calculate Unix timestamp from GMT. + * + * @param timegmt {[number, number, number, number, number, number]} + * An array containing the elements from a time structure dataset. + * Format: [tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec] + * + * @throws {IllegalMonthError} if the provided month element is invalid. + * + * @throws {IllegalDayError} if the provided day element is invalid. + * + * @throws {IllegalTimeError} if any of the the provided time elements are invalid. + * + * @return {number} + * Unix timestamp from GMT. + */ + export function timegm(timegmt: [number, number, number, number, number, number]): number; + + /** + * @param {number} year + * Year for which the weekday should be calculated. + * + * @param {number} month + * Month for which the weekday should be calculated. + * + * @param {number} day + * Day for which the weekday should be calculated. + * + * @throws {IllegalMonthError} if the provided month element is invalid. + * + * @throws {IllegalDayError} if the provided day element is invalid. + * + * @return {number} + * weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12), day (1-31). + */ + export function weekday(year: number, month: number, day: number): number; + + /** Error indicating a nonexistent or unsupported locale specified. */ + export class IllegalLocaleError implements Error { + public name: string; + public message: string; + + /** + * @param {string} message + * Optional custom error message. + */ + constructor(message?: string) + } + + /** Error indicating a day index specified outside of the valid range. */ + export class IllegalDayError implements Error { + public name: string; + public message: string; + + /** + * @param {string} message + * Optional custom error message. + */ + constructor(message?: string) + } + + /** Error indicating a month index specified outside of the expected range (1-12 ~ Jan-Dec). */ + export class IllegalMonthError implements Error { + public name: string; + public message: string; + + /** + * @param {string} message + * Optional custom error message. + */ + constructor(message?: string) + } + + /** Error indicating a time element is outside of the valid range. */ + export class IllegalTimeError implements Error { + public name: string; + public message: string; + + /** + * @param {string} message + * Optional custom error message. + */ + constructor(message?: string) + } + + /** Error indicating a weekday index specified outside of the expected range (0-6 ~ Mon-Sun). */ + export class IllegalWeekdayError implements Error { + public name: string; + public message: string; + + /** + * @param {string} message + * Optional custom error message. + */ + constructor(message?: string) + } +} \ No newline at end of file