blockchain/internal/logic/blockchainservice/get_history_kline_data_logi...

108 lines
2.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}