Browse Source

修复MySQL数据时间少8小时问题,确保登录和收藏时间一致

pull/1/head
徐飞洋 3 months ago
parent
commit
dbace286a6
  1. 115
      server-example/server-mysql.js
  2. 39
      test-time-backend.js
  3. 34
      test-time-frontend.js
  4. 4
      utils/api.js
  5. 110
      utils/time.js

115
server-example/server-mysql.js

@ -1,3 +1,17 @@
// 时间处理辅助函数 - 获取UTC+8时间
function getBeijingTime() {
const now = new Date();
return new Date(now.getTime() + 8 * 60 * 60 * 1000); // 手动加8小时
}
function getBeijingTimeISOString() {
return getBeijingTime().toISOString();
}
function getBeijingTimeTimestamp() {
return getBeijingTime().getTime();
}
// 类型处理辅助函数 - 添加于修复聊天功能 // 类型处理辅助函数 - 添加于修复聊天功能
function ensureStringId(id) { function ensureStringId(id) {
return String(id).trim(); return String(id).trim();
@ -293,7 +307,7 @@ const wechatAppSequelize = new Sequelize(
define: { define: {
timestamps: false timestamps: false
}, },
timezone: '+00:00' // 设置时区为UTC timezone: '+08:00' // 设置时区为UTC+8
} }
); );
@ -316,7 +330,7 @@ const userLoginSequelize = new Sequelize(
define: { define: {
timestamps: false timestamps: false
}, },
timezone: '+00:00' // 设置时区为UTC timezone: '+08:00' // 设置时区为UTC+8
} }
); );
@ -500,7 +514,7 @@ app.get('/api/conversations/user/:userId', async (req, res) => {
user_id: conv.userId, user_id: conv.userId,
manager_id: conv.managerId, manager_id: conv.managerId,
last_message: conv.last_message || '', last_message: conv.last_message || '',
last_message_time: lastMessageTime ? lastMessageTime.toISOString() : null, last_message_time: lastMessageTime ? new Date(lastMessageTime.getTime() + 8 * 60 * 60 * 1000).toISOString() : null,
unread_count: conv.unread_count || 0, unread_count: conv.unread_count || 0,
status: conv.status status: conv.status
}; };
@ -1114,15 +1128,16 @@ async function createUserAssociations(user) {
// 使用事务确保操作原子性 // 使用事务确保操作原子性
await sequelize.transaction(async (transaction) => { await sequelize.transaction(async (transaction) => {
// 1. 处理联系人记录 - 使用INSERT ... ON DUPLICATE KEY UPDATE确保无论如何都只保留一条记录 // 1. 处理联系人记录 - 使用INSERT ... ON DUPLICATE KEY UPDATE确保无论如何都只保留一条记录
const currentTime = getBeijingTime();
await sequelize.query( await sequelize.query(
`INSERT INTO contacts (userId, name, phoneNumber, created_at, updated_at) `INSERT INTO contacts (userId, name, phoneNumber, created_at, updated_at)
VALUES (?, ?, ?, NOW(), NOW()) VALUES (?, ?, ?, ?, ?)
ON DUPLICATE KEY UPDATE ON DUPLICATE KEY UPDATE
name = VALUES(name), name = VALUES(name),
phoneNumber = VALUES(phoneNumber), phoneNumber = VALUES(phoneNumber),
updated_at = NOW()`, updated_at = ?`,
{ {
replacements: [user.userId, user.name || '默认联系人', user.phoneNumber || ''], replacements: [user.userId, user.name || '默认联系人', user.phoneNumber || '', currentTime, currentTime, currentTime],
transaction: transaction transaction: transaction
} }
); );
@ -1131,11 +1146,11 @@ async function createUserAssociations(user) {
// 2. 处理用户管理记录 - 使用相同策略 // 2. 处理用户管理记录 - 使用相同策略
await sequelize.query( await sequelize.query(
`INSERT INTO usermanagements (userId, created_at, updated_at) `INSERT INTO usermanagements (userId, created_at, updated_at)
VALUES (?, NOW(), NOW()) VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE ON DUPLICATE KEY UPDATE
updated_at = NOW()`, updated_at = ?`,
{ {
replacements: [user.userId], replacements: [user.userId, currentTime, currentTime, currentTime],
transaction: transaction transaction: transaction
} }
); );
@ -1179,7 +1194,7 @@ app.post('/api/user/upload', async (req, res) => {
await User.update( await User.update(
{ {
...userData, ...userData,
updated_at: new Date() updated_at: getBeijingTime()
}, },
{ {
where: { openid: userData.openid } where: { openid: userData.openid }
@ -1194,8 +1209,8 @@ app.post('/api/user/upload', async (req, res) => {
user = await User.create({ user = await User.create({
...userData, ...userData,
notice: 'new', // 创建用户时固定设置notice为new notice: 'new', // 创建用户时固定设置notice为new
created_at: new Date(), created_at: getBeijingTime(),
updated_at: new Date() updated_at: getBeijingTime()
}); });
// 使用统一的关联记录创建函数 // 使用统一的关联记录创建函数
@ -1289,7 +1304,7 @@ app.post('/api/user/decodePhone', async (req, res) => {
await User.update( await User.update(
{ {
phoneNumber: phoneNumber, phoneNumber: phoneNumber,
updated_at: new Date() updated_at: getBeijingTime()
}, },
{ {
where: { openid } where: { openid }
@ -1360,7 +1375,7 @@ app.post('/api/wechat/getOpenid', async (req, res) => {
await User.update( await User.update(
{ {
session_key: session_key, session_key: session_key,
updated_at: new Date() updated_at: getBeijingTime()
}, },
{ {
where: { openid } where: { openid }
@ -1385,8 +1400,8 @@ app.post('/api/wechat/getOpenid', async (req, res) => {
cooperation: '', // 默认空字符串 cooperation: '', // 默认空字符串
businesslicenseurl: '', // 默认空字符串 businesslicenseurl: '', // 默认空字符串
notice: 'new', // 创建用户时固定设置notice为new notice: 'new', // 创建用户时固定设置notice为new
created_at: new Date(), created_at: getBeijingTime(),
updated_at: new Date() updated_at: getBeijingTime()
}); });
// 为新创建的用户创建关联记录 // 为新创建的用户创建关联记录
@ -1547,7 +1562,7 @@ app.post('/api/user/update', async (req, res) => {
await User.update( await User.update(
{ {
...updateData, ...updateData,
updated_at: new Date() updated_at: getBeijingTime()
}, },
{ {
where: { openid } where: { openid }
@ -1711,13 +1726,13 @@ app.post('/api/product/list', async (req, res) => {
// 确保created_at字段存在并转换为ISO字符串格式 // 确保created_at字段存在并转换为ISO字符串格式
if (!productJSON.created_at) { if (!productJSON.created_at) {
console.log('商品缺少created_at字段,使用默认值'); console.log('商品缺少created_at字段,使用默认值');
productJSON.created_at = new Date().toISOString(); productJSON.created_at = getBeijingTimeISOString();
} else { } else {
// 确保created_at是字符串格式 // 确保created_at是字符串格式
if (productJSON.created_at instanceof Date) { if (productJSON.created_at instanceof Date) {
productJSON.created_at = productJSON.created_at.toISOString(); productJSON.created_at = new Date(productJSON.created_at.getTime() + 8 * 60 * 60 * 1000).toISOString();
} else if (typeof productJSON.created_at !== 'string') { } else if (typeof productJSON.created_at !== 'string') {
productJSON.created_at = new Date(productJSON.created_at).toISOString(); productJSON.created_at = new Date(new Date(productJSON.created_at).getTime() + 8 * 60 * 60 * 1000).toISOString();
} }
} }
@ -2473,7 +2488,7 @@ try {
sellerId: actualSellerId, sellerId: actualSellerId,
// 查找最近5分钟内创建的商品 // 查找最近5分钟内创建的商品
created_at: { created_at: {
[Op.gt]: new Date(Date.now() - 5 * 60 * 1000) [Op.gt]: new Date(getBeijingTimeTimestamp() - 5 * 60 * 1000)
} }
}, },
order: [['created_at', 'DESC']], order: [['created_at', 'DESC']],
@ -2754,7 +2769,7 @@ try {
sellerId: actualSellerId, sellerId: actualSellerId,
status: productData.status || existingProduct.status || 'pending_review', status: productData.status || existingProduct.status || 'pending_review',
region: finalRegion, // 使用调试确定的地区字段 region: finalRegion, // 使用调试确定的地区字段
updated_at: new Date(), updated_at: getBeijingTime(),
// 【重要修复】确保保存会话ID // 【重要修复】确保保存会话ID
sessionId: sessionId || existingProduct.dataValues.sessionId, sessionId: sessionId || existingProduct.dataValues.sessionId,
uploadSessionId: sessionId || existingProduct.dataValues.uploadSessionId, uploadSessionId: sessionId || existingProduct.dataValues.uploadSessionId,
@ -2762,7 +2777,7 @@ try {
hasMultipleImages: mergedImageUrls.length > 1, hasMultipleImages: mergedImageUrls.length > 1,
totalImages: mergedImageUrls.length, totalImages: mergedImageUrls.length,
// 确保保留原始的创建时间 // 确保保留原始的创建时间
created_at: existingProduct.dataValues.created_at || new Date() created_at: existingProduct.dataValues.created_at || getBeijingTime()
}; };
// ========== 【新增】保存前的地区字段验证 ========== // ========== 【新增】保存前的地区字段验证 ==========
@ -2798,8 +2813,8 @@ try {
// 标记多图片 // 标记多图片
hasMultipleImages: finalImageUrls.length > 1, hasMultipleImages: finalImageUrls.length > 1,
totalImages: finalImageUrls.length, totalImages: finalImageUrls.length,
created_at: new Date(), created_at: getBeijingTime(),
updated_at: new Date() updated_at: getBeijingTime()
}; };
// ========== 【新增】保存前的地区字段验证 ========== // ========== 【新增】保存前的地区字段验证 ==========
@ -3330,7 +3345,8 @@ app.post('/api/favorites/add', async (req, res) => {
// 创建新的收藏记录 // 创建新的收藏记录
const newFavorite = await Favorite.create({ const newFavorite = await Favorite.create({
user_phone, user_phone,
productId productId,
date: req.body.date || getBeijingTime() // 使用前端传递的时间或当前UTC+8时间
}); });
console.log('收藏添加成功:', newFavorite); console.log('收藏添加成功:', newFavorite);
@ -3715,7 +3731,7 @@ app.post('/api/products/delete', async (req, res) => {
// 直接使用商品实例更新状态 // 直接使用商品实例更新状态
product.status = 'hidden'; product.status = 'hidden';
product.updated_at = new Date(); product.updated_at = getBeijingTime();
try { try {
// 先尝试保存商品实例 // 先尝试保存商品实例
@ -3727,7 +3743,7 @@ app.post('/api/products/delete', async (req, res) => {
// 如果保存失败,尝试使用update方法 // 如果保存失败,尝试使用update方法
try { try {
const updateResult = await Product.update( const updateResult = await Product.update(
{ status: 'hidden', updated_at: new Date() }, { status: 'hidden', updated_at: getBeijingTime() },
{ where: { productId } } { where: { productId } }
); );
console.log('删除商品成功(使用update方法):', { productId, updateResult }); console.log('删除商品成功(使用update方法):', { productId, updateResult });
@ -3741,7 +3757,7 @@ app.post('/api/products/delete', async (req, res) => {
{ {
replacements: { replacements: {
status: 'hidden', status: 'hidden',
updatedAt: new Date(), updatedAt: getBeijingTime(),
productId: productId productId: productId
} }
} }
@ -3876,7 +3892,7 @@ app.post('/api/cart/test-format', async (req, res) => {
}, },
productDataStructure: productData ? Object.keys(productData) : [] productDataStructure: productData ? Object.keys(productData) : []
}, },
timestamp: new Date().toISOString() timestamp: getBeijingTimeISOString()
}); });
} catch (error) { } catch (error) {
console.error('测试路由出错:', error); console.error('测试路由出错:', error);
@ -3886,7 +3902,7 @@ app.post('/api/cart/test-format', async (req, res) => {
message: '测试路由处理失败', message: '测试路由处理失败',
error: error.message, error: error.message,
requestData: req.body, requestData: req.body,
timestamp: new Date().toISOString() timestamp: getBeijingTimeISOString()
}); });
} }
}); });
@ -4117,7 +4133,7 @@ app.post('/api/cart/add', async (req, res) => {
console.log(`准备创建/更新购物车项: userId=${cartData.userId}, productId=${cartData.productId}`); console.log(`准备创建/更新购物车项: userId=${cartData.userId}, productId=${cartData.productId}`);
if (existingItem) { if (existingItem) {
// 添加详细的时间调试日志 // 添加详细的时间调试日志
const updateCurrentDate = new Date(); const updateCurrentDate = getBeijingTime();
const updateUtcTime = updateCurrentDate.toISOString(); const updateUtcTime = updateCurrentDate.toISOString();
console.log('购物车更新 - 当前时间对象:', updateCurrentDate); console.log('购物车更新 - 当前时间对象:', updateCurrentDate);
console.log('购物车更新 - 转换后UTC时间:', updateUtcTime); console.log('购物车更新 - 转换后UTC时间:', updateUtcTime);
@ -4126,7 +4142,7 @@ app.post('/api/cart/add', async (req, res) => {
await CartItem.update( await CartItem.update(
{ {
quantity: existingItem.quantity + cartData.quantity, quantity: existingItem.quantity + cartData.quantity,
updated_at: new Date().toISOString() updated_at: getBeijingTimeISOString()
}, },
{ {
where: { where: {
@ -4137,7 +4153,7 @@ app.post('/api/cart/add', async (req, res) => {
console.log(`更新购物车项成功: id=${existingItem.id}, 新数量=${existingItem.quantity + cartData.quantity}`); console.log(`更新购物车项成功: id=${existingItem.id}, 新数量=${existingItem.quantity + cartData.quantity}`);
// 同步更新用户表的updated_at为UTC时间 // 同步更新用户表的updated_at为UTC时间
const userUtcTime = new Date().toISOString(); const userUtcTime = getBeijingTimeISOString();
console.log('用户表更新 - UTC时间:', userUtcTime); console.log('用户表更新 - UTC时间:', userUtcTime);
await User.update( await User.update(
{ updated_at: userUtcTime }, { updated_at: userUtcTime },
@ -4148,8 +4164,8 @@ app.post('/api/cart/add', async (req, res) => {
// 不存在,创建新购物车项 // 不存在,创建新购物车项
console.log('创建新购物车项,所有字段:'); console.log('创建新购物车项,所有字段:');
// 添加详细的时间调试日志 // 添加详细的时间调试日志
const currentDate = new Date(); const currentDate = getBeijingTime();
const utcTime = currentDate.toISOString(); const utcTime = getBeijingTimeISOString();
console.log('购物车创建 - 当前时间对象:', currentDate); console.log('购物车创建 - 当前时间对象:', currentDate);
console.log('购物车创建 - 转换后UTC时间:', utcTime); console.log('购物车创建 - 转换后UTC时间:', utcTime);
console.log('购物车创建 - 时区设置:', sequelize.options.timezone); console.log('购物车创建 - 时区设置:', sequelize.options.timezone);
@ -4167,12 +4183,12 @@ app.post('/api/cart/add', async (req, res) => {
} }
await CartItem.create({ await CartItem.create({
...cartData, ...cartData,
added_at: new Date().toISOString() added_at: getBeijingTimeISOString()
}); });
console.log(`创建购物车项成功: userId=${cartData.userId}, productId=${cartData.productId}`); console.log(`创建购物车项成功: userId=${cartData.userId}, productId=${cartData.productId}`);
// 同步更新用户表的updated_at为UTC时间 // 同步更新用户表的updated_at为UTC时间
const updateUserUtcTime = new Date().toISOString(); const updateUserUtcTime = getBeijingTimeISOString()
console.log('用户表更新 - UTC时间:', updateUserUtcTime); console.log('用户表更新 - UTC时间:', updateUserUtcTime);
await User.update( await User.update(
{ updated_at: updateUserUtcTime }, { updated_at: updateUserUtcTime },
@ -4407,7 +4423,7 @@ app.post('/api/cart/update', async (req, res) => {
// 构建更新数据 // 构建更新数据
const updateData = {}; const updateData = {};
if (quantity !== undefined) updateData.quantity = quantity; if (quantity !== undefined) updateData.quantity = quantity;
updateData.updated_at = new Date(); updateData.updated_at = getBeijingTime();
// 如果selected状态发生变化,先获取当前购物车项信息 // 如果selected状态发生变化,先获取当前购物车项信息
let cartItem = null; let cartItem = null;
@ -4599,7 +4615,7 @@ app.get('/api/test-connection', async (req, res) => {
success: true, success: true,
code: 200, code: 200,
message: '服务器连接成功,数据库可用', message: '服务器连接成功,数据库可用',
timestamp: new Date().toISOString(), timestamp: getBeijingTimeISOString(),
serverInfo: { serverInfo: {
port: PORT, port: PORT,
nodeVersion: process.version, nodeVersion: process.version,
@ -4626,7 +4642,7 @@ app.get('/api/test-oss-connection', async (req, res) => {
res.status(result.success ? 200 : 500).json({ res.status(result.success ? 200 : 500).json({
...result, ...result,
timestamp: new Date().toISOString(), timestamp: getBeijingTimeISOString(),
code: result.success ? 200 : 500 code: result.success ? 200 : 500
}); });
} catch (error) { } catch (error) {
@ -4669,7 +4685,7 @@ app.post('/api/user/debug', async (req, res) => {
message: '用户不存在', message: '用户不存在',
debugInfo: { debugInfo: {
searchCriteria: { openid }, searchCriteria: { openid },
timestamp: new Date().toISOString() timestamp: getBeijingTimeISOString()
} }
}); });
} }
@ -4734,7 +4750,7 @@ app.post('/api/user/debug', async (req, res) => {
userCount: await User.count(), userCount: await User.count(),
totalProductsInSystem: await Product.count(), totalProductsInSystem: await Product.count(),
timestamp: new Date().toISOString(), timestamp: new Date().toISOString(),
serverTime: new Date().toLocaleString('zh-CN') serverTime: getBeijingTime().toLocaleString('zh-CN')
} }
}; };
@ -4814,7 +4830,7 @@ app.post('/api/product/hide', async (req, res) => {
try { try {
// 方法1: 直接保存实例 // 方法1: 直接保存实例
product.status = 'sold_out'; product.status = 'sold_out';
product.updated_at = new Date(); product.updated_at = getBeijingTime();
await product.save(); await product.save();
console.log('商品下架成功(使用save方法):', { productId: product.productId, newStatus: product.status }); console.log('商品下架成功(使用save方法):', { productId: product.productId, newStatus: product.status });
} catch (saveError) { } catch (saveError) {
@ -4823,7 +4839,7 @@ app.post('/api/product/hide', async (req, res) => {
try { try {
// 方法2: 使用update方法 // 方法2: 使用update方法
const updateResult = await Product.update( const updateResult = await Product.update(
{ status: 'sold_out', updated_at: new Date() }, { status: 'sold_out', updated_at: getBeijingTime() },
{ where: { productId: productId, sellerId: user.userId } } { where: { productId: productId, sellerId: user.userId } }
); );
console.log('商品下架成功(使用update方法):', { productId: productId, sellerIdType: typeof user.userId, updateResult }); console.log('商品下架成功(使用update方法):', { productId: productId, sellerIdType: typeof user.userId, updateResult });
@ -4834,7 +4850,7 @@ app.post('/api/product/hide', async (req, res) => {
// 方法3: 直接执行SQL语句绕过ORM验证 // 方法3: 直接执行SQL语句绕过ORM验证
const replacements = { const replacements = {
status: 'sold_out', status: 'sold_out',
updatedAt: new Date(), updatedAt: getBeijingTime(),
productId: productId, productId: productId,
sellerId: user.userId sellerId: user.userId
}; };
@ -5108,7 +5124,7 @@ app.post('/api/product/publish', async (req, res) => {
if (createdProduct.status !== 'pending_review') { if (createdProduct.status !== 'pending_review') {
console.log('⚠️ 警告: 发现状态不一致,强制更新回pending_review'); console.log('⚠️ 警告: 发现状态不一致,强制更新回pending_review');
await Product.update( await Product.update(
{ status: 'pending_review', updated_at: new Date() }, { status: 'pending_review', updated_at: getBeijingTime() },
{ where: { productId } } { where: { productId } }
); );
@ -8083,9 +8099,10 @@ async function handleSessionMessage(ws, data) {
// 如果是客服查看消息,自动将未读消息标记为已读 // 如果是客服查看消息,自动将未读消息标记为已读
if (connection.isManager) { if (connection.isManager) {
const readTime = getBeijingTime();
await sequelize.query( await sequelize.query(
'UPDATE chat_messages SET is_read = 1, read_time = NOW() WHERE conversation_id = ? AND is_read = 0 AND sender_type = 1', 'UPDATE chat_messages SET is_read = 1, read_time = ? WHERE conversation_id = ? AND is_read = 0 AND sender_type = 1',
{ replacements: [conversationId] } { replacements: [readTime, conversationId] }
); );
// 更新会话未读数 // 更新会话未读数

39
test-time-backend.js

@ -0,0 +1,39 @@
// 后端时间处理函数测试脚本
// 复制后端的时间处理函数
function getBeijingTime() {
const now = new Date();
return new Date(now.getTime() + 8 * 60 * 60 * 1000); // 手动加8小时
}
function getBeijingTimeISOString() {
return getBeijingTime().toISOString();
}
function getBeijingTimeTimestamp() {
return getBeijingTime().getTime();
}
console.log('=== 后端时间处理函数测试 ===');
// 测试当前时间
const now = Date.now();
console.log('当前时间戳 (UTC):', now);
console.log('当前时间 (UTC):', new Date(now).toISOString());
// 测试getBeijingTime
const beijingTime = getBeijingTime();
console.log('UTC+8 Date对象:', beijingTime);
console.log('UTC+8 ISO字符串:', beijingTime.toISOString());
// 测试getBeijingTimeISOString
const beijingTimeISOString = getBeijingTimeISOString();
console.log('getBeijingTimeISOString():', beijingTimeISOString);
// 测试getBeijingTimeTimestamp
const beijingTimeTimestamp = getBeijingTimeTimestamp();
console.log('UTC+8时间戳 (手动加8小时):', beijingTimeTimestamp);
console.log('时间差 (毫秒):', beijingTimeTimestamp - now);
console.log('时间差 (小时):', (beijingTimeTimestamp - now) / (1000 * 60 * 60));
console.log('=== 测试完成 ===');

34
test-time-frontend.js

@ -0,0 +1,34 @@
// 前端时间处理工具测试脚本
const timeUtils = require('./utils/time.js');
console.log('=== 前端时间处理工具测试 ===');
// 测试当前时间
const now = Date.now();
console.log('当前时间戳 (UTC):', now);
console.log('当前时间 (UTC):', new Date(now).toISOString());
// 测试getUtc8Timestamp
const utc8Timestamp = timeUtils.getUtc8Timestamp();
console.log('UTC+8时间戳 (手动加8小时):', utc8Timestamp);
console.log('时间差 (毫秒):', utc8Timestamp - now);
console.log('时间差 (小时):', (utc8Timestamp - now) / (1000 * 60 * 60));
// 测试getUtc8Date
const utc8Date = timeUtils.getUtc8Date();
console.log('UTC+8 Date对象:', utc8Date);
console.log('UTC+8 ISO字符串:', utc8Date.toISOString());
// 测试toUtc8ISOString
const utc8ISOString = timeUtils.toUtc8ISOString();
console.log('toUtc8ISOString():', utc8ISOString);
// 测试toUtc8String
const utc8String = timeUtils.toUtc8String();
console.log('toUtc8String():', utc8String);
// 测试toBeijingTimeISOString (别名)
const beijingTimeISOString = timeUtils.toBeijingTimeISOString();
console.log('toBeijingTimeISOString():', beijingTimeISOString);
console.log('=== 测试完成 ===');

4
utils/api.js

@ -2699,6 +2699,8 @@ module.exports = {
addFavorite: function (productId) { addFavorite: function (productId) {
console.log('API.addFavorite - productId:', productId); console.log('API.addFavorite - productId:', productId);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// 导入时间工具函数
const timeUtils = require('./time.js');
const userId = wx.getStorageSync('userId'); const userId = wx.getStorageSync('userId');
// 获取用户信息,包含手机号 // 获取用户信息,包含手机号
@ -2729,7 +2731,7 @@ module.exports = {
const favoriteData = { const favoriteData = {
user_phone: userPhone, user_phone: userPhone,
productId: productId, productId: productId,
date: new Date().toISOString() // 当前时间 date: timeUtils.toBeijingTimeISOString() // 当前时间
}; };
console.log('添加收藏请求数据:', favoriteData); console.log('添加收藏请求数据:', favoriteData);

110
utils/time.js

@ -0,0 +1,110 @@
// UTC+8时间处理工具函数
// 固定时间戳(北京时间:2025-12-19 17:10:35.186)
const FIXED_UTC8_TIME = 1766135435186;
let isFixedTimeMode = false; // 默认关闭固定时间模式
/**
* 获取UTC+8时间戳
* @param {Date|number} date - 可选日期对象或时间戳
* @returns {number} UTC+8时间戳
*/
function getUtc8Timestamp(date) {
let baseTimestamp;
if (isFixedTimeMode) {
baseTimestamp = FIXED_UTC8_TIME;
} else if (!date) {
baseTimestamp = Date.now();
} else if (typeof date === 'number') {
baseTimestamp = date;
} else {
baseTimestamp = date.getTime();
}
return baseTimestamp + 8 * 60 * 60 * 1000; // 手动加8小时
}
/**
* 获取UTC+8 Date对象
* @param {number} timestamp - 可选时间戳
* @returns {Date} UTC+8 Date对象
*/
function getUtc8Date(timestamp) {
const ts = isFixedTimeMode ? FIXED_UTC8_TIME : (timestamp || Date.now());
const date = new Date(ts + 8 * 60 * 60 * 1000); // 手动加8小时
return date;
}
/**
* 将时间转换为UTC+8的ISO字符串带时区信息
* @param {Date|number} date - 可选日期对象或时间戳
* @returns {string} ISO格式的UTC+8时间字符串
*/
function toUtc8ISOString(date) {
const timestamp = getUtc8Timestamp(date);
const utcDate = new Date(timestamp);
const year = utcDate.getUTCFullYear();
const month = String(utcDate.getUTCMonth() + 1).padStart(2, '0');
const day = String(utcDate.getUTCDate()).padStart(2, '0');
const hours = String(utcDate.getUTCHours()).padStart(2, '0');
const minutes = String(utcDate.getUTCMinutes()).padStart(2, '0');
const seconds = String(utcDate.getUTCSeconds()).padStart(2, '0');
const milliseconds = String(utcDate.getUTCMilliseconds()).padStart(3, '0');
return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${milliseconds}+08:00`;
}
/**
* 将时间转换为UTC+8的本地字符串
* @param {Date|number} date - 可选日期对象或时间戳
* @param {Object} options - 可选格式化选项
* @returns {string} 本地化的UTC+8时间字符串
*/
function toUtc8String(date, options = {}) {
const defaultOptions = {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
// 移除timeZone设置,因为getUtc8Timestamp已经返回UTC+8时间戳
};
const timestamp = getUtc8Timestamp(date);
const utc8Date = new Date(timestamp);
return utc8Date.toLocaleString('zh-CN', { ...defaultOptions, ...options });
}
/**
* 设置固定时间模式
* @param {boolean} mode - true启用false禁用
*/
function setFixedTimeMode(mode) {
isFixedTimeMode = mode;
}
/**
* 获取固定时间模式状态
* @returns {boolean} 当前固定时间模式状态
*/
function getFixedTimeMode() {
return isFixedTimeMode;
}
// 导出函数
module.exports = {
getUtc8Timestamp,
getUtc8Date,
toUtc8ISOString,
toUtc8String,
setFixedTimeMode,
getFixedTimeMode,
// 向后兼容别名
getBeijingTimeTimestamp: getUtc8Timestamp,
getBeijingTimeDate: getUtc8Date,
toBeijingTimeISOString: toUtc8ISOString,
toBeijingTimeString: toUtc8String
};
Loading…
Cancel
Save