mirror of
https://github.com/langgenius/dify.git
synced 2026-02-11 13:34:38 +08:00
Critical regression fix for convertTimezoneToOffsetStr:
Issues Fixed:
- Previous regex /^([+-]?\d{1,2}):00/ only matched :00 offsets
- This caused half-hour offsets (e.g., India +05:30) to return UTC+0
- Even if matched, parseInt only parsed hours, losing minute info
Changes:
- Update regex to /^([+-]?\d{1,2}):(\d{2})/ to match all offset formats
- Parse both hours and minutes separately
- Output format: "UTC+5:30" for non-zero minutes, "UTC+8" for whole hours
- Preserve leading zeros in minute part (e.g., "UTC+5:30" not "UTC+5:3")
Test Coverage:
- Added 8 comprehensive tests covering:
* Default/invalid timezone handling
* Whole hour offsets (positive/negative)
* Zero offset (UTC)
* Half-hour offsets (India +5:30, Australia +9:30)
* 45-minute offset (Chatham +12:45)
* Leading zero preservation in minutes
All 14 tests passing. Verified with timezone.json entries at lines 967, 1135, 1251.
116 lines
4.0 KiB
TypeScript
116 lines
4.0 KiB
TypeScript
import dayjs from './dayjs'
|
|
import {
|
|
convertTimezoneToOffsetStr,
|
|
getDateWithTimezone,
|
|
isDayjsObject,
|
|
toDayjs,
|
|
} from './dayjs'
|
|
|
|
describe('dayjs utilities', () => {
|
|
const timezone = 'UTC'
|
|
|
|
test('toDayjs parses time-only strings with timezone support', () => {
|
|
const result = toDayjs('18:45', { timezone })
|
|
expect(result).toBeDefined()
|
|
expect(result?.format('HH:mm')).toBe('18:45')
|
|
expect(result?.utcOffset()).toBe(getDateWithTimezone({ timezone }).utcOffset())
|
|
})
|
|
|
|
test('toDayjs parses 12-hour time strings', () => {
|
|
const tz = 'America/New_York'
|
|
const result = toDayjs('07:15 PM', { timezone: tz })
|
|
expect(result).toBeDefined()
|
|
expect(result?.format('HH:mm')).toBe('19:15')
|
|
expect(result?.utcOffset()).toBe(getDateWithTimezone({ timezone: tz }).utcOffset())
|
|
})
|
|
|
|
test('isDayjsObject detects dayjs instances', () => {
|
|
const date = dayjs()
|
|
expect(isDayjsObject(date)).toBe(true)
|
|
expect(isDayjsObject(getDateWithTimezone({ timezone }))).toBe(true)
|
|
expect(isDayjsObject('2024-01-01')).toBe(false)
|
|
expect(isDayjsObject({})).toBe(false)
|
|
})
|
|
|
|
test('toDayjs parses datetime strings in target timezone', () => {
|
|
const value = '2024-05-01 12:00:00'
|
|
const tz = 'America/New_York'
|
|
|
|
const result = toDayjs(value, { timezone: tz })
|
|
|
|
expect(result).toBeDefined()
|
|
expect(result?.hour()).toBe(12)
|
|
expect(result?.format('YYYY-MM-DD HH:mm')).toBe('2024-05-01 12:00')
|
|
})
|
|
|
|
test('toDayjs parses ISO datetime strings in target timezone', () => {
|
|
const value = '2024-05-01T14:30:00'
|
|
const tz = 'Europe/London'
|
|
|
|
const result = toDayjs(value, { timezone: tz })
|
|
|
|
expect(result).toBeDefined()
|
|
expect(result?.hour()).toBe(14)
|
|
expect(result?.minute()).toBe(30)
|
|
})
|
|
|
|
test('toDayjs handles dates without time component', () => {
|
|
const value = '2024-05-01'
|
|
const tz = 'America/Los_Angeles'
|
|
|
|
const result = toDayjs(value, { timezone: tz })
|
|
|
|
expect(result).toBeDefined()
|
|
expect(result?.format('YYYY-MM-DD')).toBe('2024-05-01')
|
|
expect(result?.hour()).toBe(0)
|
|
expect(result?.minute()).toBe(0)
|
|
})
|
|
})
|
|
|
|
describe('convertTimezoneToOffsetStr', () => {
|
|
test('should return default UTC+0 for undefined timezone', () => {
|
|
expect(convertTimezoneToOffsetStr(undefined)).toBe('UTC+0')
|
|
})
|
|
|
|
test('should return default UTC+0 for invalid timezone', () => {
|
|
expect(convertTimezoneToOffsetStr('Invalid/Timezone')).toBe('UTC+0')
|
|
})
|
|
|
|
test('should handle whole hour positive offsets without leading zeros', () => {
|
|
expect(convertTimezoneToOffsetStr('Asia/Shanghai')).toBe('UTC+8')
|
|
expect(convertTimezoneToOffsetStr('Pacific/Auckland')).toBe('UTC+12')
|
|
expect(convertTimezoneToOffsetStr('Pacific/Apia')).toBe('UTC+13')
|
|
})
|
|
|
|
test('should handle whole hour negative offsets without leading zeros', () => {
|
|
expect(convertTimezoneToOffsetStr('Pacific/Niue')).toBe('UTC-11')
|
|
expect(convertTimezoneToOffsetStr('Pacific/Honolulu')).toBe('UTC-10')
|
|
expect(convertTimezoneToOffsetStr('America/New_York')).toBe('UTC-5')
|
|
})
|
|
|
|
test('should handle zero offset', () => {
|
|
expect(convertTimezoneToOffsetStr('Europe/London')).toBe('UTC+0')
|
|
expect(convertTimezoneToOffsetStr('UTC')).toBe('UTC+0')
|
|
})
|
|
|
|
test('should handle half-hour offsets (30 minutes)', () => {
|
|
// India Standard Time: UTC+5:30
|
|
expect(convertTimezoneToOffsetStr('Asia/Kolkata')).toBe('UTC+5:30')
|
|
// Australian Central Time: UTC+9:30
|
|
expect(convertTimezoneToOffsetStr('Australia/Adelaide')).toBe('UTC+9:30')
|
|
expect(convertTimezoneToOffsetStr('Australia/Darwin')).toBe('UTC+9:30')
|
|
})
|
|
|
|
test('should handle 45-minute offsets', () => {
|
|
// Chatham Time: UTC+12:45
|
|
expect(convertTimezoneToOffsetStr('Pacific/Chatham')).toBe('UTC+12:45')
|
|
})
|
|
|
|
test('should preserve leading zeros in minute part for non-zero minutes', () => {
|
|
// Ensure +05:30 is displayed as "UTC+5:30", not "UTC+5:3"
|
|
const result = convertTimezoneToOffsetStr('Asia/Kolkata')
|
|
expect(result).toMatch(/UTC[+-]\d+:30/)
|
|
expect(result).not.toMatch(/UTC[+-]\d+:3[^0]/)
|
|
})
|
|
})
|