diff --git a/package.json b/package.json index 83744b6..6420413 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "holy-time", - "version": "3.3.0", + "version": "3.4.0", "description": "Utility functions", "repository": "Yet another (type-safe) date time library", "main": "dist/index.js", diff --git a/src/__tests__/end-of.test.ts b/src/__tests__/end-of.test.ts index f32c61e..988d4dc 100644 --- a/src/__tests__/end-of.test.ts +++ b/src/__tests__/end-of.test.ts @@ -16,23 +16,23 @@ describe('test HolyTime.endOf', () => { describe('test endOf with timeZone', () => { it('should return end of unit in timeZone', () => { const date = new HolyTime(new Date('2023-01-01T01:02:03.000Z')); - expect(date.endOf('hour', 'America/New_York').format('YYYY-MM-DD hh:mm:ss')).toBe('2023-01-01 01:59:59'); - expect(date.endOf('hour', 'America/New_York').format('YYYY-MM-DD hh:mm:ss', 'Europe/Berlin')).toBe('2023-01-01 02:59:59'); + expect(date.endOf('hour', 'America/New_York').format('YYYY-MM-DD HH:mm:ss')).toBe('2023-01-01 01:59:59'); + expect(date.endOf('hour', 'America/New_York').format('YYYY-MM-DD HH:mm:ss', 'Europe/Berlin')).toBe('2023-01-01 02:59:59'); - expect(date.endOf('day', 'Europe/London').format('YYYY-MM-DD hh:mm:ss')).toBe('2023-01-01 23:59:59'); - expect(date.endOf('day', 'America/New_York').format('YYYY-MM-DD hh:mm:ss', 'Europe/London')).toBe('2023-01-01 04:59:59'); - expect(date.endOf('day', 'Europe/Berlin').format('YYYY-MM-DD hh:mm:ss', 'America/New_York')).toBe('2023-01-01 19:59:59'); + expect(date.endOf('day', 'Europe/London').format('YYYY-MM-DD HH:mm:ss')).toBe('2023-01-01 23:59:59'); + expect(date.endOf('day', 'America/New_York').format('YYYY-MM-DD HH:mm:ss', 'Europe/London')).toBe('2023-01-01 04:59:59'); + expect(date.endOf('day', 'Europe/Berlin').format('YYYY-MM-DD HH:mm:ss', 'America/New_York')).toBe('2023-01-01 19:59:59'); - expect(date.endOf('week', 'Europe/London').format('YYYY-MM-DD hh:mm:ss')).toBe('2023-01-07 23:59:59'); - expect(date.endOf('week', 'Europe/London').format('YYYY-MM-DD hh:mm:ss', 'America/New_York')).toBe('2023-01-07 18:59:59'); - expect(date.endOf('week', 'America/New_York').format('YYYY-MM-DD hh:mm:ss', 'Europe/London')).toBe('2023-01-01 04:59:59'); + expect(date.endOf('week', 'Europe/London').format('YYYY-MM-DD HH:mm:ss')).toBe('2023-01-07 23:59:59'); + expect(date.endOf('week', 'Europe/London').format('YYYY-MM-DD HH:mm:ss', 'America/New_York')).toBe('2023-01-07 18:59:59'); + expect(date.endOf('week', 'America/New_York').format('YYYY-MM-DD HH:mm:ss', 'Europe/London')).toBe('2023-01-01 04:59:59'); - expect(date.endOf('month', 'Europe/London').format('YYYY-MM-DD hh:mm:ss')).toBe('2023-01-31 23:59:59'); - expect(date.endOf('month', 'Europe/London').format('YYYY-MM-DD hh:mm:ss', 'America/New_York')).toBe('2023-01-31 18:59:59'); - expect(date.endOf('month', 'America/New_York').format('YYYY-MM-DD hh:mm:ss', 'Europe/London')).toBe('2023-01-01 04:59:59'); + expect(date.endOf('month', 'Europe/London').format('YYYY-MM-DD HH:mm:ss')).toBe('2023-01-31 23:59:59'); + expect(date.endOf('month', 'Europe/London').format('YYYY-MM-DD HH:mm:ss', 'America/New_York')).toBe('2023-01-31 18:59:59'); + expect(date.endOf('month', 'America/New_York').format('YYYY-MM-DD HH:mm:ss', 'Europe/London')).toBe('2023-01-01 04:59:59'); - expect(date.endOf('year', 'Europe/London').format('YYYY-MM-DD hh:mm:ss')).toBe('2023-12-31 23:59:59'); - expect(date.endOf('year', 'Europe/London').format('YYYY-MM-DD hh:mm:ss', 'America/New_York')).toBe('2023-12-31 18:59:59'); - expect(date.endOf('year', 'America/New_York').format('YYYY-MM-DD hh:mm:ss', 'Europe/London')).toBe('2023-01-01 04:59:59'); + expect(date.endOf('year', 'Europe/London').format('YYYY-MM-DD HH:mm:ss')).toBe('2023-12-31 23:59:59'); + expect(date.endOf('year', 'Europe/London').format('YYYY-MM-DD HH:mm:ss', 'America/New_York')).toBe('2023-12-31 18:59:59'); + expect(date.endOf('year', 'America/New_York').format('YYYY-MM-DD HH:mm:ss', 'Europe/London')).toBe('2023-01-01 04:59:59'); }); }); diff --git a/src/__tests__/format.test.ts b/src/__tests__/format.test.ts index 97e95d3..76b0197 100644 --- a/src/__tests__/format.test.ts +++ b/src/__tests__/format.test.ts @@ -5,7 +5,7 @@ describe('test HolyTime.format without timeZone', () => { it('should format date', () => { const date = new HolyTime(new Date('2023-01-01T13:45:30.000Z')); - expect(date.format('YYYY-MM-DD hh:mm:ss')).toBe('2023-01-01 13:45:30'); + expect(date.format('YYYY-MM-DD HH:mm:ss')).toBe('2023-01-01 13:45:30'); }); it('should format year', () => { @@ -30,8 +30,8 @@ describe('test HolyTime.format without timeZone', () => { it('should format hour', () => { const date = new HolyTime(new Date('2023-01-01T13:00:00.000Z')); - expect(date.format('hh')).toBe('13'); - expect(date.format('h')).toBe('13'); + expect(date.format('HH')).toBe('13'); + expect(date.format('H')).toBe('13'); }); it('should format minute', () => { @@ -53,7 +53,7 @@ describe('test HolyTime.format without timeZone', () => { it('should format date with mixed valid and invalid tokens', () => { const date = new HolyTime(new Date('2023-01-01T15:45:30.000Z')); - expect(date.format('Year: YYYY, Hour: hh, Unknown: UUU')).toBe('Year: 2023, Hour: 15, Unknown: UUU'); + expect(date.format('[Year:] YYYY, [Hour:] HH, [Unknown:] UUU')).toBe('Year: 2023, Hour: 15, Unknown: UUU'); }); it('should handle empty format string correctly', () => { @@ -66,12 +66,12 @@ describe('test HolyTime.format with timeZone', () => { it('should format date from UTC to America/New_York with 4h difference', () => { const date = new HolyTime(new Date('2023-04-01T00:00:00.000Z')); - expect(date.format('YYYY-MM-DD hh:mm:ss', 'America/New_York')).toBe('2023-03-31 20:00:00'); + expect(date.format('YYYY-MM-DD HH:mm:ss', 'America/New_York')).toBe('2023-03-31 20:00:00'); }); it('should format date from UTC to America/New_York with 5h difference', () => { const date = new HolyTime(new Date('2023-08-01T00:00:00.000Z')); - const format = 'YYYY-MM-DD hh:mm:ss'; + const format = 'YYYY-MM-DD HH:mm:ss'; expect(date.format(format, 'America/New_York')).toBe('2023-07-31 20:00:00'); }); @@ -79,12 +79,12 @@ describe('test HolyTime.format with timeZone', () => { it('should format date from UTC to America/New_York with 6h difference', () => { const date = new HolyTime(new Date('2023-12-01T00:00:00.000Z')); - expect(date.format('YYYY-MM-DD hh:mm:ss', 'America/New_York')).toBe('2023-11-30 19:00:00'); + expect(date.format('YYYY-MM-DD HH:mm:ss', 'America/New_York')).toBe('2023-11-30 19:00:00'); }); it('should format date from UTC to Europe/Berlin with 1h difference', () => { const date = new HolyTime(new Date('2023-04-01T00:00:00.000Z')); - expect(date.format('YYYY-MM-DD hh:mm:ss', 'Europe/Berlin')).toBe('2023-04-01 02:00:00'); + expect(date.format('YYYY-MM-DD HH:mm:ss', 'Europe/Berlin')).toBe('2023-04-01 02:00:00'); }); }); diff --git a/src/__tests__/start-of.test.ts b/src/__tests__/start-of.test.ts index e068563..0ec4301 100644 --- a/src/__tests__/start-of.test.ts +++ b/src/__tests__/start-of.test.ts @@ -16,24 +16,24 @@ describe('test HolyTime.startOf', () => { describe('test startOf with timeZone', () => { it('should return start of unit in timeZone', () => { const date = new HolyTime(new Date('2023-01-01T01:02:03.000Z')); - expect(date.startOf('hour', 'America/New_York').format('YYYY-MM-DD hh:mm:ss')).toBe('2023-01-01 01:00:00'); - expect(date.startOf('hour', 'America/New_York').format('YYYY-MM-DD hh:mm:ss', 'Europe/Berlin')).toBe('2023-01-01 02:00:00'); + expect(date.startOf('hour', 'America/New_York').format('YYYY-MM-DD HH:mm:ss')).toBe('2023-01-01 01:00:00'); + expect(date.startOf('hour', 'America/New_York').format('YYYY-MM-DD HH:mm:ss', 'Europe/Berlin')).toBe('2023-01-01 02:00:00'); - expect(date.startOf('day', 'Europe/London').format('YYYY-MM-DD hh:mm:ss')).toBe('2023-01-01 00:00:00'); - expect(date.startOf('day', 'America/New_York').format('YYYY-MM-DD hh:mm:ss', 'Europe/London')).toBe('2022-12-31 05:00:00'); - expect(date.startOf('day', 'Europe/Berlin').format('YYYY-MM-DD hh:mm:ss', 'America/New_York')).toBe('2022-12-31 20:00:00'); + expect(date.startOf('day', 'Europe/London').format('YYYY-MM-DD HH:mm:ss')).toBe('2023-01-01 00:00:00'); + expect(date.startOf('day', 'America/New_York').format('YYYY-MM-DD HH:mm:ss', 'Europe/London')).toBe('2022-12-31 05:00:00'); + expect(date.startOf('day', 'Europe/Berlin').format('YYYY-MM-DD HH:mm:ss', 'America/New_York')).toBe('2022-12-31 20:00:00'); - expect(date.startOf('week', 'Europe/London').format('YYYY-MM-DD hh:mm:ss')).toBe('2023-01-01 00:00:00'); - expect(date.startOf('week', 'Europe/London').format('YYYY-MM-DD hh:mm:ss', 'America/New_York')).toBe('2022-12-31 19:00:00'); - expect(date.startOf('week', 'America/New_York').format('YYYY-MM-DD hh:mm:ss', 'Europe/London')).toBe('2022-12-25 05:00:00'); + expect(date.startOf('week', 'Europe/London').format('YYYY-MM-DD HH:mm:ss')).toBe('2023-01-01 00:00:00'); + expect(date.startOf('week', 'Europe/London').format('YYYY-MM-DD HH:mm:ss', 'America/New_York')).toBe('2022-12-31 19:00:00'); + expect(date.startOf('week', 'America/New_York').format('YYYY-MM-DD HH:mm:ss', 'Europe/London')).toBe('2022-12-25 05:00:00'); - expect(date.startOf('month', 'Europe/London').format('YYYY-MM-DD hh:mm:ss')).toBe('2023-01-01 00:00:00'); - expect(date.startOf('month', 'Europe/London').format('YYYY-MM-DD hh:mm:ss', 'America/New_York')).toBe('2022-12-31 19:00:00'); - expect(date.startOf('month', 'America/New_York').format('YYYY-MM-DD hh:mm:ss', 'Europe/London')).toBe('2022-12-01 05:00:00'); + expect(date.startOf('month', 'Europe/London').format('YYYY-MM-DD HH:mm:ss')).toBe('2023-01-01 00:00:00'); + expect(date.startOf('month', 'Europe/London').format('YYYY-MM-DD HH:mm:ss', 'America/New_York')).toBe('2022-12-31 19:00:00'); + expect(date.startOf('month', 'America/New_York').format('YYYY-MM-DD HH:mm:ss', 'Europe/London')).toBe('2022-12-01 05:00:00'); - expect(date.startOf('year', 'Europe/London').format('YYYY-MM-DD hh:mm:ss')).toBe('2023-01-01 00:00:00'); - expect(date.startOf('year', 'Europe/London').format('YYYY-MM-DD hh:mm:ss', 'America/New_York')).toBe('2022-12-31 19:00:00'); - expect(date.startOf('year', 'America/New_York').format('YYYY-MM-DD hh:mm:ss', 'Europe/London')).toBe('2022-01-01 05:00:00'); + expect(date.startOf('year', 'Europe/London').format('YYYY-MM-DD HH:mm:ss')).toBe('2023-01-01 00:00:00'); + expect(date.startOf('year', 'Europe/London').format('YYYY-MM-DD HH:mm:ss', 'America/New_York')).toBe('2022-12-31 19:00:00'); + expect(date.startOf('year', 'America/New_York').format('YYYY-MM-DD HH:mm:ss', 'Europe/London')).toBe('2022-01-01 05:00:00'); }); }); diff --git a/src/constants.ts b/src/constants.ts index 333cc8d..9c61508 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -9,7 +9,7 @@ export const TimeUnits = { MILLISECOND: 1, } as const; -export const FORMAT_REGEX = /\[(?[^\]]+)]|Y{4}|Y{2}|M{1,4}|D{1,2}|d{1,4}|h{1,2}|m{1,2}|s{1,2}/g; +export const FORMAT_REGEX = /\[(?[^\]]+)]|Y{4}|Y{2}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|m{1,2}|s{1,2}|a|A/g; export const MONTH_NAMES = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ]; export const RELATIVE_MAP: Record string)> = { diff --git a/src/time.ts b/src/time.ts index 1701f2c..439249b 100644 --- a/src/time.ts +++ b/src/time.ts @@ -210,8 +210,12 @@ export class HolyTime { MMMM: MONTH_NAMES[date.getMonth()], D: date.getDate().toString(), DD: date.getDate().toString().padStart(2, '0'), - h: date.getHours().toString(), - hh: date.getHours().toString().padStart(2, '0'), + HH: date.getHours().toString().padStart(2, '0'), + H: date.getHours().toString(), + h: (date.getHours() % 12).toString(), + hh: (date.getHours() % 12).toString().padStart(2, '0'), + A: date.getHours() >= 12 ? 'PM' : 'AM', + a: date.getHours() >= 12 ? 'pm' : 'am', m: date.getMinutes().toString(), mm: date.getMinutes().toString().padStart(2, '0'), s: date.getSeconds().toString(),