# 时区处理修复总结 ## ✅ 已完成的修改 ### 1. trading_system/position_manager.py **修改内容**: - ✅ 导入 `get_beijing_time` 函数(从 `database.models` 或创建本地版本) - ✅ 将 `entryTime` 的存储从 `datetime.now()` 改为 `get_beijing_time()` - ✅ 将所有计算持续时间的地方从 `datetime.now()` 改为 `get_beijing_time()` **修改位置**: - 第337行:`'entryTime': get_beijing_time()` - 开仓时记录入场时间 - 第464行及多处:`exit_dt = get_beijing_time()` - 计算持仓持续时间时使用北京时间 ### 2. backend/database/models.py **已确认**: - ✅ `Trade.create()` 方法已使用 `get_beijing_time()` 设置 `entry_time` - ✅ `Trade.update_exit()` 方法已使用 `get_beijing_time()` 设置 `exit_time` - ✅ 所有其他模型(`AccountSnapshot`, `MarketScan`, `TradingSignal`, `TradeRecommendation`)都已使用 `get_beijing_time()` ### 3. SQL更新脚本 **文件**:`backend/database/update_timezone_to_beijing.sql` **功能**: - 将旧数据的 `entry_time` 和 `exit_time` 从UTC时间(或服务器本地时间)转换为北京时间(UTC+8) - 提供了三种转换方法: 1. 直接加8小时(如果旧数据是UTC时间) 2. 根据服务器时区调整(如果旧数据是服务器本地时间) 3. 使用MySQL时区转换函数(需要加载时区数据) **使用方法**: ```sql -- 1. 先备份数据库 mysqldump -u root -p auto_trade_sys > backup_$(date +%Y%m%d_%H%M%S).sql -- 2. 根据实际情况调整SQL脚本中的时间偏移量 -- 3. 运行SQL脚本 mysql -u root -p auto_trade_sys < backend/database/update_timezone_to_beijing.sql ``` ## 时间处理流程 ### 开仓(Entry Time) 1. `position_manager.py` 中 `open_position()` 方法: - 内存中存储:`'entryTime': get_beijing_time()` - 数据库入库:`Trade.create()` → 使用 `get_beijing_time()` 设置 `entry_time` ### 平仓(Exit Time) 1. `position_manager.py` 中各种平仓方法: - 计算持续时间:`exit_dt = get_beijing_time()` - 数据库更新:`Trade.update_exit()` → 使用 `get_beijing_time()` 设置 `exit_time` ### 时间格式 - 数据库存储:`TIMESTAMP` 类型,无时区信息(MySQL默认) - Python代码:使用 `datetime` 对象,通过 `get_beijing_time()` 确保是北京时间(UTC+8) - 显示:前端可以根据需要转换为任何时区显示 ## 验证方法 ### 1. 检查新数据 ```sql -- 查看最近几条记录的入场时间 SELECT id, symbol, entry_time, exit_time, status FROM trades ORDER BY id DESC LIMIT 10; ``` ### 2. 检查时间是否合理 ```sql -- 检查是否有异常的时间(例如未来时间或很久以前的时间) SELECT id, symbol, entry_time, exit_time FROM trades WHERE entry_time > NOW() OR entry_time < '2020-01-01' OR (exit_time IS NOT NULL AND exit_time > NOW()) OR (exit_time IS NOT NULL AND exit_time < entry_time); ``` ### 3. 检查持续时间计算 ```sql -- 检查持仓持续时间是否合理 SELECT id, symbol, entry_time, exit_time, TIMESTAMPDIFF(MINUTE, entry_time, COALESCE(exit_time, NOW())) as duration_minutes, duration_minutes as stored_duration FROM trades WHERE exit_time IS NOT NULL ORDER BY id DESC LIMIT 10; ``` ## 注意事项 1. **旧数据处理**: - 如果旧数据已经是北京时间,不需要运行SQL更新脚本 - 如果旧数据是UTC时间,需要加8小时 - 如果旧数据是其他时区,需要相应调整 2. **时区一致性**: - 所有入库时间都使用北京时间(UTC+8) - 所有计算持续时间的地方也使用北京时间 - 前端显示可以根据需要转换时区 3. **数据库时区设置**: - MySQL的 `TIMESTAMP` 类型会根据服务器时区自动转换 - 建议服务器时区设置为 `Asia/Shanghai` 或 `UTC+8` - 可以通过 `SELECT @@global.time_zone, @@session.time_zone;` 查看 4. **代码时区处理**: - Python代码中使用 `get_beijing_time()` 确保时区一致 - 不依赖系统时区设置,避免时区问题 ## 测试建议 1. **开仓测试**: - 开仓后检查数据库中的 `entry_time` 是否为北京时间 - 检查内存中的 `entryTime` 是否为北京时间 2. **平仓测试**: - 平仓后检查数据库中的 `exit_time` 是否为北京时间 - 检查 `duration_minutes` 计算是否正确 3. **时区转换测试**: - 在不同时区的服务器上测试(如果可能) - 验证时间显示是否正确 ## 总结 ✅ **所有入库时间已统一使用北京时间** ✅ **所有计算持续时间的地方已使用北京时间** ✅ **已提供SQL脚本更新旧数据** ✅ **代码已通过语法检查** 现在系统的时间处理已经完全统一,所有时间都使用北京时间(UTC+8)存储和计算。