Spaces:
Running
Running
Fix dateBounds: always read dates directly from Supabase using UTC to avoid timezone issues
Browse files- src/lib/dataService.js +62 -33
src/lib/dataService.js
CHANGED
|
@@ -476,45 +476,55 @@ class DataService {
|
|
| 476 |
}
|
| 477 |
}
|
| 478 |
|
| 479 |
-
// 3. 计算全局日期范围 -
|
| 480 |
-
|
| 481 |
-
|
| 482 |
-
const calculatedMax = allDates.length ? allDates[allDates.length - 1] : null
|
| 483 |
-
|
| 484 |
-
// Also verify with DB to ensure we have the latest max date
|
| 485 |
let dbMaxDate = null
|
| 486 |
try {
|
| 487 |
-
const
|
| 488 |
-
|
| 489 |
-
|
| 490 |
-
|
| 491 |
-
|
| 492 |
-
|
| 493 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 494 |
}
|
| 495 |
} catch (e) {
|
| 496 |
-
console.error('[DataService] Error getting DB
|
| 497 |
}
|
| 498 |
|
| 499 |
-
//
|
| 500 |
-
|
| 501 |
-
|
| 502 |
-
|
| 503 |
-
|
| 504 |
-
if (dbMaxDateStr > calculatedMaxStr) {
|
| 505 |
-
console.warn(`[DataService] dateBounds: DB max date ${dbMaxDateStr} is newer than calculated ${calculatedMaxStr}, using DB date`)
|
| 506 |
-
finalMax = dbMaxDate
|
| 507 |
}
|
| 508 |
-
|
| 509 |
-
finalMax = dbMaxDate
|
| 510 |
}
|
| 511 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 512 |
this.dateBounds = {
|
| 513 |
-
min:
|
| 514 |
-
max:
|
| 515 |
}
|
| 516 |
|
| 517 |
-
console.log(`[DataService] dateBounds set: min = ${
|
|
|
|
| 518 |
|
| 519 |
// 4. 按 agent_name|asset|model 分组去重
|
| 520 |
const keyToRow = new Map()
|
|
@@ -620,7 +630,7 @@ class DataService {
|
|
| 620 |
*/
|
| 621 |
async updateDateBounds() {
|
| 622 |
try {
|
| 623 |
-
// 查询数据库的最小和最大日期
|
| 624 |
const [minDateResult, maxDateResult] = await Promise.all([
|
| 625 |
supabase
|
| 626 |
.from('trading_decisions')
|
|
@@ -644,23 +654,42 @@ class DataService {
|
|
| 644 |
dbMaxDate = maxDateResult.data[0].date
|
| 645 |
}
|
| 646 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 647 |
// 如果查询到了新的日期,更新 dateBounds
|
| 648 |
-
if (
|
| 649 |
const oldMax = this.dateBounds.max ? this.dateBounds.max.toISOString().split('T')[0] : null
|
| 650 |
-
const newMax =
|
| 651 |
|
| 652 |
// 只有当新日期确实更新时才更新
|
| 653 |
if (newMax && (!oldMax || newMax > oldMax)) {
|
|
|
|
|
|
|
| 654 |
this.dateBounds = {
|
| 655 |
-
min:
|
| 656 |
-
max:
|
| 657 |
}
|
| 658 |
-
console.log(`[DataService] updateDateBounds: Updated
|
|
|
|
| 659 |
// 通知所有订阅者
|
| 660 |
this._notify()
|
| 661 |
} else if (newMax && oldMax && newMax === oldMax) {
|
| 662 |
console.log(`[DataService] updateDateBounds: Date bounds already up to date (max = ${newMax})`)
|
|
|
|
|
|
|
| 663 |
}
|
|
|
|
|
|
|
| 664 |
}
|
| 665 |
} catch (e) {
|
| 666 |
console.error('[DataService] Error updating dateBounds:', e)
|
|
|
|
| 476 |
}
|
| 477 |
}
|
| 478 |
|
| 479 |
+
// 3. 计算全局日期范围 - 直接从 Supabase 读取,避免时区问题
|
| 480 |
+
// 始终从数据库读取最新的日期范围,而不是从已获取的数据计算
|
| 481 |
+
let dbMinDate = null
|
|
|
|
|
|
|
|
|
|
| 482 |
let dbMaxDate = null
|
| 483 |
try {
|
| 484 |
+
const [minDateResult, maxDateResult] = await Promise.all([
|
| 485 |
+
supabase
|
| 486 |
+
.from('trading_decisions')
|
| 487 |
+
.select('date')
|
| 488 |
+
.order('date', { ascending: true })
|
| 489 |
+
.limit(1),
|
| 490 |
+
supabase
|
| 491 |
+
.from('trading_decisions')
|
| 492 |
+
.select('date')
|
| 493 |
+
.order('date', { ascending: false })
|
| 494 |
+
.limit(1)
|
| 495 |
+
])
|
| 496 |
+
|
| 497 |
+
if (!minDateResult.error && minDateResult.data && minDateResult.data.length > 0) {
|
| 498 |
+
dbMinDate = minDateResult.data[0].date
|
| 499 |
+
}
|
| 500 |
+
if (!maxDateResult.error && maxDateResult.data && maxDateResult.data.length > 0) {
|
| 501 |
+
dbMaxDate = maxDateResult.data[0].date
|
| 502 |
}
|
| 503 |
} catch (e) {
|
| 504 |
+
console.error('[DataService] Error getting DB date range for dateBounds:', e)
|
| 505 |
}
|
| 506 |
|
| 507 |
+
// 从 Supabase 读取的日期字符串,提取日期部分(YYYY-MM-DD)
|
| 508 |
+
const normalizeDateStr = (dateStr) => {
|
| 509 |
+
if (!dateStr) return null
|
| 510 |
+
if (typeof dateStr === 'string') {
|
| 511 |
+
return dateStr.split('T')[0] // 提取 YYYY-MM-DD 部分
|
|
|
|
|
|
|
|
|
|
| 512 |
}
|
| 513 |
+
return null
|
|
|
|
| 514 |
}
|
| 515 |
|
| 516 |
+
const dbMinDateStr = normalizeDateStr(dbMinDate)
|
| 517 |
+
const dbMaxDateStr = normalizeDateStr(dbMaxDate)
|
| 518 |
+
|
| 519 |
+
// 使用 UTC 时间创建 Date 对象,避免时区问题
|
| 520 |
+
// 格式:YYYY-MM-DDTHH:mm:ss.sssZ (UTC midnight)
|
| 521 |
this.dateBounds = {
|
| 522 |
+
min: dbMinDateStr ? new Date(dbMinDateStr + 'T00:00:00.000Z') : null,
|
| 523 |
+
max: dbMaxDateStr ? new Date(dbMaxDateStr + 'T00:00:00.000Z') : null
|
| 524 |
}
|
| 525 |
|
| 526 |
+
console.log(`[DataService] dateBounds set from DB: min = ${dbMinDateStr}, max = ${dbMaxDateStr}`)
|
| 527 |
+
console.log(`[DataService] dateBounds Date objects: min = ${this.dateBounds.min?.toISOString()}, max = ${this.dateBounds.max?.toISOString()}`)
|
| 528 |
|
| 529 |
// 4. 按 agent_name|asset|model 分组去重
|
| 530 |
const keyToRow = new Map()
|
|
|
|
| 630 |
*/
|
| 631 |
async updateDateBounds() {
|
| 632 |
try {
|
| 633 |
+
// 查询数据库的最小和最大日期 - 直接从 Supabase 读取,避免时区问题
|
| 634 |
const [minDateResult, maxDateResult] = await Promise.all([
|
| 635 |
supabase
|
| 636 |
.from('trading_decisions')
|
|
|
|
| 654 |
dbMaxDate = maxDateResult.data[0].date
|
| 655 |
}
|
| 656 |
|
| 657 |
+
// 从 Supabase 读取的日期字符串,提取日期部分(YYYY-MM-DD)
|
| 658 |
+
const normalizeDateStr = (dateStr) => {
|
| 659 |
+
if (!dateStr) return null
|
| 660 |
+
if (typeof dateStr === 'string') {
|
| 661 |
+
return dateStr.split('T')[0] // 提取 YYYY-MM-DD 部分
|
| 662 |
+
}
|
| 663 |
+
return null
|
| 664 |
+
}
|
| 665 |
+
|
| 666 |
+
const dbMinDateStr = normalizeDateStr(dbMinDate)
|
| 667 |
+
const dbMaxDateStr = normalizeDateStr(dbMaxDate)
|
| 668 |
+
|
| 669 |
// 如果查询到了新的日期,更新 dateBounds
|
| 670 |
+
if (dbMinDateStr || dbMaxDateStr) {
|
| 671 |
const oldMax = this.dateBounds.max ? this.dateBounds.max.toISOString().split('T')[0] : null
|
| 672 |
+
const newMax = dbMaxDateStr
|
| 673 |
|
| 674 |
// 只有当新日期确实更新时才更新
|
| 675 |
if (newMax && (!oldMax || newMax > oldMax)) {
|
| 676 |
+
// 使用 UTC 时间创建 Date 对象,避免时区问题
|
| 677 |
+
// 格式:YYYY-MM-DDTHH:mm:ss.sssZ (UTC midnight)
|
| 678 |
this.dateBounds = {
|
| 679 |
+
min: dbMinDateStr ? new Date(dbMinDateStr + 'T00:00:00.000Z') : this.dateBounds.min,
|
| 680 |
+
max: dbMaxDateStr ? new Date(dbMaxDateStr + 'T00:00:00.000Z') : this.dateBounds.max
|
| 681 |
}
|
| 682 |
+
console.log(`[DataService] updateDateBounds: Updated from DB - min = ${dbMinDateStr}, max = ${dbMaxDateStr}`)
|
| 683 |
+
console.log(`[DataService] updateDateBounds: Date objects - min = ${this.dateBounds.min?.toISOString()}, max = ${this.dateBounds.max?.toISOString()}`)
|
| 684 |
// 通知所有订阅者
|
| 685 |
this._notify()
|
| 686 |
} else if (newMax && oldMax && newMax === oldMax) {
|
| 687 |
console.log(`[DataService] updateDateBounds: Date bounds already up to date (max = ${newMax})`)
|
| 688 |
+
} else {
|
| 689 |
+
console.log(`[DataService] updateDateBounds: No update needed - oldMax = ${oldMax}, newMax = ${newMax}`)
|
| 690 |
}
|
| 691 |
+
} else {
|
| 692 |
+
console.warn(`[DataService] updateDateBounds: No dates found in DB`)
|
| 693 |
}
|
| 694 |
} catch (e) {
|
| 695 |
console.error('[DataService] Error updating dateBounds:', e)
|