|
@@ -0,0 +1,593 @@
|
|
|
|
+package area_graph
|
|
|
|
+
|
|
|
|
+import (
|
|
|
|
+ "errors"
|
|
|
|
+ "eta/eta_chart_lib/models"
|
|
|
|
+ "eta/eta_chart_lib/models/data_manage"
|
|
|
|
+ "eta/eta_chart_lib/utils"
|
|
|
|
+ "github.com/shopspring/decimal"
|
|
|
|
+ "math"
|
|
|
|
+ "sort"
|
|
|
|
+ "time"
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+type InterpolateStrategy struct{}
|
|
|
|
+
|
|
|
|
+// Deal 空值填充:插值法填充
|
|
|
|
+func (i *InterpolateStrategy) Deal(tmpConfig data_manage.AreaExtraConf, edbDataList []*models.ChartEdbInfoMapping, standardIndexMap map[string]*models.EdbDataList, startDate string, endDate string) (err error) {
|
|
|
|
+ for _, v := range edbDataList {
|
|
|
|
+ if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
|
|
|
|
+ if dataList, ok := v.DataList.([]*models.EdbDataList); ok {
|
|
|
|
+
|
|
|
|
+ // 存放补充数据
|
|
|
|
+ var replenishDataList []*models.EdbDataList
|
|
|
|
+
|
|
|
|
+ // 处理从 startDate 到第一个数据的日期补充
|
|
|
|
+ if len(dataList) > 0 {
|
|
|
|
+ firstData := dataList[0]
|
|
|
|
+ // 将 startDate 到第一个数据日期之间的自然日填充补充数据,值为 0
|
|
|
|
+ startDataTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
|
|
|
|
+ firstDataTime, _ := time.ParseInLocation(utils.FormatDate, firstData.DataTime, time.Local)
|
|
|
|
+
|
|
|
|
+ // 计算两个日期之间的天数差
|
|
|
|
+ if !startDataTime.Equal(firstDataTime) {
|
|
|
|
+ for startDataTime.Before(firstDataTime) {
|
|
|
|
+ // 补充数据
|
|
|
|
+ nextDay := startDataTime.Format(utils.FormatDate)
|
|
|
|
+
|
|
|
|
+ // 生成补充数据,值为 0
|
|
|
|
+ replenishIndexData := models.EdbDataList{
|
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
|
+ DataTime: nextDay,
|
|
|
|
+ DataTimestamp: startDataTime.UnixMilli(),
|
|
|
|
+ Value: 0,
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
|
+ replenishDataList = append(replenishDataList, &replenishIndexData)
|
|
|
|
+
|
|
|
|
+ // 更新 startDataTime 到下一个日期
|
|
|
|
+ startDataTime = startDataTime.AddDate(0, 0, 1)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 插值法补充数据
|
|
|
|
+ var startEdbInfoData *models.EdbDataList
|
|
|
|
+ for index := 0; index < len(dataList)-1; index++ {
|
|
|
|
+ // 获取当前数据和下一个数据
|
|
|
|
+ beforeIndexData := dataList[index]
|
|
|
|
+ afterIndexData := dataList[index+1]
|
|
|
|
+
|
|
|
|
+ if startEdbInfoData == nil {
|
|
|
|
+ startEdbInfoData = beforeIndexData
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 获取两条数据之间相差的天数
|
|
|
|
+ startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
|
|
|
|
+ currDataTime, _ := time.ParseInLocation(utils.FormatDate, afterIndexData.DataTime, time.Local)
|
|
|
|
+ betweenHour := int(currDataTime.Sub(startDataTime).Hours())
|
|
|
|
+ betweenDay := betweenHour / 24
|
|
|
|
+
|
|
|
|
+ // 如果相差一天,那么过滤
|
|
|
|
+ if betweenDay <= 1 {
|
|
|
|
+ startEdbInfoData = afterIndexData
|
|
|
|
+ continue
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 生成线性方程式
|
|
|
|
+ var a, b float64
|
|
|
|
+ {
|
|
|
|
+ coordinateData := make([]utils.Coordinate, 0)
|
|
|
|
+ tmpCoordinate1 := utils.Coordinate{
|
|
|
|
+ X: 1,
|
|
|
|
+ Y: startEdbInfoData.Value,
|
|
|
|
+ }
|
|
|
|
+ coordinateData = append(coordinateData, tmpCoordinate1)
|
|
|
|
+ tmpCoordinate2 := utils.Coordinate{
|
|
|
|
+ X: float64(betweenDay) + 1,
|
|
|
|
+ Y: afterIndexData.Value,
|
|
|
|
+ }
|
|
|
|
+ coordinateData = append(coordinateData, tmpCoordinate2)
|
|
|
|
+
|
|
|
|
+ a, b = utils.GetLinearResult(coordinateData)
|
|
|
|
+ if math.IsNaN(a) || math.IsNaN(b) {
|
|
|
|
+ err = errors.New("线性方程公式生成失败")
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 插值补充数据
|
|
|
|
+ for i := 1; i < betweenDay; i++ {
|
|
|
|
+ tmpDataTime := startDataTime.AddDate(0, 0, i)
|
|
|
|
+ aDecimal := decimal.NewFromFloat(a)
|
|
|
|
+ xDecimal := decimal.NewFromInt(int64(i) + 1)
|
|
|
|
+ bDecimal := decimal.NewFromFloat(b)
|
|
|
|
+
|
|
|
|
+ val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
|
|
|
|
+ nextDay := tmpDataTime.Format(utils.FormatDate)
|
|
|
|
+
|
|
|
|
+ replenishIndexData := models.EdbDataList{
|
|
|
|
+ EdbDataId: afterIndexData.EdbDataId,
|
|
|
|
+ DataTime: nextDay,
|
|
|
|
+ DataTimestamp: tmpDataTime.UnixMilli(),
|
|
|
|
+ Value: val,
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
|
+ replenishDataList = append(replenishDataList, &replenishIndexData)
|
|
|
|
+ }
|
|
|
|
+ startEdbInfoData = afterIndexData
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 处理从最后一个数据到 endDate 的日期补充
|
|
|
|
+ if len(dataList) > 0 {
|
|
|
|
+ lastData := dataList[len(dataList)-1]
|
|
|
|
+ // 将最后一个数据日期到 endDate 之间的自然日填充补充数据,值为 0
|
|
|
|
+ lastDataTime, _ := time.ParseInLocation(utils.FormatDate, lastData.DataTime, time.Local)
|
|
|
|
+ endDataTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
|
|
|
|
+
|
|
|
|
+ // 如果 lastDataTime 不等于 endDate,进行补充
|
|
|
|
+ if !lastDataTime.Equal(endDataTime) {
|
|
|
|
+ // 补充数据直到 endDate
|
|
|
|
+ for lastDataTime.Before(endDataTime) {
|
|
|
|
+ // 补充数据
|
|
|
|
+ addDate := lastDataTime.AddDate(0, 0, 1)
|
|
|
|
+ nextDay := addDate.Format(utils.FormatDate)
|
|
|
|
+
|
|
|
|
+ // 生成补充数据,值为 0
|
|
|
|
+ replenishIndexData := models.EdbDataList{
|
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
|
+ DataTime: nextDay,
|
|
|
|
+ DataTimestamp: addDate.UnixMilli(),
|
|
|
|
+ Value: 0,
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
|
+ replenishDataList = append(replenishDataList, &replenishIndexData)
|
|
|
|
+
|
|
|
|
+ // 更新 lastDataTime 到下一个日期
|
|
|
|
+ lastDataTime = addDate
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dataList = append(dataList, replenishDataList...)
|
|
|
|
+
|
|
|
|
+ // 根据基准指标筛选出符合数据
|
|
|
|
+ var resultDataList []*models.EdbDataList
|
|
|
|
+ for _, dataObject := range dataList {
|
|
|
|
+ if _, ok := standardIndexMap[dataObject.DataTime]; ok {
|
|
|
|
+ // 存在才保留
|
|
|
|
+ resultDataList = append(resultDataList, dataObject)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 排序
|
|
|
|
+ sort.Slice(resultDataList, func(i, j int) bool {
|
|
|
|
+ return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ v.DataList = resultDataList
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type FillWithPreviousStrategy struct{}
|
|
|
|
+
|
|
|
|
+// Deal 空值填充:前值填充
|
|
|
|
+func (f *FillWithPreviousStrategy) Deal(tmpConfig data_manage.AreaExtraConf, edbDataList []*models.ChartEdbInfoMapping, standardIndexMap map[string]*models.EdbDataList, startDate string, endDate string) (err error) {
|
|
|
|
+ // 按自然日补充,再根据基准指标取对应数据
|
|
|
|
+ for _, v := range edbDataList {
|
|
|
|
+ if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
|
|
|
|
+ if dataList, ok := v.DataList.([]*models.EdbDataList); ok {
|
|
|
|
+ // 存放补充数据
|
|
|
|
+ var replenishDataList []*models.EdbDataList
|
|
|
|
+
|
|
|
|
+ // 处理从 startDate 到第一个数据的日期补充
|
|
|
|
+ if len(dataList) > 0 {
|
|
|
|
+ firstData := dataList[0]
|
|
|
|
+ // 将 startDate 到第一个数据日期之间的自然日填充补充数据,值为 0
|
|
|
|
+ startDataTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
|
|
|
|
+ firstDataTime, _ := time.ParseInLocation(utils.FormatDate, firstData.DataTime, time.Local)
|
|
|
|
+
|
|
|
|
+ // 计算两个日期之间的天数差
|
|
|
|
+ if !startDataTime.Equal(firstDataTime) {
|
|
|
|
+ for startDataTime.Before(firstDataTime) {
|
|
|
|
+ // 补充数据
|
|
|
|
+ nextDay := startDataTime.Format(utils.FormatDate)
|
|
|
|
+
|
|
|
|
+ // 生成补充数据,值为 0
|
|
|
|
+ replenishIndexData := models.EdbDataList{
|
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
|
+ DataTime: nextDay,
|
|
|
|
+ DataTimestamp: startDataTime.UnixMilli(),
|
|
|
|
+ Value: 0,
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
|
+ replenishDataList = append(replenishDataList, &replenishIndexData)
|
|
|
|
+
|
|
|
|
+ // 更新 startDataTime 到下一个日期
|
|
|
|
+ startDataTime = startDataTime.AddDate(0, 0, 1)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 处理指标中空值数据
|
|
|
|
+ for index := 0; index < len(dataList)-1; index++ {
|
|
|
|
+ // 获取当前数据和下一个数据
|
|
|
|
+ beforeIndexData := dataList[index]
|
|
|
|
+ afterIndexData := dataList[index+1]
|
|
|
|
+
|
|
|
|
+ for utils.IsMoreThanOneDay(beforeIndexData.DataTime, afterIndexData.DataTime) {
|
|
|
|
+ // 创建补充数据
|
|
|
|
+ nextDay := utils.GetNextDay(beforeIndexData.DataTime)
|
|
|
|
+
|
|
|
|
+ toTime := utils.StringToTime(nextDay)
|
|
|
|
+ replenishIndexData := models.EdbDataList{
|
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
|
+ DataTime: nextDay,
|
|
|
|
+ DataTimestamp: toTime.UnixMilli(),
|
|
|
|
+ Value: beforeIndexData.Value,
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
|
+ replenishDataList = append(replenishDataList, &replenishIndexData)
|
|
|
|
+
|
|
|
|
+ // 更新 beforeIndexData 为新创建的补充数据
|
|
|
|
+ beforeIndexData = &replenishIndexData
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 处理从最后一个数据到 endDate 的日期补充
|
|
|
|
+ if len(dataList) > 0 {
|
|
|
|
+ lastData := dataList[len(dataList)-1]
|
|
|
|
+ // 将最后一个数据日期到 endDate 之间的自然日填充补充数据,值为 0
|
|
|
|
+ lastDataTime, _ := time.ParseInLocation(utils.FormatDate, lastData.DataTime, time.Local)
|
|
|
|
+ endDataTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
|
|
|
|
+
|
|
|
|
+ // 如果 lastDataTime 不等于 endDate,进行补充
|
|
|
|
+ if !lastDataTime.Equal(endDataTime) {
|
|
|
|
+ // 补充数据直到 endDate
|
|
|
|
+ for lastDataTime.Before(endDataTime) {
|
|
|
|
+ // 补充数据
|
|
|
|
+ addDate := lastDataTime.AddDate(0, 0, 1)
|
|
|
|
+ nextDay := addDate.Format(utils.FormatDate)
|
|
|
|
+
|
|
|
|
+ // 生成补充数据,值为 0
|
|
|
|
+ replenishIndexData := models.EdbDataList{
|
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
|
+ DataTime: nextDay,
|
|
|
|
+ DataTimestamp: addDate.UnixMilli(),
|
|
|
|
+ Value: 0,
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
|
+ replenishDataList = append(replenishDataList, &replenishIndexData)
|
|
|
|
+
|
|
|
|
+ // 更新 lastDataTime 到下一个日期
|
|
|
|
+ lastDataTime = addDate
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dataList = append(dataList, replenishDataList...)
|
|
|
|
+
|
|
|
|
+ // 根据基准指标筛选出符合数据
|
|
|
|
+ var resultDataList []*models.EdbDataList
|
|
|
|
+ for _, dataObject := range dataList {
|
|
|
|
+ _, ok = standardIndexMap[dataObject.DataTime]
|
|
|
|
+ if ok {
|
|
|
|
+ // 存在才保留
|
|
|
|
+ resultDataList = append(resultDataList, dataObject)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 排序
|
|
|
|
+ sort.Slice(resultDataList, func(i, j int) bool {
|
|
|
|
+ return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ v.DataList = resultDataList
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type FillWithNextStrategy struct{}
|
|
|
|
+
|
|
|
|
+// Deal 空值填充:后值填充
|
|
|
|
+func (f *FillWithNextStrategy) Deal(tmpConfig data_manage.AreaExtraConf, edbDataList []*models.ChartEdbInfoMapping, standardIndexMap map[string]*models.EdbDataList, startDate string, endDate string) (err error) {
|
|
|
|
+ // 按自然日补充,再根据基准指标取对应数据
|
|
|
|
+ for _, v := range edbDataList {
|
|
|
|
+ if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
|
|
|
|
+ if dataList, ok := v.DataList.([]*models.EdbDataList); ok {
|
|
|
|
+
|
|
|
|
+ // 存放补充数据
|
|
|
|
+ var replenishDataList []*models.EdbDataList
|
|
|
|
+
|
|
|
|
+ // 处理从 startDate 到第一个数据的日期补充
|
|
|
|
+ if len(dataList) > 0 {
|
|
|
|
+ firstData := dataList[0]
|
|
|
|
+ // 将 startDate 到第一个数据日期之间的自然日填充补充数据,值为 0
|
|
|
|
+ startDataTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
|
|
|
|
+ firstDataTime, _ := time.ParseInLocation(utils.FormatDate, firstData.DataTime, time.Local)
|
|
|
|
+
|
|
|
|
+ // 计算两个日期之间的天数差
|
|
|
|
+ if !startDataTime.Equal(firstDataTime) {
|
|
|
|
+ for !startDataTime.After(firstDataTime) {
|
|
|
|
+ // 补充数据
|
|
|
|
+ nextDay := startDataTime.Format(utils.FormatDate)
|
|
|
|
+
|
|
|
|
+ // 生成补充数据,值为 0
|
|
|
|
+ replenishIndexData := models.EdbDataList{
|
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
|
+ DataTime: nextDay,
|
|
|
|
+ DataTimestamp: startDataTime.UnixMilli(),
|
|
|
|
+ Value: 0,
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
|
+ replenishDataList = append(replenishDataList, &replenishIndexData)
|
|
|
|
+
|
|
|
|
+ // 更新 startDataTime 到下一个日期
|
|
|
|
+ startDataTime = startDataTime.AddDate(0, 0, 1)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 处理从最后一个数据到 endDate 的日期补充
|
|
|
|
+ if len(dataList) > 0 {
|
|
|
|
+ lastData := dataList[len(dataList)-1]
|
|
|
|
+ // 将最后一个数据日期到 endDate 之间的自然日填充补充数据,值为 0
|
|
|
|
+ lastDataTime, _ := time.ParseInLocation(utils.FormatDate, lastData.DataTime, time.Local)
|
|
|
|
+ endDataTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
|
|
|
|
+
|
|
|
|
+ // 如果 lastDataTime 不等于 endDate,进行补充
|
|
|
|
+ if !lastDataTime.Equal(endDataTime) {
|
|
|
|
+ // 补充数据直到 endDate
|
|
|
|
+ for lastDataTime.Before(endDataTime) {
|
|
|
|
+ // 补充数据
|
|
|
|
+ addDate := lastDataTime.AddDate(0, 0, 1)
|
|
|
|
+ nextDay := addDate.Format(utils.FormatDate)
|
|
|
|
+
|
|
|
|
+ // 生成补充数据,值为 0
|
|
|
|
+ replenishIndexData := models.EdbDataList{
|
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
|
+ DataTime: nextDay,
|
|
|
|
+ DataTimestamp: addDate.UnixMilli(),
|
|
|
|
+ Value: 0,
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
|
+ replenishDataList = append(replenishDataList, &replenishIndexData)
|
|
|
|
+
|
|
|
|
+ // 更新 lastDataTime 到下一个日期
|
|
|
|
+ lastDataTime = addDate
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 将切片数据倒序
|
|
|
|
+ reverseSlice(dataList)
|
|
|
|
+
|
|
|
|
+ // 处理指标中空值数据
|
|
|
|
+ for index := 0; index < len(dataList)-1; index++ {
|
|
|
|
+ // 获取当前数据和下一个数据
|
|
|
|
+ beforeIndexData := dataList[index]
|
|
|
|
+ afterIndexData := dataList[index+1]
|
|
|
|
+
|
|
|
|
+ for utils.IsMoreThanOneDay(afterIndexData.DataTime, beforeIndexData.DataTime) {
|
|
|
|
+ // 创建补充数据
|
|
|
|
+ nextDay := utils.GetNextDay(afterIndexData.DataTime)
|
|
|
|
+
|
|
|
|
+ toTime := utils.StringToTime(nextDay)
|
|
|
|
+ replenishIndexData := models.EdbDataList{
|
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
|
+ DataTime: nextDay,
|
|
|
|
+ DataTimestamp: toTime.UnixMilli(),
|
|
|
|
+ Value: afterIndexData.Value,
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
|
+ replenishDataList = append(replenishDataList, &replenishIndexData)
|
|
|
|
+
|
|
|
|
+ // 更新 beforeIndexData 为新创建的补充数据
|
|
|
|
+ afterIndexData = &replenishIndexData
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dataList = append(dataList, replenishDataList...)
|
|
|
|
+
|
|
|
|
+ // 根据基准指标筛选出符合数据
|
|
|
|
+ var resultDataList []*models.EdbDataList
|
|
|
|
+ for _, dataObject := range dataList {
|
|
|
|
+ _, ok = standardIndexMap[dataObject.DataTime]
|
|
|
|
+ if ok {
|
|
|
|
+ // 存在才保留
|
|
|
|
+ resultDataList = append(resultDataList, dataObject)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 排序
|
|
|
|
+ sort.Slice(resultDataList, func(i, j int) bool {
|
|
|
|
+ return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ v.DataList = resultDataList
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type SetToZeroStrategy struct{}
|
|
|
|
+
|
|
|
|
+// Deal 空值填充:设为0
|
|
|
|
+func (s *SetToZeroStrategy) Deal(tmpConfig data_manage.AreaExtraConf, edbDataList []*models.ChartEdbInfoMapping, standardIndexMap map[string]*models.EdbDataList, startDate string, endDate string) (err error) {
|
|
|
|
+ // 按自然日补充,再根据基准指标取对应数据
|
|
|
|
+ for _, v := range edbDataList {
|
|
|
|
+ if v.EdbInfoId != tmpConfig.StandardEdbInfoId {
|
|
|
|
+ if dataList, ok := v.DataList.([]*models.EdbDataList); ok {
|
|
|
|
+ // 存放补充数据
|
|
|
|
+ var replenishDataList []*models.EdbDataList
|
|
|
|
+
|
|
|
|
+ // 处理从 startDate 到第一个数据的日期补充
|
|
|
|
+ if len(dataList) > 0 {
|
|
|
|
+ firstData := dataList[0]
|
|
|
|
+ // 将 startDate 到第一个数据日期之间的自然日填充补充数据,值为 0
|
|
|
|
+ startDataTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
|
|
|
|
+ firstDataTime, _ := time.ParseInLocation(utils.FormatDate, firstData.DataTime, time.Local)
|
|
|
|
+
|
|
|
|
+ // 计算两个日期之间的天数差
|
|
|
|
+ if !startDataTime.Equal(firstDataTime) {
|
|
|
|
+ for startDataTime.Before(firstDataTime) {
|
|
|
|
+ // 补充数据
|
|
|
|
+ nextDay := startDataTime.Format(utils.FormatDate)
|
|
|
|
+
|
|
|
|
+ // 生成补充数据,值为 0
|
|
|
|
+ replenishIndexData := models.EdbDataList{
|
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
|
+ DataTime: nextDay,
|
|
|
|
+ DataTimestamp: startDataTime.UnixMilli(),
|
|
|
|
+ Value: 0,
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
|
+ replenishDataList = append(replenishDataList, &replenishIndexData)
|
|
|
|
+
|
|
|
|
+ // 更新 startDataTime 到下一个日期
|
|
|
|
+ startDataTime = startDataTime.AddDate(0, 0, 1)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 处理指标中空值数据
|
|
|
|
+ for index := 0; index < len(dataList)-1; index++ {
|
|
|
|
+ // 获取当前数据和下一个数据
|
|
|
|
+ beforeIndexData := dataList[index]
|
|
|
|
+ afterIndexData := dataList[index+1]
|
|
|
|
+
|
|
|
|
+ for utils.IsMoreThanOneDay(beforeIndexData.DataTime, afterIndexData.DataTime) {
|
|
|
|
+ // 创建补充数据
|
|
|
|
+ nextDay := utils.GetNextDay(beforeIndexData.DataTime)
|
|
|
|
+
|
|
|
|
+ toTime := utils.StringToTime(nextDay)
|
|
|
|
+ replenishIndexData := models.EdbDataList{
|
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
|
+ DataTime: nextDay,
|
|
|
|
+ DataTimestamp: toTime.UnixMilli(),
|
|
|
|
+ Value: 0,
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
|
+ replenishDataList = append(replenishDataList, &replenishIndexData)
|
|
|
|
+
|
|
|
|
+ // 更新 beforeIndexData 为新创建的补充数据
|
|
|
|
+ beforeIndexData = &replenishIndexData
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 处理从最后一个数据到 endDate 的日期补充
|
|
|
|
+ if len(dataList) > 0 {
|
|
|
|
+ lastData := dataList[len(dataList)-1]
|
|
|
|
+ // 将最后一个数据日期到 endDate 之间的自然日填充补充数据,值为 0
|
|
|
|
+ lastDataTime, _ := time.ParseInLocation(utils.FormatDate, lastData.DataTime, time.Local)
|
|
|
|
+ endDataTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
|
|
|
|
+
|
|
|
|
+ // 如果 lastDataTime 不等于 endDate,进行补充
|
|
|
|
+ if !lastDataTime.Equal(endDataTime) {
|
|
|
|
+ // 补充数据直到 endDate
|
|
|
|
+ for lastDataTime.Before(endDataTime) {
|
|
|
|
+ // 补充数据
|
|
|
|
+ addDate := lastDataTime.AddDate(0, 0, 1)
|
|
|
|
+ nextDay := addDate.Format(utils.FormatDate)
|
|
|
|
+
|
|
|
|
+ // 生成补充数据,值为 0
|
|
|
|
+ replenishIndexData := models.EdbDataList{
|
|
|
|
+ EdbInfoId: v.EdbInfoId,
|
|
|
|
+ DataTime: nextDay,
|
|
|
|
+ DataTimestamp: addDate.UnixMilli(),
|
|
|
|
+ Value: 0,
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 将补充数据加入补充数据列表
|
|
|
|
+ replenishDataList = append(replenishDataList, &replenishIndexData)
|
|
|
|
+
|
|
|
|
+ // 更新 lastDataTime 到下一个日期
|
|
|
|
+ lastDataTime = addDate
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ dataList = append(dataList, replenishDataList...)
|
|
|
|
+
|
|
|
|
+ // 根据基准指标筛选出符合数据
|
|
|
|
+ var resultDataList []*models.EdbDataList
|
|
|
|
+ for _, dataObject := range dataList {
|
|
|
|
+ _, ok = standardIndexMap[dataObject.DataTime]
|
|
|
|
+ if ok {
|
|
|
|
+ // 存在才保留
|
|
|
|
+ resultDataList = append(resultDataList, dataObject)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 排序
|
|
|
|
+ sort.Slice(resultDataList, func(i, j int) bool {
|
|
|
|
+ return resultDataList[i].DataTimestamp < resultDataList[j].DataTimestamp
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ v.DataList = resultDataList
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+type DeleteDateStrategy struct{}
|
|
|
|
+
|
|
|
|
+// Deal 删除日期
|
|
|
|
+func (d *DeleteDateStrategy) Deal(tmpConfig data_manage.AreaExtraConf, edbDataList []*models.ChartEdbInfoMapping, standardIndexMap map[string]*models.EdbDataList, startDate string, endDate string) error {
|
|
|
|
+ // 取所有指标的时间交集
|
|
|
|
+ // 创建一个 map 来保存每个时间点的出现次数
|
|
|
|
+ timeMap := make(map[string]int)
|
|
|
|
+ for _, v := range edbDataList {
|
|
|
|
+ if dataList, ok := v.DataList.([]*models.EdbDataList); ok {
|
|
|
|
+ // 遍历所有的 dataList,为每个 DataTime 增加一个计数
|
|
|
|
+ for _, dataObject := range dataList {
|
|
|
|
+ timeMap[dataObject.DataTime]++
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for _, v := range edbDataList {
|
|
|
|
+ if dataList, ok := v.DataList.([]*models.EdbDataList); ok {
|
|
|
|
+ // 遍历所有的 dataList,保留所有时间点在所有指标中都存在的数据
|
|
|
|
+ var resultDataList []*models.EdbDataList
|
|
|
|
+ for _, dataObject := range dataList {
|
|
|
|
+ if timeMap[dataObject.DataTime] == len(edbDataList) {
|
|
|
|
+ // 如果该时间点在所有指标中都存在,加入到结果列表
|
|
|
|
+ resultDataList = append(resultDataList, dataObject)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 将符合条件的数据重新赋值回 v.DataList
|
|
|
|
+ v.DataList = resultDataList
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// 将列表颠倒
|
|
|
|
+func reverseSlice(dataList []*models.EdbDataList) {
|
|
|
|
+ // 使用双指针法,前后两个指针向中间逼近
|
|
|
|
+ for i, j := 0, len(dataList)-1; i < j; i, j = i+1, j-1 {
|
|
|
|
+ // 交换位置
|
|
|
|
+ dataList[i], dataList[j] = dataList[j], dataList[i]
|
|
|
|
+ }
|
|
|
|
+}
|