package job import ( "context" "fmt" "time" "stock-analysis/internal/cache" "stock-analysis/internal/model" ) // resolveCandidates 根据任务类型解析要处理的转债候选列表。 // // full: 从 eastmoney datacenter 获取全量转债列表,过滤 ListDate 为空的 // incremental: 从 SQLite 获取已入库的转债代码列表 func resolveCandidates(ctx context.Context, store Store, lister BondLister, typ cache.TaskType, limit int) ([]model.ConvertibleBond, error) { switch typ { case cache.TaskTypeFull: bonds, err := lister.FetchAllBondCodes(ctx) if err != nil { return nil, fmt.Errorf("获取转债列表: %w", err) } var candidates []model.ConvertibleBond for _, b := range bonds { if b.ListDate == "" { continue // 过滤未上市 } candidates = append(candidates, b) } if limit > 0 && limit < len(candidates) { candidates = candidates[:limit] } return candidates, nil case cache.TaskTypeIncremental: codes, err := store.ListCodes(ctx) if err != nil { return nil, fmt.Errorf("加载已入库转债: %w", err) } candidates := make([]model.ConvertibleBond, 0, len(codes)) for i, c := range codes { if limit > 0 && i >= limit { break } candidates = append(candidates, model.ConvertibleBond{Code: c}) } return candidates, nil default: return nil, fmt.Errorf("未知任务类型: %s", typ) } } // yearOf 从上市日期(2006-01-02)解析年份。 func yearOf(listDate string) int { if len(listDate) >= 4 { var y int if _, err := fmt.Sscanf(listDate[:4], "%d", &y); err == nil && y > 2000 { return y } } return time.Now().Year() } // resolveIncrementalBeg 确定增量拉取的起始日期(YYYYMMDD)。 // // since 非空 → 直接使用(覆盖库中最后日期) // 否则 → lastDateMap[code] 次日;无记录返回空串(表示跳过) func resolveIncrementalBeg(code, since string, lastDateMap map[string]string) (string, bool) { if since != "" { return since, true } lastDate, ok := lastDateMap[code] if !ok || lastDate == "" { return "", false } t, err := time.Parse("2006-01-02", lastDate) if err != nil { return "", false } return t.AddDate(0, 0, 1).Format("20060102"), true }