Files
claude-relay-service/src/utils/dateHelper.js
shaw 5cfa3cc72f feat: 添加精确的账户费用计算和时区支持
- 实现基于模型使用量的精确每日费用计算
- 添加 dateHelper 工具支持时区转换
- 移除未使用的 webhook 配置代码
- 清理环境变量和配置文件中的 webhook 相关设置
- 优化前端费用显示,使用后端精确计算的数据
- 添加 DEBUG_HTTP_TRAFFIC 调试选项支持

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-01 11:29:16 +08:00

101 lines
3.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const config = require('../../config/config')
/**
* 格式化日期时间为指定时区的本地时间字符串
* @param {Date|number} date - Date对象或时间戳秒或毫秒
* @param {boolean} includeTimezone - 是否在输出中包含时区信息
* @returns {string} 格式化后的时间字符串
*/
function formatDateWithTimezone(date, includeTimezone = true) {
// 处理不同类型的输入
let dateObj
if (typeof date === 'number') {
// 判断是秒还是毫秒时间戳
// Unix时间戳通常小于 10^10毫秒时间戳通常大于 10^12
if (date < 10000000000) {
dateObj = new Date(date * 1000) // 秒转毫秒
} else {
dateObj = new Date(date) // 已经是毫秒
}
} else if (date instanceof Date) {
dateObj = date
} else {
dateObj = new Date(date)
}
// 获取配置的时区偏移(小时)
const timezoneOffset = config.system.timezoneOffset || 8 // 默认 UTC+8
// 计算本地时间
const offsetMs = timezoneOffset * 3600000 // 转换为毫秒
const localTime = new Date(dateObj.getTime() + offsetMs)
// 格式化为 YYYY-MM-DD HH:mm:ss
const year = localTime.getUTCFullYear()
const month = String(localTime.getUTCMonth() + 1).padStart(2, '0')
const day = String(localTime.getUTCDate()).padStart(2, '0')
const hours = String(localTime.getUTCHours()).padStart(2, '0')
const minutes = String(localTime.getUTCMinutes()).padStart(2, '0')
const seconds = String(localTime.getUTCSeconds()).padStart(2, '0')
let formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
// 添加时区信息
if (includeTimezone) {
const sign = timezoneOffset >= 0 ? '+' : ''
formattedDate += ` (UTC${sign}${timezoneOffset})`
}
return formattedDate
}
/**
* 获取指定时区的ISO格式时间字符串
* @param {Date|number} date - Date对象或时间戳
* @returns {string} ISO格式的时间字符串
*/
function getISOStringWithTimezone(date) {
// 先获取本地格式的时间(不含时区后缀)
const localTimeStr = formatDateWithTimezone(date, false)
// 获取时区偏移
const timezoneOffset = config.system.timezoneOffset || 8
// 构建ISO格式添加时区偏移
const sign = timezoneOffset >= 0 ? '+' : '-'
const absOffset = Math.abs(timezoneOffset)
const offsetHours = String(Math.floor(absOffset)).padStart(2, '0')
const offsetMinutes = String(Math.round((absOffset % 1) * 60)).padStart(2, '0')
// 将空格替换为T并添加时区
return `${localTimeStr.replace(' ', 'T')}${sign}${offsetHours}:${offsetMinutes}`
}
/**
* 计算时间差并格式化为人类可读的字符串
* @param {number} seconds - 秒数
* @returns {string} 格式化的时间差字符串
*/
function formatDuration(seconds) {
if (seconds < 60) {
return `${seconds}`
} else if (seconds < 3600) {
const minutes = Math.floor(seconds / 60)
return `${minutes}分钟`
} else if (seconds < 86400) {
const hours = Math.floor(seconds / 3600)
const minutes = Math.floor((seconds % 3600) / 60)
return minutes > 0 ? `${hours}小时${minutes}分钟` : `${hours}小时`
} else {
const days = Math.floor(seconds / 86400)
const hours = Math.floor((seconds % 86400) / 3600)
return hours > 0 ? `${days}${hours}小时` : `${days}`
}
}
module.exports = {
formatDateWithTimezone,
getISOStringWithTimezone,
formatDuration
}