/** * 将时区偏移小时转换为 ±HHMM 格式 * @param {number|string} offset 如 8, -4, "+8", "-04" * @returns {string} 如 "+0800", "-0400" */ const formatTimezoneOffset = (offset) => { const hours = Number(offset); if (Number.isNaN(hours)) { throw new Error('Invalid timezone offset'); } const sign = hours >= 0 ? '+' : '-'; const hh = String(Math.abs(hours)).padStart(2, '0'); return `${sign}${hh}00`; } /** * 判断日期是否无效 * @param {Date} date * @returns {boolean} */ const isInvalidDate = (date) => { return date instanceof Date && Number.isNaN(date.getTime()); } /** * 获取指定时区当前日期或时间 * @param {number} offset - 时区相对 UTC 的偏移(例如:-4 表示 GMT-4) * @param {number} timestamp - 时间戳(可选) * @param {boolean} [withTime=false] - 是否返回完整时间(默认只返回日期) * @returns {string} 格式化的日期或时间字符串 */ const getDateInTimezone = (offset, timestamp, withTime=false) => { offset = Number(offset); if (Number.isNaN(offset)) { throw new Error('Invalid timezone offset'); } if (typeof(timestamp) === 'undefined') { timestamp = Date.now(); } else if (typeof(timestamp) === 'boolean') { withTime = timestamp; timestamp = Date.now(); } else if (typeof(timestamp) === 'string') { const date = new Date(timestamp); if (isInvalidDate(date)) { throw new Error('Invalid timestamp'); } timestamp = date.getTime(); } else if (typeof(timestamp) !== 'number') { throw new Error('Invalid timestamp'); } const nowUTC = new Date(timestamp); const targetTime = new Date(nowUTC.getTime() + offset * 60 * 60 * 1000); const year = targetTime.getUTCFullYear(); const month = String(targetTime.getUTCMonth() + 1).padStart(2, '0'); const day = String(targetTime.getUTCDate()).padStart(2, '0'); if (!withTime) { return `${year}-${month}-${day}`; } const hours = String(targetTime.getUTCHours()).padStart(2, '0'); const minutes = String(targetTime.getUTCMinutes()).padStart(2, '0'); const seconds = String(targetTime.getUTCSeconds()).padStart(2, '0'); return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}${formatTimezoneOffset(offset)}`; } export default getDateInTimezone;