11
This commit is contained in:
parent
c8066cf432
commit
5513d22655
23
web/app.py
23
web/app.py
@ -184,14 +184,35 @@ def api_pullbacks():
|
|||||||
|
|
||||||
@app.template_filter('datetime_format')
|
@app.template_filter('datetime_format')
|
||||||
def datetime_format(value, format='%Y-%m-%d %H:%M'):
|
def datetime_format(value, format='%Y-%m-%d %H:%M'):
|
||||||
"""日期时间格式化过滤器"""
|
"""日期时间格式化过滤器 - 转换为东八区时间"""
|
||||||
if value is None:
|
if value is None:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
# 导入时区支持
|
||||||
|
from datetime import timezone, timedelta
|
||||||
|
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
try:
|
try:
|
||||||
|
# 解析ISO格式时间字符串
|
||||||
|
if 'Z' in value:
|
||||||
value = datetime.fromisoformat(value.replace('Z', '+00:00'))
|
value = datetime.fromisoformat(value.replace('Z', '+00:00'))
|
||||||
|
elif '+' not in value and 'T' in value:
|
||||||
|
# 假设是UTC时间
|
||||||
|
value = datetime.fromisoformat(value).replace(tzinfo=timezone.utc)
|
||||||
|
else:
|
||||||
|
value = datetime.fromisoformat(value)
|
||||||
except:
|
except:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
# 如果是naive datetime,假设是UTC时间
|
||||||
|
if isinstance(value, datetime) and value.tzinfo is None:
|
||||||
|
value = value.replace(tzinfo=timezone.utc)
|
||||||
|
|
||||||
|
# 转换为东八区时间 (UTC+8)
|
||||||
|
if isinstance(value, datetime) and value.tzinfo is not None:
|
||||||
|
china_tz = timezone(timedelta(hours=8))
|
||||||
|
value = value.astimezone(china_tz)
|
||||||
|
|
||||||
return value.strftime(format)
|
return value.strftime(format)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -238,6 +238,49 @@ function formatNumbers() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间格式化 - 转换为东八区时间
|
||||||
|
*/
|
||||||
|
function formatDatetimeToChina(datetimeStr, format = '%m-%d %H:%M') {
|
||||||
|
if (!datetimeStr) return '';
|
||||||
|
|
||||||
|
let date;
|
||||||
|
try {
|
||||||
|
// 解析时间字符串
|
||||||
|
if (datetimeStr.endsWith('Z')) {
|
||||||
|
// UTC时间
|
||||||
|
date = new Date(datetimeStr);
|
||||||
|
} else if (datetimeStr.includes('T') && !datetimeStr.includes('+')) {
|
||||||
|
// 假设是UTC时间
|
||||||
|
date = new Date(datetimeStr + 'Z');
|
||||||
|
} else {
|
||||||
|
date = new Date(datetimeStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 转换为东八区时间
|
||||||
|
const chinaTime = new Date(date.getTime() + (8 * 60 * 60 * 1000) - (date.getTimezoneOffset() * 60 * 1000));
|
||||||
|
|
||||||
|
// 格式化显示
|
||||||
|
const year = chinaTime.getFullYear();
|
||||||
|
const month = String(chinaTime.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(chinaTime.getDate()).padStart(2, '0');
|
||||||
|
const hour = String(chinaTime.getHours()).padStart(2, '0');
|
||||||
|
const minute = String(chinaTime.getMinutes()).padStart(2, '0');
|
||||||
|
|
||||||
|
// 根据格式返回
|
||||||
|
if (format === '%Y-%m-%d') {
|
||||||
|
return `${year}-${month}-${day}`;
|
||||||
|
} else if (format === '%m-%d %H:%M') {
|
||||||
|
return `${month}-${day} ${hour}:${minute}`;
|
||||||
|
} else {
|
||||||
|
return `${year}-${month}-${day} ${hour}:${minute}`;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error('时间格式化错误:', e);
|
||||||
|
return datetimeStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导出数据
|
* 导出数据
|
||||||
*/
|
*/
|
||||||
@ -342,18 +385,22 @@ function updateSignalTable(signals) {
|
|||||||
tbody.empty();
|
tbody.empty();
|
||||||
|
|
||||||
signals.forEach(function(signal) {
|
signals.forEach(function(signal) {
|
||||||
|
const scanTime = signal.scan_time ? formatDatetimeToChina(signal.scan_time, '%m-%d %H:%M') : '';
|
||||||
|
const signalDate = signal.signal_date ? formatDatetimeToChina(signal.signal_date, '%Y-%m-%d') : '';
|
||||||
|
|
||||||
const row = `
|
const row = `
|
||||||
<tr>
|
<tr>
|
||||||
<td><span class="badge bg-secondary">${signal.stock_code}</span></td>
|
<td><span class="badge bg-secondary">${signal.stock_code}</span></td>
|
||||||
<td class="fw-bold">${signal.stock_name || '未知'}</td>
|
<td class="fw-bold">${signal.stock_name || '未知'}</td>
|
||||||
<td><span class="badge bg-info">${signal.strategy_name}</span></td>
|
<td><span class="badge bg-info">${signal.strategy_name}</span></td>
|
||||||
<td>${signal.timeframe}</td>
|
<td>${signal.timeframe}</td>
|
||||||
<td>${signal.signal_date}</td>
|
<td>${signalDate}</td>
|
||||||
<td class="text-success fw-bold">${signal.breakout_price.toFixed(2)}元</td>
|
<td class="text-success fw-bold">${signal.breakout_price.toFixed(2)}元</td>
|
||||||
<td>${signal.yin_high.toFixed(2)}元</td>
|
<td>${signal.yin_high.toFixed(2)}元</td>
|
||||||
<td><span class="badge bg-success">${signal.breakout_pct.toFixed(2)}%</span></td>
|
<td><span class="badge bg-success">${signal.breakout_pct.toFixed(2)}%</span></td>
|
||||||
<td>${signal.final_yang_entity_ratio.toFixed(2)}%</td>
|
<td>${signal.final_yang_entity_ratio.toFixed(2)}%</td>
|
||||||
<td>${signal.turnover_ratio.toFixed(2)}%</td>
|
<td>${signal.turnover_ratio.toFixed(2)}%</td>
|
||||||
|
<td class="text-muted small">${scanTime}</td>
|
||||||
</tr>
|
</tr>
|
||||||
`;
|
`;
|
||||||
tbody.append(row);
|
tbody.append(row);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user