import {Calendar, PlainDate, ZonedDateTime} from '@/'; import importer from '@clarify/zone-data/importer'; import {describe, it, assert, beforeEach, beforeAll} from 'vitest'; import {TimeZone} from '@clarify/zone-data'; describe('Calendar', () => { describe('#dateUntil', () => { let calendar = new Calendar(); let timeZone!: TimeZone; beforeEach(async () => { timeZone = await importer['Europe/Oslo'](); }); it('same year, same month, different days', async function () { let one = new ZonedDateTime(Date.UTC(2024, 4, 12, 20, 54, 0), timeZone); let two = new ZonedDateTime(Date.UTC(2024, 4, 14, 20, 54, 0), timeZone); assert.equal(calendar.dateUntil(one.toPlainDate(), two.toPlainDate(), {largestUnit: 'year'}).toJSON(), 'P2D'); assert.equal(calendar.dateUntil(two.toPlainDate(), one.toPlainDate(), {largestUnit: 'year'}).toJSON(), '-P2D'); }); it('same year, same month, different days (wraps month)', function () { let one = new ZonedDateTime(Date.UTC(2024, 4, 12, 20, 54, 0), timeZone); let two = new ZonedDateTime(Date.UTC(2024, 5, 8, 20, 54, 0), timeZone); assert.equal(calendar.dateUntil(one.toPlainDate(), two.toPlainDate(), {largestUnit: 'year'}).toJSON(), 'P27D'); assert.equal(calendar.dateUntil(two.toPlainDate(), one.toPlainDate(), {largestUnit: 'year'}).toJSON(), '-P27D'); }); it('same year, same month, different days (wraps month with leap year)', function () { let one = new ZonedDateTime(Date.UTC(2024, 1, 12, 20, 54, 0), timeZone); let two = new ZonedDateTime(Date.UTC(2024, 2, 8, 20, 54, 0), timeZone); assert.equal(calendar.dateUntil(one.toPlainDate(), two.toPlainDate(), {largestUnit: 'year'}).toJSON(), 'P25D'); assert.equal(calendar.dateUntil(two.toPlainDate(), one.toPlainDate(), {largestUnit: 'year'}).toJSON(), '-P25D'); }); it('same year, same month, different days (wraps month without leap year)', function () { let one = new ZonedDateTime(Date.UTC(2023, 1, 12, 20, 54, 0), timeZone); let two = new ZonedDateTime(Date.UTC(2023, 2, 8, 20, 54, 0), timeZone); assert.equal(calendar.dateUntil(one.toPlainDate(), two.toPlainDate(), {largestUnit: 'year'}).toJSON(), 'P24D'); assert.equal(calendar.dateUntil(two.toPlainDate(), one.toPlainDate(), {largestUnit: 'year'}).toJSON(), '-P24D'); }); it('same year, different month, same days', function () { let one = new ZonedDateTime(Date.UTC(2024, 4, 12, 20, 54, 0), timeZone); let two = new ZonedDateTime(Date.UTC(2024, 5, 12, 20, 54, 0), timeZone); assert.equal(calendar.dateUntil(one.toPlainDate(), two.toPlainDate(), {largestUnit: 'year'}).toJSON(), 'P1M'); assert.equal(calendar.dateUntil(two.toPlainDate(), one.toPlainDate(), {largestUnit: 'year'}).toJSON(), '-P1M'); }); it('different year, same month, same days', function () { let one = new ZonedDateTime(Date.UTC(2023, 5, 12, 20, 54, 0), timeZone); let two = new ZonedDateTime(Date.UTC(2024, 5, 12, 20, 54, 0), timeZone); assert.equal(calendar.dateUntil(one.toPlainDate(), two.toPlainDate(), {largestUnit: 'year'}).toJSON(), 'P1Y'); assert.equal(calendar.dateUntil(two.toPlainDate(), one.toPlainDate(), {largestUnit: 'year'}).toJSON(), '-P1Y'); }); it('different year, different month, same days (less than a year)', function () { let one = new ZonedDateTime(Date.UTC(2023, 5, 12, 20, 54, 0), timeZone); let two = new ZonedDateTime(Date.UTC(2024, 2, 12, 20, 54, 0), timeZone); assert.equal(calendar.dateUntil(one.toPlainDate(), two.toPlainDate(), {largestUnit: 'year'}).toJSON(), 'P9M'); assert.equal(calendar.dateUntil(two.toPlainDate(), one.toPlainDate(), {largestUnit: 'year'}).toJSON(), '-P9M'); }); it('different year, different month, same days (more than a year)', function () { let one = new ZonedDateTime(Date.UTC(2023, 5, 12, 20, 54, 0), timeZone); let two = new ZonedDateTime(Date.UTC(2024, 6, 12, 20, 54, 0), timeZone); assert.equal(calendar.dateUntil(one.toPlainDate(), two.toPlainDate(), {largestUnit: 'year'}).toJSON(), 'P1Y1M'); assert.equal(calendar.dateUntil(two.toPlainDate(), one.toPlainDate(), {largestUnit: 'year'}).toJSON(), '-P1Y1M'); }); it('different year, different month, different days (less than a year and less than a month)', function () { let one = new ZonedDateTime(Date.UTC(2023, 5, 12, 20, 54, 0), timeZone); let two = new ZonedDateTime(Date.UTC(2024, 4, 2, 20, 54, 0), timeZone); assert.equal(calendar.dateUntil(one.toPlainDate(), two.toPlainDate(), {largestUnit: 'year'}).toJSON(), 'P10M20D'); assert.equal( calendar.dateUntil(two.toPlainDate(), one.toPlainDate(), {largestUnit: 'year'}).toJSON(), '-P10M20D', ); }); it('different year, different month, different days (more than a year and more than a month)', function () { let one = new ZonedDateTime(Date.UTC(2023, 5, 12, 20, 54, 0), timeZone); let two = new ZonedDateTime(Date.UTC(2024, 6, 14, 20, 54, 0), timeZone); assert.equal(calendar.dateUntil(one.toPlainDate(), two.toPlainDate(), {largestUnit: 'year'}).toJSON(), 'P1Y1M2D'); assert.equal( calendar.dateUntil(two.toPlainDate(), one.toPlainDate(), {largestUnit: 'year'}).toJSON(), '-P1Y1M2D', ); }); it('regression test', async function () { let one = new PlainDate(2023, 12, 19); let two = new PlainDate(2024, 6, 1); assert.equal(calendar.dateUntil(one, two, {largestUnit: 'year'}).toJSON(), 'P5M13D'); assert.equal(calendar.dateUntil(two, one, {largestUnit: 'year'}).toJSON(), '-P5M13D'); }); it('seemingly a year, but not really the case', async function () { let one = new PlainDate(2023, 6, 15); let two = new PlainDate(2024, 6, 3); assert.equal(calendar.dateUntil(one, two, {largestUnit: 'year'}).toJSON(), 'P11M19D'); assert.equal(calendar.dateUntil(two, one, {largestUnit: 'year'}).toJSON(), '-P11M18D'); }); it('crosses month', async function () { let one = new PlainDate(2024, 3, 31); let two = new PlainDate(2024, 4, 1); assert.equal(calendar.dateUntil(one, two, {largestUnit: 'year'}).toJSON(), 'P1D'); assert.equal(calendar.dateUntil(two, one, {largestUnit: 'year'}).toJSON(), '-P1D'); }); it('crosses year (positive)', async function () { let one = new PlainDate(1991, 12, 2); let two = new PlainDate(2024, 1, 1); assert.equal(calendar.dateUntil(one, two, {largestUnit: 'year'}).toJSON(), 'P32Y30D'); assert.equal(calendar.dateUntil(two, one, {largestUnit: 'year'}).toJSON(), '-P32Y30D'); }); }); describe('daysInYear', () => { let calendar = new Calendar(); let timeZone!: TimeZone; beforeAll(async () => { timeZone = await importer['Europe/Oslo'](); }); it('in leap year in Oslo', async function () { let one = new ZonedDateTime(Date.UTC(2024, 4, 12, 20, 54, 0), timeZone); assert.equal(calendar.daysInYear(one), 366); }); it('in regular year in Oslo', async function () { let one = new ZonedDateTime(Date.UTC(2023, 4, 12, 20, 54, 0), timeZone); assert.equal(calendar.daysInYear(one), 365); }); }); });