package blockchainservicelogic import ( "blockchain/internal/domain/usecase" "context" "fmt" "time" "blockchain/gen_result/pb/code.30cm.net/digimon/app-cloudep-blockchain" "blockchain/internal/svc" "github.com/zeromicro/go-zero/core/logx" ) type GetHistoryKlineDataLogic struct { ctx context.Context svcCtx *svc.ServiceContext logx.Logger } func NewGetHistoryKlineDataLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetHistoryKlineDataLogic { return &GetHistoryKlineDataLogic{ ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx), } } func (l *GetHistoryKlineDataLogic) GetHistoryKlineData(in *app_cloudep_blockchain.HistoryReq) (*app_cloudep_blockchain.OKResp, error) { // 1) 先驗證輸入(避免把錯誤時間丟進背景 goroutine) st, err := time.Parse(time.RFC3339, in.GetStartTime()) if err != nil { return nil, fmt.Errorf("invalid startTime (RFC3339): %w", err) } et, err := time.Parse(time.RFC3339, in.GetEndTime()) if err != nil { return nil, fmt.Errorf("invalid endTime (RFC3339): %w", err) } if !st.Before(et) { return nil, fmt.Errorf("startTime must be before endTime") } chunks := splitByWeeksUTC(st, et) if len(chunks) == 0 { return &app_cloudep_blockchain.OKResp{}, nil } for _, ch := range chunks { timeBucket := ch err := l.svcCtx.WorkerPools.Submit(func() { _ = l.svcCtx.BinanceDataSource.UpsertKline(context.Background(), usecase.QueryKline{ Symbol: in.GetSymbol(), Interval: in.GetInterval(), StartTime: timeBucket.start.UnixNano(), EndTime: timeBucket.end.UnixNano(), }) }) if err != nil { return nil, err } } return &app_cloudep_blockchain.OKResp{}, nil } // --------- 小工具:按「週一起」切段(UTC) --------- type timeRange struct { start time.Time // 含 end time.Time // 不含 } // 取得該時間所在「週一 00:00:00」(UTC) func weekStartMondayUTC(t time.Time) time.Time { t = t.UTC() // Go: Sunday=0 ... Saturday=6;我們要週一=起始 wd := int(t.Weekday()) if wd == 0 { // Sunday wd = 7 } // 將時間歸零到當天 00:00 d0 := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.UTC) // 回推到週一 return d0.AddDate(0, 0, -(wd - 1)) } // 將 [start,end) 切成多個「週粒度」的區間 func splitByWeeksUTC(start, end time.Time) []timeRange { var chunks []timeRange if !start.Before(end) { return chunks } cur := start.UTC() end = end.UTC() for cur.Before(end) { // 下一個週一 00:00 nextWeekStart := weekStartMondayUTC(cur).AddDate(0, 0, 7) chunkEnd := end if nextWeekStart.Before(end) { chunkEnd = nextWeekStart } chunks = append(chunks, timeRange{start: cur, end: chunkEnd}) cur = chunkEnd } return chunks }