修复复盘
This commit is contained in:
@@ -59,8 +59,10 @@ from history_window_lib import (
|
|||||||
PRESET_UTC_LAST7D,
|
PRESET_UTC_LAST7D,
|
||||||
PRESET_UTC_TODAY,
|
PRESET_UTC_TODAY,
|
||||||
list_window_redirect_query,
|
list_window_redirect_query,
|
||||||
|
normalize_bj_datetime_storage,
|
||||||
resolve_list_window,
|
resolve_list_window,
|
||||||
resolve_window,
|
resolve_window,
|
||||||
|
sql_list_time_field,
|
||||||
utc_window_to_bj_sql_strings,
|
utc_window_to_bj_sql_strings,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -5653,9 +5655,9 @@ def render_main_page(page="trade"):
|
|||||||
order_list = []
|
order_list = []
|
||||||
for o in raw_order_list:
|
for o in raw_order_list:
|
||||||
order_list.append(enrich_order_item(row_to_dict(o), current_capital))
|
order_list.append(enrich_order_item(row_to_dict(o), current_capital))
|
||||||
|
tr_ts = sql_list_time_field("closed_at", "created_at", "opened_at")
|
||||||
raw_records = conn.execute(
|
raw_records = conn.execute(
|
||||||
"SELECT * FROM trade_records WHERE COALESCE(closed_at, created_at, opened_at) >= ? "
|
f"SELECT * FROM trade_records WHERE {tr_ts} >= ? AND {tr_ts} <= ? ORDER BY id DESC LIMIT 1000",
|
||||||
"AND COALESCE(closed_at, created_at, opened_at) <= ? ORDER BY id DESC LIMIT 1000",
|
|
||||||
(start_bj, end_bj),
|
(start_bj, end_bj),
|
||||||
).fetchall()
|
).fetchall()
|
||||||
records = [to_effective_trade_dict(r) for r in raw_records]
|
records = [to_effective_trade_dict(r) for r in raw_records]
|
||||||
@@ -6834,8 +6836,8 @@ def export_trade_records():
|
|||||||
"margin_capital,leverage,pnl_amount,hold_seconds,hold_minutes,planned_rr,actual_rr,risk_amount,"
|
"margin_capital,leverage,pnl_amount,hold_seconds,hold_minutes,planned_rr,actual_rr,risk_amount,"
|
||||||
"opened_at,closed_at,result,miss_reason,entry_reason,reviewed_entry_reason,"
|
"opened_at,closed_at,result,miss_reason,entry_reason,reviewed_entry_reason,"
|
||||||
"exchange_realized_pnl,exchange_opened_at,exchange_closed_at,created_at "
|
"exchange_realized_pnl,exchange_opened_at,exchange_closed_at,created_at "
|
||||||
"FROM trade_records WHERE COALESCE(closed_at, created_at, opened_at) >= ? "
|
f"FROM trade_records WHERE {sql_list_time_field('closed_at', 'created_at', 'opened_at')} >= ? "
|
||||||
"AND COALESCE(closed_at, created_at, opened_at) <= ? ORDER BY id ASC",
|
f"AND {sql_list_time_field('closed_at', 'created_at', 'opened_at')} <= ? ORDER BY id ASC",
|
||||||
(start_bj, end_bj),
|
(start_bj, end_bj),
|
||||||
).fetchall()
|
).fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
@@ -7239,7 +7241,12 @@ def add_journal():
|
|||||||
new_trade_while_occupied, note, image)
|
new_trade_while_occupied, note, image)
|
||||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
|
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
|
||||||
(
|
(
|
||||||
entry_id, d.get("open_datetime"), d.get("close_datetime"), hold_duration, d.get("coin"), d.get("tf"),
|
entry_id,
|
||||||
|
normalize_bj_datetime_storage(d.get("open_datetime")),
|
||||||
|
normalize_bj_datetime_storage(d.get("close_datetime")),
|
||||||
|
hold_duration,
|
||||||
|
d.get("coin"),
|
||||||
|
d.get("tf"),
|
||||||
d.get("pnl"), entry_reason_norm, exit_reason_stored, d.get("expect_rr"), real_rr_text,
|
d.get("pnl"), entry_reason_norm, exit_reason_stored, d.get("expect_rr"), real_rr_text,
|
||||||
early_exit_raw, early_exit_reason_saved, early_exit_trigger, early_exit_note,
|
early_exit_raw, early_exit_reason_saved, early_exit_trigger, early_exit_note,
|
||||||
None, None, None, mood_issues,
|
None, None, None, mood_issues,
|
||||||
@@ -7261,9 +7268,9 @@ def api_journals():
|
|||||||
win = _list_window_from_request()
|
win = _list_window_from_request()
|
||||||
start_bj, end_bj = utc_window_to_bj_sql_strings(win["start_utc"], win["end_utc"], APP_TZ)
|
start_bj, end_bj = utc_window_to_bj_sql_strings(win["start_utc"], win["end_utc"], APP_TZ)
|
||||||
conn = get_db()
|
conn = get_db()
|
||||||
|
j_ts = sql_list_time_field("close_datetime", "created_at", "open_datetime")
|
||||||
rows = conn.execute(
|
rows = conn.execute(
|
||||||
"SELECT * FROM journal_entries WHERE COALESCE(close_datetime, created_at, open_datetime) >= ? "
|
f"SELECT * FROM journal_entries WHERE {j_ts} >= ? AND {j_ts} <= ? ORDER BY created_at DESC LIMIT 500",
|
||||||
"AND COALESCE(close_datetime, created_at, open_datetime) <= ? ORDER BY created_at DESC LIMIT 500",
|
|
||||||
(start_bj, end_bj),
|
(start_bj, end_bj),
|
||||||
).fetchall()
|
).fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|||||||
@@ -60,8 +60,10 @@ from history_window_lib import (
|
|||||||
PRESET_UTC_LAST7D,
|
PRESET_UTC_LAST7D,
|
||||||
PRESET_UTC_TODAY,
|
PRESET_UTC_TODAY,
|
||||||
list_window_redirect_query,
|
list_window_redirect_query,
|
||||||
|
normalize_bj_datetime_storage,
|
||||||
resolve_list_window,
|
resolve_list_window,
|
||||||
resolve_window,
|
resolve_window,
|
||||||
|
sql_list_time_field,
|
||||||
utc_window_to_bj_sql_strings,
|
utc_window_to_bj_sql_strings,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -5632,9 +5634,9 @@ def render_main_page(page="trade"):
|
|||||||
exchange_pnl_sync = sync_trade_records_from_exchange(conn) or {}
|
exchange_pnl_sync = sync_trade_records_from_exchange(conn) or {}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
exchange_pnl_sync = {"ok": False, "reason": str(e)}
|
exchange_pnl_sync = {"ok": False, "reason": str(e)}
|
||||||
|
tr_ts = sql_list_time_field("closed_at", "created_at", "opened_at")
|
||||||
raw_records = conn.execute(
|
raw_records = conn.execute(
|
||||||
"SELECT * FROM trade_records WHERE COALESCE(closed_at, created_at, opened_at) >= ? "
|
f"SELECT * FROM trade_records WHERE {tr_ts} >= ? AND {tr_ts} <= ? ORDER BY id DESC LIMIT 1000",
|
||||||
"AND COALESCE(closed_at, created_at, opened_at) <= ? ORDER BY id DESC LIMIT 1000",
|
|
||||||
(start_bj, end_bj),
|
(start_bj, end_bj),
|
||||||
).fetchall()
|
).fetchall()
|
||||||
records = [to_effective_trade_dict(r) for r in raw_records]
|
records = [to_effective_trade_dict(r) for r in raw_records]
|
||||||
@@ -6879,8 +6881,8 @@ def export_trade_records():
|
|||||||
"margin_capital,leverage,pnl_amount,hold_seconds,hold_minutes,planned_rr,actual_rr,risk_amount,"
|
"margin_capital,leverage,pnl_amount,hold_seconds,hold_minutes,planned_rr,actual_rr,risk_amount,"
|
||||||
"opened_at,closed_at,result,miss_reason,entry_reason,reviewed_entry_reason,"
|
"opened_at,closed_at,result,miss_reason,entry_reason,reviewed_entry_reason,"
|
||||||
"exchange_realized_pnl,exchange_opened_at,exchange_closed_at,created_at "
|
"exchange_realized_pnl,exchange_opened_at,exchange_closed_at,created_at "
|
||||||
"FROM trade_records WHERE COALESCE(closed_at, created_at, opened_at) >= ? "
|
f"FROM trade_records WHERE {sql_list_time_field('closed_at', 'created_at', 'opened_at')} >= ? "
|
||||||
"AND COALESCE(closed_at, created_at, opened_at) <= ? ORDER BY id ASC",
|
f"AND {sql_list_time_field('closed_at', 'created_at', 'opened_at')} <= ? ORDER BY id ASC",
|
||||||
(start_bj, end_bj),
|
(start_bj, end_bj),
|
||||||
).fetchall()
|
).fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
@@ -7265,7 +7267,12 @@ def add_journal():
|
|||||||
new_trade_while_occupied, note, image)
|
new_trade_while_occupied, note, image)
|
||||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
|
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
|
||||||
(
|
(
|
||||||
entry_id, d.get("open_datetime"), d.get("close_datetime"), hold_duration, d.get("coin"), d.get("tf"),
|
entry_id,
|
||||||
|
normalize_bj_datetime_storage(d.get("open_datetime")),
|
||||||
|
normalize_bj_datetime_storage(d.get("close_datetime")),
|
||||||
|
hold_duration,
|
||||||
|
d.get("coin"),
|
||||||
|
d.get("tf"),
|
||||||
d.get("pnl"), entry_reason_norm, exit_reason_stored, d.get("expect_rr"), real_rr_text,
|
d.get("pnl"), entry_reason_norm, exit_reason_stored, d.get("expect_rr"), real_rr_text,
|
||||||
early_exit_raw, early_exit_reason_saved, early_exit_trigger, early_exit_note,
|
early_exit_raw, early_exit_reason_saved, early_exit_trigger, early_exit_note,
|
||||||
None, None, None, mood_issues,
|
None, None, None, mood_issues,
|
||||||
@@ -7287,9 +7294,9 @@ def api_journals():
|
|||||||
win = _list_window_from_request()
|
win = _list_window_from_request()
|
||||||
start_bj, end_bj = utc_window_to_bj_sql_strings(win["start_utc"], win["end_utc"], APP_TZ)
|
start_bj, end_bj = utc_window_to_bj_sql_strings(win["start_utc"], win["end_utc"], APP_TZ)
|
||||||
conn = get_db()
|
conn = get_db()
|
||||||
|
j_ts = sql_list_time_field("close_datetime", "created_at", "open_datetime")
|
||||||
rows = conn.execute(
|
rows = conn.execute(
|
||||||
"SELECT * FROM journal_entries WHERE COALESCE(close_datetime, created_at, open_datetime) >= ? "
|
f"SELECT * FROM journal_entries WHERE {j_ts} >= ? AND {j_ts} <= ? ORDER BY created_at DESC LIMIT 500",
|
||||||
"AND COALESCE(close_datetime, created_at, open_datetime) <= ? ORDER BY created_at DESC LIMIT 500",
|
|
||||||
(start_bj, end_bj),
|
(start_bj, end_bj),
|
||||||
).fetchall()
|
).fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|||||||
@@ -40,8 +40,10 @@ from history_window_lib import (
|
|||||||
PRESET_UTC_LAST7D,
|
PRESET_UTC_LAST7D,
|
||||||
PRESET_UTC_TODAY,
|
PRESET_UTC_TODAY,
|
||||||
list_window_redirect_query,
|
list_window_redirect_query,
|
||||||
|
normalize_bj_datetime_storage,
|
||||||
resolve_list_window,
|
resolve_list_window,
|
||||||
resolve_window,
|
resolve_window,
|
||||||
|
sql_list_time_field,
|
||||||
utc_window_to_bj_sql_strings,
|
utc_window_to_bj_sql_strings,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -5213,8 +5215,8 @@ def render_main_page(page="trade"):
|
|||||||
pass
|
pass
|
||||||
if page in ("records", "plan_history"):
|
if page in ("records", "plan_history"):
|
||||||
raw_records = conn.execute(
|
raw_records = conn.execute(
|
||||||
"SELECT * FROM trade_records WHERE COALESCE(closed_at, created_at, opened_at) >= ? "
|
f"SELECT * FROM trade_records WHERE {sql_list_time_field('closed_at', 'created_at', 'opened_at')} >= ? "
|
||||||
"AND COALESCE(closed_at, created_at, opened_at) <= ? ORDER BY id DESC LIMIT 2000",
|
f"AND {sql_list_time_field('closed_at', 'created_at', 'opened_at')} <= ? ORDER BY id DESC LIMIT 2000",
|
||||||
(start_bj, end_bj),
|
(start_bj, end_bj),
|
||||||
).fetchall()
|
).fetchall()
|
||||||
else:
|
else:
|
||||||
@@ -6542,8 +6544,8 @@ def export_trade_records():
|
|||||||
"pnl_amount,hold_seconds,hold_minutes,opened_at,closed_at,result,miss_reason,"
|
"pnl_amount,hold_seconds,hold_minutes,opened_at,closed_at,result,miss_reason,"
|
||||||
"entry_reason,reviewed_entry_reason,created_at,trend_plan_id,exchange_realized_pnl,"
|
"entry_reason,reviewed_entry_reason,created_at,trend_plan_id,exchange_realized_pnl,"
|
||||||
"exchange_opened_at,exchange_closed_at,exchange_sync_key FROM trade_records "
|
"exchange_opened_at,exchange_closed_at,exchange_sync_key FROM trade_records "
|
||||||
"WHERE COALESCE(closed_at, created_at, opened_at) >= ? "
|
f"WHERE {sql_list_time_field('closed_at', 'created_at', 'opened_at')} >= ? "
|
||||||
"AND COALESCE(closed_at, created_at, opened_at) <= ? ORDER BY id ASC",
|
f"AND {sql_list_time_field('closed_at', 'created_at', 'opened_at')} <= ? ORDER BY id ASC",
|
||||||
(start_bj, end_bj),
|
(start_bj, end_bj),
|
||||||
).fetchall()
|
).fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
@@ -6916,7 +6918,12 @@ def add_journal():
|
|||||||
new_trade_while_occupied, note, image)
|
new_trade_while_occupied, note, image)
|
||||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
|
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
|
||||||
(
|
(
|
||||||
entry_id, d.get("open_datetime"), d.get("close_datetime"), hold_duration, d.get("coin"), d.get("tf"),
|
entry_id,
|
||||||
|
normalize_bj_datetime_storage(d.get("open_datetime")),
|
||||||
|
normalize_bj_datetime_storage(d.get("close_datetime")),
|
||||||
|
hold_duration,
|
||||||
|
d.get("coin"),
|
||||||
|
d.get("tf"),
|
||||||
d.get("pnl"), entry_reason_norm, exit_reason_stored, d.get("expect_rr"), real_rr_text,
|
d.get("pnl"), entry_reason_norm, exit_reason_stored, d.get("expect_rr"), real_rr_text,
|
||||||
early_exit_raw, early_exit_reason_saved, early_exit_trigger, early_exit_note,
|
early_exit_raw, early_exit_reason_saved, early_exit_trigger, early_exit_note,
|
||||||
None, None, None, mood_issues,
|
None, None, None, mood_issues,
|
||||||
@@ -6939,8 +6946,8 @@ def api_journals():
|
|||||||
start_bj, end_bj = utc_window_to_bj_sql_strings(win["start_utc"], win["end_utc"], APP_TZ)
|
start_bj, end_bj = utc_window_to_bj_sql_strings(win["start_utc"], win["end_utc"], APP_TZ)
|
||||||
conn = get_db()
|
conn = get_db()
|
||||||
rows = conn.execute(
|
rows = conn.execute(
|
||||||
"SELECT * FROM journal_entries WHERE COALESCE(close_datetime, created_at, open_datetime) >= ? "
|
f"SELECT * FROM journal_entries WHERE {sql_list_time_field('close_datetime', 'created_at', 'open_datetime')} >= ? "
|
||||||
"AND COALESCE(close_datetime, created_at, open_datetime) <= ? ORDER BY created_at DESC LIMIT 500",
|
f"AND {sql_list_time_field('close_datetime', 'created_at', 'open_datetime')} <= ? ORDER BY created_at DESC LIMIT 500",
|
||||||
(start_bj, end_bj),
|
(start_bj, end_bj),
|
||||||
).fetchall()
|
).fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|||||||
@@ -59,8 +59,10 @@ from history_window_lib import (
|
|||||||
PRESET_UTC_LAST7D,
|
PRESET_UTC_LAST7D,
|
||||||
PRESET_UTC_TODAY,
|
PRESET_UTC_TODAY,
|
||||||
list_window_redirect_query,
|
list_window_redirect_query,
|
||||||
|
normalize_bj_datetime_storage,
|
||||||
resolve_list_window,
|
resolve_list_window,
|
||||||
resolve_window,
|
resolve_window,
|
||||||
|
sql_list_time_field,
|
||||||
utc_window_to_bj_sql_strings,
|
utc_window_to_bj_sql_strings,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -4166,8 +4168,8 @@ def render_main_page(page="trade"):
|
|||||||
for o in raw_order_list:
|
for o in raw_order_list:
|
||||||
order_list.append(enrich_order_item(row_to_dict(o), current_capital))
|
order_list.append(enrich_order_item(row_to_dict(o), current_capital))
|
||||||
raw_records = conn.execute(
|
raw_records = conn.execute(
|
||||||
"SELECT * FROM trade_records WHERE COALESCE(closed_at, created_at, opened_at) >= ? "
|
f"SELECT * FROM trade_records WHERE {sql_list_time_field('closed_at', 'created_at', 'opened_at')} >= ? "
|
||||||
"AND COALESCE(closed_at, created_at, opened_at) <= ? ORDER BY id DESC LIMIT 1000",
|
f"AND {sql_list_time_field('closed_at', 'created_at', 'opened_at')} <= ? ORDER BY id DESC LIMIT 1000",
|
||||||
(start_bj, end_bj),
|
(start_bj, end_bj),
|
||||||
).fetchall()
|
).fetchall()
|
||||||
records = [to_effective_trade_dict(r) for r in raw_records]
|
records = [to_effective_trade_dict(r) for r in raw_records]
|
||||||
@@ -5139,8 +5141,8 @@ def export_trade_records():
|
|||||||
"SELECT id,symbol,monitor_type,key_signal_type,direction,trigger_price,stop_loss,initial_stop_loss,take_profit,"
|
"SELECT id,symbol,monitor_type,key_signal_type,direction,trigger_price,stop_loss,initial_stop_loss,take_profit,"
|
||||||
"margin_capital,leverage,pnl_amount,hold_seconds,hold_minutes,planned_rr,actual_rr,risk_amount,"
|
"margin_capital,leverage,pnl_amount,hold_seconds,hold_minutes,planned_rr,actual_rr,risk_amount,"
|
||||||
"opened_at,closed_at,result,miss_reason,entry_reason,reviewed_entry_reason,created_at "
|
"opened_at,closed_at,result,miss_reason,entry_reason,reviewed_entry_reason,created_at "
|
||||||
"FROM trade_records WHERE COALESCE(closed_at, created_at, opened_at) >= ? "
|
f"FROM trade_records WHERE {sql_list_time_field('closed_at', 'created_at', 'opened_at')} >= ? "
|
||||||
"AND COALESCE(closed_at, created_at, opened_at) <= ? ORDER BY id ASC",
|
f"AND {sql_list_time_field('closed_at', 'created_at', 'opened_at')} <= ? ORDER BY id ASC",
|
||||||
(start_bj, end_bj),
|
(start_bj, end_bj),
|
||||||
).fetchall()
|
).fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
@@ -5502,7 +5504,12 @@ def add_journal():
|
|||||||
new_trade_while_occupied, note, image)
|
new_trade_while_occupied, note, image)
|
||||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
|
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)""",
|
||||||
(
|
(
|
||||||
entry_id, d.get("open_datetime"), d.get("close_datetime"), hold_duration, d.get("coin"), d.get("tf"),
|
entry_id,
|
||||||
|
normalize_bj_datetime_storage(d.get("open_datetime")),
|
||||||
|
normalize_bj_datetime_storage(d.get("close_datetime")),
|
||||||
|
hold_duration,
|
||||||
|
d.get("coin"),
|
||||||
|
d.get("tf"),
|
||||||
d.get("pnl"), entry_reason_norm, exit_reason_stored, d.get("expect_rr"), real_rr_text,
|
d.get("pnl"), entry_reason_norm, exit_reason_stored, d.get("expect_rr"), real_rr_text,
|
||||||
early_exit_raw, early_exit_reason_saved, early_exit_trigger, early_exit_note,
|
early_exit_raw, early_exit_reason_saved, early_exit_trigger, early_exit_note,
|
||||||
None, None, None, mood_issues,
|
None, None, None, mood_issues,
|
||||||
@@ -5525,8 +5532,8 @@ def api_journals():
|
|||||||
start_bj, end_bj = utc_window_to_bj_sql_strings(win["start_utc"], win["end_utc"], APP_TZ)
|
start_bj, end_bj = utc_window_to_bj_sql_strings(win["start_utc"], win["end_utc"], APP_TZ)
|
||||||
conn = get_db()
|
conn = get_db()
|
||||||
rows = conn.execute(
|
rows = conn.execute(
|
||||||
"SELECT * FROM journal_entries WHERE COALESCE(close_datetime, created_at, open_datetime) >= ? "
|
f"SELECT * FROM journal_entries WHERE {sql_list_time_field('close_datetime', 'created_at', 'open_datetime')} >= ? "
|
||||||
"AND COALESCE(close_datetime, created_at, open_datetime) <= ? ORDER BY created_at DESC LIMIT 500",
|
f"AND {sql_list_time_field('close_datetime', 'created_at', 'open_datetime')} <= ? ORDER BY created_at DESC LIMIT 500",
|
||||||
(start_bj, end_bj),
|
(start_bj, end_bj),
|
||||||
).fetchall()
|
).fetchall()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|||||||
@@ -75,6 +75,28 @@ def utc_window_to_bj_sql_strings(start_utc, end_utc, app_tz):
|
|||||||
return start_bj, end_bj
|
return start_bj, end_bj
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_bj_datetime_storage(raw):
|
||||||
|
"""表单 datetime-local(含 T)入库前统一为 YYYY-MM-DD HH:MM:SS(北京时间)。"""
|
||||||
|
s = (raw or "").strip().replace("T", " ").replace("Z", "").strip()
|
||||||
|
if not s:
|
||||||
|
return ""
|
||||||
|
for fmt, n in (("%Y-%m-%d %H:%M:%S", 19), ("%Y-%m-%d %H:%M", 16), ("%Y-%m-%d", 10)):
|
||||||
|
try:
|
||||||
|
return datetime.strptime(s[:n], fmt).strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def sql_list_time_field(*columns):
|
||||||
|
"""
|
||||||
|
SQLite 列表时间窗比较表达式。
|
||||||
|
journal_entries 的 open/close 可能含 'T',直接与 bounds(空格格式)比会误判为超出上界。
|
||||||
|
"""
|
||||||
|
cols = ", ".join(columns)
|
||||||
|
return f"REPLACE(COALESCE({cols}), 'T', ' ')"
|
||||||
|
|
||||||
|
|
||||||
SESSION_KEY_LIST_WIN = "list_win_filter"
|
SESSION_KEY_LIST_WIN = "list_win_filter"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user