瀏覽代碼

feat:基础的计算方法,整理列出来

Roc 1 年之前
父節點
當前提交
e0cb4fcf8b
共有 3 個文件被更改,包括 1672 次插入5 次删除
  1. 1670 0
      models/base_calculate.go
  2. 0 3
      models/edb_data_calculate_hcz.go
  3. 2 2
      models/edb_data_calculate_rjz.go

+ 1670 - 0
models/base_calculate.go

@@ -0,0 +1,1670 @@
+package models
+
+import (
+	"errors"
+	"eta/eta_index_lib/utils"
+	"fmt"
+	"github.com/shopspring/decimal"
+	"strconv"
+	"strings"
+	"time"
+)
+
+type BaseCalculate struct {
+	DataList      []*EdbInfoSearchData
+	Frequency     string `description:"需要转换的频度"`
+	Formula       interface{}
+	Calendar      string `description:"公历/农历"`
+	MoveType      int    `description:"移动方式:1:领先(默认),2:滞后"`
+	MoveFrequency string `description:"移动频度"`
+	FromFrequency string `description:"来源的频度"`
+}
+
+// Ljzzy
+// @Description: 累计值转月
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:05:19
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) Ljzzy() (dateDataMap map[string]float64, err error) {
+	dataList := obj.DataList
+	// 数据处理
+	yearMap := make(map[int]map[int]*EdbInfoSearchData)
+	dataLen := len(dataList)
+	for i := 0; i < dataLen; i++ {
+		item := dataList[i]
+		//日其中获取年
+		itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		year := itemDate.Year()
+		month := int(itemDate.Month())
+		if monthMap, yok := yearMap[year]; yok {
+			monthMap[month] = item
+			yearMap[year] = monthMap
+		} else {
+			monthMap = make(map[int]*EdbInfoSearchData)
+			monthMap[month] = item
+			yearMap[year] = monthMap
+		}
+	}
+
+	// 开始计算
+	for yk, yv := range yearMap {
+		_, oneMonthOk := yv[1]
+		_, twoMonthOk := yv[2]
+		if !oneMonthOk && !twoMonthOk {
+			continue
+		}
+		for i := 1; i <= 12; i++ {
+			//fmt.Println(yk, i, yv[i])
+			dataCurrentItem := yv[i]
+			if dataCurrentItem == nil {
+				continue
+			}
+			var date string
+			var val float64
+
+			// 一二月单独处理
+			if i == 1 || i == 2 {
+				if _, mok := yv[1]; mok { //1月有值
+					if i == 1 {
+						date = dataCurrentItem.DataTime
+						val, _ = decimal.NewFromFloat(dataCurrentItem.Value).Float64() //a.Div(b).Float64()
+					}
+					if i == 2 {
+						dataOneItem := yv[1]
+						date = dataCurrentItem.DataTime
+						twoMonth := decimal.NewFromFloat(dataCurrentItem.Value)
+						oneMonth := decimal.NewFromFloat(dataOneItem.Value)
+						val, _ = twoMonth.Sub(oneMonth).Float64()
+					}
+				} else { //1月无值
+					dataTwoItem := yv[2]
+					if i == 1 {
+						date = strconv.Itoa(yk) + "-01-31"
+						a := decimal.NewFromFloat(dataTwoItem.Value)
+						b := decimal.NewFromFloat(2.0)
+						val, _ = a.Div(b).Float64()
+					}
+					if i == 2 {
+						//1月无值:1月=2月/2 (不管怎样,都要给1月赋值)
+						{
+							date = strconv.Itoa(yk) + "-01-31"
+							a := decimal.NewFromFloat(dataTwoItem.Value)
+							b := decimal.NewFromFloat(2.0)
+							val, _ = a.Div(b).Float64()
+							dateDataMap[date] = val
+						}
+						//end 1月无值
+
+						// 这是正常二月份的值
+						date = dataCurrentItem.DataTime
+						a := decimal.NewFromFloat(dataTwoItem.Value)
+						b := decimal.NewFromFloat(2.0)
+						val, _ = a.Div(b).Float64()
+					}
+				}
+			} else {
+				dataPreItem := yv[i-1]
+				if dataCurrentItem != nil && dataPreItem != nil {
+					date = dataCurrentItem.DataTime
+					//val =  dataCurrentItem.Value - dataPreItem.Value
+					a := decimal.NewFromFloat(dataCurrentItem.Value)
+					b := decimal.NewFromFloat(dataPreItem.Value)
+					val, _ = a.Sub(b).Float64()
+				}
+			}
+
+			// 如果没有日期,那么就退出当前循环,进入下一个循环
+			if date == "" {
+				continue
+			}
+
+			dateDataMap[date] = val
+		}
+	}
+
+	return
+}
+
+// Ljzzj
+// @Description: 累计值转季度
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:05:05
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) Ljzzj() (dateDataMap map[string]float64, err error) {
+	dataList := obj.DataList
+	// 数据处理
+	yearMap := make(map[int]map[int]*EdbInfoSearchData)
+	dataLen := len(dataList)
+	for i := 0; i < dataLen; i++ {
+		item := dataList[i]
+		//日其中获取年
+		itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		year := itemDate.Year()
+		quarter := utils.MonthQuarterMap[int(itemDate.Month())]
+		if quarterMap, yok := yearMap[year]; yok {
+			quarterMap[quarter] = item
+			yearMap[year] = quarterMap
+		} else {
+			quarterMap = make(map[int]*EdbInfoSearchData)
+			quarterMap[quarter] = item
+			yearMap[year] = quarterMap
+		}
+	}
+
+	// 开始计算
+	for yk, yv := range yearMap {
+		_, oneQuarterOk := yv[1]
+		_, twoQuarterOk := yv[2]
+		if !oneQuarterOk && !twoQuarterOk {
+			continue
+		}
+		for i := 1; i <= 4; i++ {
+			//fmt.Println(yk, i, yv[i])
+			dataCurrentItem := yv[i]
+			if dataCurrentItem == nil {
+				continue
+			}
+			var date string
+			var val float64
+
+			// 一二季度单独处理
+			if i == 1 || i == 2 {
+				if _, mok := yv[1]; mok { //第1个季度有值
+					if i == 1 {
+						date = dataCurrentItem.DataTime
+						val, _ = decimal.NewFromFloat(dataCurrentItem.Value).Float64() //a.Div(b).Float64()
+					}
+					if i == 2 {
+						dataOneItem := yv[1]
+						date = dataCurrentItem.DataTime
+						twoQuarter := decimal.NewFromFloat(dataCurrentItem.Value)
+						oneQuarter := decimal.NewFromFloat(dataOneItem.Value)
+						val, _ = twoQuarter.Sub(oneQuarter).Float64()
+					}
+				} else { //第1个季度无值
+					dataTwoItem := yv[2]
+					if i == 1 {
+						date = strconv.Itoa(yk) + "-03-31"
+						a := decimal.NewFromFloat(dataTwoItem.Value)
+						b := decimal.NewFromFloat(2.0)
+						val, _ = a.Div(b).Float64()
+					}
+					if i == 2 {
+						//第1个季度无值:第1个季度=第2个季度/2 (不管怎样,都要给1季度赋值)
+						{
+							date = strconv.Itoa(yk) + "-03-31"
+							a := decimal.NewFromFloat(dataTwoItem.Value)
+							b := decimal.NewFromFloat(2.0)
+							val, _ = a.Div(b).Float64()
+
+							dateDataMap[date] = val
+						}
+						//end 第1个季度无值
+
+						date = dataCurrentItem.DataTime
+						a := decimal.NewFromFloat(dataTwoItem.Value)
+						b := decimal.NewFromFloat(2.0)
+						val, _ = a.Div(b).Float64()
+					}
+				}
+			} else {
+				dataPreItem := yv[i-1]
+				if dataCurrentItem != nil && dataPreItem != nil {
+					date = dataCurrentItem.DataTime
+					//val =  dataCurrentItem.Value - dataPreItem.Value
+					a := decimal.NewFromFloat(dataCurrentItem.Value)
+					b := decimal.NewFromFloat(dataPreItem.Value)
+					val, _ = a.Sub(b).Float64()
+				}
+			}
+
+			// 如果没有日期,那么就退出当前循环,进入下一个循环
+			if date == "" {
+				continue
+			}
+
+			dateDataMap[date] = val
+		}
+	}
+
+	return
+}
+
+// Tbz
+// @Description: 同比值计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:04:59
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) Tbz() (dateDataMap map[string]float64, err error) {
+	dataList := obj.DataList
+	//数据处理
+	var dateArr []string
+	dataMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+	}
+
+	// 开始计算
+	for _, av := range dateArr {
+		currentItem, ok := dataMap[av]
+		if !ok {
+			continue
+		}
+
+		//当前日期
+		currentDate, tmpErr := time.ParseInLocation(utils.FormatDate, av, time.Local)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+
+		// 找到的数据
+		var findItem *EdbInfoSearchData
+
+		//上一年的日期
+		preDate := currentDate.AddDate(-1, 0, 0)
+		preDateStr := preDate.Format(utils.FormatDate)
+		if findItem, ok = dataMap[preDateStr]; !ok { //上一年同期没找到
+			if obj.Frequency == "月度" { //向上和向下,各找一个月
+				for i := 0; i <= 35; i++ {
+					nextDateDay := preDate.AddDate(0, 0, i)
+					nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+					if findItem, ok = dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+						break
+					} else {
+						preDateDay := preDate.AddDate(0, 0, -i)
+						preDateDayStr := preDateDay.Format(utils.FormatDate)
+						if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+							break
+						}
+					}
+				}
+			} else if obj.Frequency == "季度" || obj.Frequency == "年度" {
+				if findItem, ok = dataMap[preDateStr]; ok { //上一年同期->下一个月找到
+					break
+				}
+			} else {
+				nextDateDay := preDate.AddDate(0, 0, 1)
+				nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+
+				preDateDay := preDate.AddDate(0, 0, -1)
+				preDateDayStr := preDateDay.Format(utils.FormatDate)
+
+				for i := 0; i < 35; i++ {
+					if i >= 1 {
+						nextDateDay = nextDateDay.AddDate(0, 0, i)
+						nextDateDayStr = nextDateDay.Format(utils.FormatDate)
+					}
+					if findItem, ok = dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+						break
+					} else {
+						if i >= 1 {
+							preDateDay = preDateDay.AddDate(0, 0, -i)
+							preDateDayStr = preDateDay.Format(utils.FormatDate)
+						}
+						if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+							break
+						}
+					}
+				}
+			}
+
+		}
+
+		// 如果没找到数据
+		if findItem == nil {
+			continue
+		}
+
+		dateDataMap[av] = tbzDiv(currentItem.Value, findItem.Value)
+	}
+
+	return
+}
+
+// tbzDiv
+// @Description: 同比值计算
+// @author: Roc
+// @datetime2023-11-02 16:29:14
+// @param a float64
+// @param b float64
+// @return float64
+func tbzDiv(a, b float64) float64 {
+	var val float64
+	if b != 0 {
+		af := decimal.NewFromFloat(a)
+		bf := decimal.NewFromFloat(b)
+		val, _ = af.Div(bf).Sub(decimal.NewFromFloat(1)).RoundCeil(4).Float64()
+	}
+	return val
+}
+
+// Tcz
+// @Description: 计算同差值
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:04:51
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) Tcz() (dateDataMap map[string]float64, err error) {
+	dataList := obj.DataList
+	// 数据处理
+	var dateArr []string
+	dataMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+	}
+
+	// 开始计算
+	for _, av := range dateArr {
+		currentItem, ok := dataMap[av]
+		if !ok {
+			continue
+		}
+
+		//当前日期
+		currentDate, tmpErr := time.ParseInLocation(utils.FormatDate, av, time.Local)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+
+		// 找到的数据
+		var findItem *EdbInfoSearchData
+
+		//上一年的日期
+		preDate := currentDate.AddDate(-1, 0, 0)
+		preDateStr := preDate.Format(utils.FormatDate)
+		if findItem, ok = dataMap[preDateStr]; !ok {
+			//上一年同期没找到
+			if obj.Frequency == "月度" { //向上和向下,各找一个月
+				for i := 0; i <= 35; i++ {
+					nextDateDay := preDate.AddDate(0, 0, i)
+					nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+					if findItem, ok = dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+						break
+					} else {
+						preDateDay := preDate.AddDate(0, 0, -i)
+						preDateDayStr := preDateDay.Format(utils.FormatDate)
+						if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+							break
+						}
+					}
+				}
+			} else if obj.Frequency == "季度" || obj.Frequency == "年度" {
+				if findItem, ok = dataMap[preDateStr]; ok { //上一年同期->下一个月找到
+					break
+				}
+			} else {
+				for i := 0; i < 35; i++ {
+					nextDateDay := preDate.AddDate(0, 0, i)
+					nextDateDayStr := nextDateDay.Format(utils.FormatDate)
+					if findItem, ok = dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
+						break
+					} else {
+						preDateDay := preDate.AddDate(0, 0, -i)
+						preDateDayStr := preDateDay.Format(utils.FormatDate)
+						if findItem, ok = dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
+							break
+						}
+					}
+				}
+			}
+		}
+
+		// 如果没找到数据
+		if findItem == nil {
+			continue
+		}
+
+		dateDataMap[av] = tczSub(currentItem.Value, findItem.Value)
+	}
+
+	return
+}
+
+// tczSub
+// @Description: 计算同差值
+// @author: Roc
+// @datetime2023-11-02 18:01:46
+// @param a float64
+// @param b float64
+// @return float64
+func tczSub(a, b float64) float64 {
+	af := decimal.NewFromFloat(a)
+	bf := decimal.NewFromFloat(b)
+	val, _ := af.Sub(bf).RoundCeil(4).Float64()
+	return val
+}
+
+// Nszydpjjs
+// @Description: N数值移动平均数计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:17:38
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) Nszydpjjs() (dateDataMap map[string]float64, err error) {
+	fromDataList := obj.DataList
+	formulaInt := obj.Formula.(int)
+
+	// 数据处理
+	var fromDateArr []string
+	fromDataMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range fromDataList {
+		fromDateArr = append(fromDateArr, v.DataTime)
+		fromDataMap[v.DataTime] = v
+	}
+
+	arrLen := len(fromDateArr)
+	for ak, av := range fromDateArr {
+		//处理第一个值
+		var valArr []float64
+		if findItem, ok := fromDataMap[av]; ok {
+			valArr = append(valArr, findItem.Value)
+		} else {
+			continue
+		}
+		if ak+1 != arrLen {
+			//处理除第一个值之外的N-1个值
+			for i := 1; i < formulaInt; i++ {
+				arrIndex := ak + i
+				if arrIndex >= arrLen {
+					break
+				}
+				arrVal := fromDateArr[arrIndex]
+				if findItem, ok := fromDataMap[arrVal]; ok {
+					valArr = append(valArr, findItem.Value)
+				} else {
+					continue
+				}
+			}
+		}
+		valArrLen := len(valArr)
+		//var totalVal float64
+		totalVal := decimal.NewFromFloat(0.00)
+		for _, v := range valArr {
+			newDecimal := decimal.NewFromFloat(v)
+			totalVal = totalVal.Add(newDecimal)
+		}
+		af := totalVal //decimal.NewFromFloat(totalVal)
+		bf := decimal.NewFromFloat(float64(valArrLen))
+		val, _ := af.Div(bf).RoundCeil(4).Float64()
+
+		dateDataMap[av] = val
+	}
+
+	return
+}
+
+// Hbz
+// @Description: 环比值计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:28:24
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) Hbz() (dateDataMap map[string]float64, err error) {
+	dataList := obj.DataList
+	formulaInt := obj.Formula.(int)
+
+	// 数据处理
+	var dateArr []string
+	dataMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+	}
+
+	// 数据计算
+	dataLen := len(dataList)
+	//fmt.Println("dataLen:", dataLen)
+	for i := 0; i < dataLen; i++ {
+		j := i + formulaInt
+		if j < dataLen {
+			//当期
+			currentItem := dataList[i]
+			preItem := dataList[j]
+
+			// 当期和上期没有数据
+			if currentItem == nil || preItem == nil {
+				continue
+			}
+
+			// 开始计算
+			val, ok := hbzDiv(currentItem.Value, preItem.Value)
+			// 计算失败
+			if !ok {
+				continue
+			}
+
+			dateDataMap[currentItem.DataTime] = val
+		}
+	}
+
+	return
+}
+
+// hbzDiv
+// @Description: 环比值计算,current:当期,pre:上期 公式: (当期-上期)/上期
+// @author: Roc
+// @datetime2023-11-02 18:20:11
+// @param current float64
+// @param pre float64
+// @return val float64
+// @return ok bool
+func hbzDiv(current, pre float64) (val float64, ok bool) {
+	if pre == 0 {
+		return
+	}
+	currentVal := decimal.NewFromFloat(current)
+	preVal := decimal.NewFromFloat(pre)
+	val, _ = currentVal.Sub(preVal).Div(preVal).RoundCeil(4).Float64()
+	//valStr := decimal.NewFromFloat(val).RoundCeil(4).String() //utils.SubFloatToString(val, 4)
+	ok = true
+
+	return
+}
+
+// Hcz
+// @Description: 计算环差值数据
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:33:20
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) Hcz() (dateDataMap map[string]float64, err error) {
+	dataList := obj.DataList
+	formulaInt := obj.Formula.(int)
+
+	// 数据处理
+	var dateArr []string
+	dataMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+	}
+
+	dataLen := len(dataList)
+	fmt.Println("dataLen:", dataLen)
+	for i := 0; i < dataLen; i++ {
+		j := i + formulaInt
+		if j < dataLen {
+			//当期
+			currentItem := dataList[i]
+			preItem := dataList[j]
+
+			// 当期和上期没有数据
+			if currentItem == nil || preItem == nil {
+				continue
+			}
+
+			// 开始计算
+			val := hczDiv(currentItem.Value, preItem.Value)
+
+			dateDataMap[currentItem.DataTime] = val
+		}
+	}
+
+	return
+}
+
+// hczDiv
+// @Description: 环差值计算,current:当期,pre:上期 公式:当期-上期
+// @author: Roc
+// @datetime2023-11-02 18:33:07
+// @param current float64
+// @param pre float64
+// @return float64
+func hczDiv(current, pre float64) float64 {
+	currentVal := decimal.NewFromFloat(current)
+	preVal := decimal.NewFromFloat(pre)
+	val, _ := currentVal.Sub(preVal).RoundCeil(4).Float64()
+	//valStr := decimal.NewFromFloat(val).RoundCeil(4).String() //utils.SubFloatToString(val, 4)
+
+	return val
+}
+
+// UpFrequency
+// @Description: 升频计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:43:03
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) UpFrequency() (dateDataMap map[string]float64, err error) {
+	dataList := obj.DataList
+
+	// 数据处理
+	var dateArr []string
+	dataMap := make(map[string]*EdbInfoSearchData)
+	fromDataMap := make(map[string]float64)
+	//来源指指标数据
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+		fromDataMap[v.DataTime] = v.Value
+	}
+
+	// 数据计算
+	dataLen := len(dataList)
+	for i := 0; i < dataLen; i++ {
+		//当期
+		currentItem := dataList[i]
+		currentDate, _ := time.ParseInLocation(utils.FormatDate, currentItem.DataTime, time.Local)
+		var day int
+		var preItem *EdbInfoSearchData
+		var preDate time.Time
+		if i == 0 {
+			day = int(time.Now().Sub(currentDate).Hours() / float64(24))
+			preDate = time.Now()
+		} else {
+			j := i - 1
+			if j < dataLen {
+				preItem = dataList[j]
+				preDate, _ = time.ParseInLocation(utils.FormatDate, preItem.DataTime, time.Local)
+				day = int(preDate.Sub(currentDate).Hours() / float64(24))
+				utils.FileLog.Info("preItem.DataTime:" + preItem.DataTime + ";currentItem.DataTime" + currentItem.DataTime)
+			}
+		}
+		for k := 0; k <= day; k++ {
+			needDay := preDate.AddDate(0, 0, -k)
+			dateDataMap[needDay.Format(utils.FormatDate)] = currentItem.Value
+		}
+		dateDataMap[currentItem.DataTime] = currentItem.Value
+	}
+
+	return
+}
+
+// DownFrequency
+// @Description: 降频计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-02 18:51:26
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) DownFrequency() (dateDataMap map[string]float64, err error) {
+	dataList := obj.DataList
+	edbFrequency := obj.Frequency
+	formula := obj.Formula.(string)
+
+	// 数据处理
+	var dateArr []string
+	dataMap := make(map[string]*EdbInfoSearchData)
+	fromDataMap := make(map[string]float64)
+	//来源指指标数据
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+		fromDataMap[v.DataTime] = v.Value
+	}
+
+	// 数据计算
+	dataLen := len(dataList)
+	if dataLen <= 0 {
+		return
+	}
+	startDataTime, _ := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
+	endDataTime, _ := time.ParseInLocation(utils.FormatDate, dataList[dataLen-1].DataTime, time.Local)
+
+	var lastValue float64     // 最近的值
+	var nextEndDate time.Time // 下一个节点的日期
+	weekDayDataList := make([]float64, 0)
+	for tmpStartDataTime := startDataTime; !tmpStartDataTime.After(endDataTime); tmpStartDataTime = tmpStartDataTime.AddDate(0, 0, 1) {
+		// 将当前数据加入到 weekDayDataList
+		if tmpData, ok := dataMap[tmpStartDataTime.Format(utils.FormatDate)]; ok {
+			tmpValue := decimal.NewFromFloat(tmpData.Value)
+			tmpValueFloat, _ := tmpValue.Round(4).Float64()
+			weekDayDataList = append(weekDayDataList, tmpValueFloat)
+		}
+		// 如果下个节点的日期不存在,那么就先给赋值(兼容时间区间内只有一组数据的情况)
+		if nextEndDate.IsZero() {
+			nextEndDate = utils.GetFrequencyEndDay(tmpStartDataTime, edbFrequency)
+		}
+
+		// 日期处理过滤
+		switch edbFrequency {
+		case "周度":
+			if tmpStartDataTime.Weekday() != 0 {
+				//不是周日,代表需要进入下一个循环获取数据并计算
+				continue
+			} else {
+				//记录下一个结束节点的日期
+				nextEndDate = tmpStartDataTime.AddDate(0, 0, 7)
+			}
+		case "旬度":
+			nextDay := tmpStartDataTime.AddDate(0, 0, 1)
+			if nextDay.Day() != 1 && nextDay.Day() != 11 && nextDay.Day() != 21 {
+				//不是每月10、20、最后一天,代表需要进入下一个循环获取数据并计算
+				continue
+			} else {
+				//记录下一个结束节点的日期
+				if nextDay.Day() == 1 || nextDay.Day() == 11 {
+					//月初或者月末的时候,加10天就好了
+					nextEndDate = nextDay.AddDate(0, 0, 9)
+				} else {
+					tmpNextMonth := nextDay.AddDate(0, 1, 0)
+					nextEndDate = time.Date(tmpNextMonth.Year(), tmpNextMonth.Month(), 1, 0, 0, 0, 0, time.Local).AddDate(0, 0, -1)
+				}
+			}
+		case "月度":
+			nextDay := tmpStartDataTime.AddDate(0, 0, 1)
+			if nextDay.Day() != 1 {
+				//不是每月最后一天,代表需要进入下一个循环获取数据并计算
+				continue
+			} else {
+				//记录下一个结束节点的日期
+				nextEndDate = nextDay.AddDate(0, 1, -1)
+			}
+		case "季度":
+			nextDay := tmpStartDataTime.AddDate(0, 0, 1)
+			if (nextDay.Month() == 1 || nextDay.Month() == 4 || nextDay.Month() == 7 || nextDay.Month() == 10) && nextDay.Day() == 1 {
+				//记录下一个结束节点的日期
+				nextEndDate = nextDay.AddDate(0, 3, -1)
+			} else {
+				//不是3,6,9,12 月份的最后一天,代表需要进入下一个循环获取数据并计算
+				continue
+			}
+		case "年度":
+			if tmpStartDataTime.Month() == 12 && tmpStartDataTime.Day() == 31 {
+				//记录下一个结束节点的日期
+				nextEndDate = tmpStartDataTime.AddDate(1, 0, 0)
+			} else {
+				//不是每年的12-31日,代表需要进入下一个循环获取数据并计算
+				continue
+			}
+		default:
+			err = errors.New("错误的频度:" + edbFrequency)
+			return
+		}
+
+		// 当前时间段内的数据计算,得出实际值
+		var currVal float64
+		lenWeekDayDataList := len(weekDayDataList)
+		// 如果这个时间区间内没有数据,那么就采用上一个时间区间的值
+		if len(weekDayDataList) <= 0 {
+			currVal = lastValue
+		} else {
+			if formula == "期末值" {
+				currVal = weekDayDataList[lenWeekDayDataList-1]
+			} else {
+				// 平均值
+				sumValDeci := decimal.NewFromFloat(0)
+				for _, v := range weekDayDataList {
+					tmpValDeci := decimal.NewFromFloat(v)
+					sumValDeci = sumValDeci.Add(tmpValDeci)
+				}
+				lenDeci := decimal.NewFromInt(int64(lenWeekDayDataList))
+				currVal, _ = sumValDeci.Div(lenDeci).Round(4).Float64()
+			}
+		}
+
+		// 赋值
+		dateDataMap[tmpStartDataTime.Format(utils.FormatDate)] = currVal
+
+		// 一轮结束后,数据清空
+		weekDayDataList = make([]float64, 0)
+	}
+
+	// 最后已有的日期处理完成后,需要对剩余不在时间段内的数据做处理
+	if len(weekDayDataList) > 0 {
+		// 当前时间段内的数据计算,得出实际值
+		var currVal float64
+		lenWeekDayDataList := len(weekDayDataList)
+		// 如果这个时间区间内没有数据,那么就采用上一个时间区间的值
+		if len(weekDayDataList) < 0 {
+			currVal = lastValue
+		} else {
+			if formula == "期末值" {
+				currVal = weekDayDataList[lenWeekDayDataList-1]
+			} else {
+				// 平均值
+				sumValDeci := decimal.NewFromFloat(0)
+				for _, v := range weekDayDataList {
+					tmpValDeci := decimal.NewFromFloat(v)
+					sumValDeci = sumValDeci.Add(tmpValDeci)
+				}
+				lenDeci := decimal.NewFromInt(int64(lenWeekDayDataList))
+				currVal, _ = sumValDeci.Div(lenDeci).Round(4).Float64()
+			}
+		}
+
+		// 赋值
+		dateDataMap[nextEndDate.Format(utils.FormatDate)] = currVal
+	}
+
+	return
+}
+
+// TimeShift
+// @Description: 时间移位计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-03 13:19:07
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) TimeShift() (dateDataMap map[string]float64, err error) {
+	dataList := obj.DataList
+	formulaInt := obj.Formula.(int)
+	moveType := obj.MoveType
+	moveFrequency := obj.MoveFrequency
+
+	// 数据处理
+	var dateArr []string
+	dataMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+	}
+
+	var shiftDay int
+	switch moveFrequency {
+	case "天":
+		shiftDay = formulaInt
+	case "周":
+		shiftDay = formulaInt * 7
+	case "月":
+		shiftDay = formulaInt * 30
+	case "季":
+		shiftDay = formulaInt * 90
+	case "年":
+		shiftDay = formulaInt * 365
+	default:
+		shiftDay = formulaInt
+	}
+
+	if moveType == 2 {
+		shiftDay = -shiftDay
+	}
+
+	dataLen := len(dataList)
+	for i := 0; i < dataLen; i++ {
+		//当期
+		currentItem := dataList[i]
+
+		currentDate, _ := time.ParseInLocation(utils.FormatDate, currentItem.DataTime, time.Local)
+		newDate := currentDate.AddDate(0, 0, shiftDay)
+
+		val, _ := decimal.NewFromFloat(currentItem.Value).RoundCeil(4).Float64()
+
+		dateDataMap[newDate.Format(utils.FormatDate)] = val
+	}
+
+	return
+}
+
+// Cjjx
+// @Description: 超季节性计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-03 13:28:23
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) Cjjx() (dateDataMap map[string]float64, err error) {
+	dataList := obj.DataList
+	formulaInt := obj.Formula.(int)
+	calendar := obj.Calendar
+
+	// 数据处理
+	var dateArr []string
+	dataMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+	}
+
+	// 通过插值法补全所有数据(包含周末)
+	handleDataMap := make(map[string]float64)
+	_, err = HandleDataByLinearRegression(dataList, handleDataMap)
+	if err != nil {
+		return
+	}
+
+	// 每个年份的日期数据需要平移的天数
+	moveDayMap := make(map[int]int, 0) // 每个年份的春节公历
+	var lastDataDay time.Time
+	if len(dataList) > 0 {
+		lastDataDay, _ = time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
+	}
+
+	// 数据计算
+	for _, av := range dateArr {
+		// 如果遇到闰二月,如2.29,去掉该天数据
+		if strings.Contains(av, "02-29") {
+			continue
+		}
+		currentDate, tmpErr := time.ParseInLocation(utils.FormatDate, av, time.Local)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		//农历的超季节性运算,只计算11月--次年5月,分段计算,与数据区间和N数值有关
+		if calendar == "农历" && currentDate.Month() > 5 && currentDate.Month() < 11 {
+			continue
+		}
+
+		currentItem, ok := dataMap[av]
+		// 找不到数据就退出当前循环,进入下一循环
+		if !ok {
+			continue
+		}
+
+		pastValueList := make([]float64, 0)                      // 过去几期的数据
+		pastValueList = append(pastValueList, currentItem.Value) //当前日期
+
+		for i := 1; i < formulaInt; i++ {
+			//前几年当天公历的日期
+			historyPreDate := currentDate.AddDate(-i, 0, 0)
+			moveDay := 0
+			if calendar == "农历" {
+				if tmpMoveDay, ok := moveDayMap[historyPreDate.Year()]; !ok {
+					moveDay, err = getMoveDay(lastDataDay, historyPreDate)
+					if err != nil {
+						return
+					}
+				} else {
+					moveDay = tmpMoveDay
+				}
+
+				// 移动天数到对应农历 的 公历 日期
+				historyPreDate = historyPreDate.AddDate(0, 0, moveDay)
+			}
+
+			historyPreDateStr := historyPreDate.Format(utils.FormatDate)
+			if tmpValue, ok := handleDataMap[historyPreDateStr]; ok { //上一年同期找到
+				pastValueList = append(pastValueList, tmpValue)
+			}
+		}
+
+		if len(pastValueList) == formulaInt {
+			val, ok := cjjxSub(currentItem.Value, pastValueList)
+			if !ok {
+				continue
+			}
+			dateDataMap[av] = val
+		}
+	}
+
+	return
+}
+
+// cjjxSub
+// @Description: 超季节性计算
+// @author: Roc
+// @datetime2023-11-03 13:25:49
+// @param currValue float64
+// @param pastValue []float64
+// @return value float64
+// @return ok bool
+func cjjxSub(currValue float64, pastValue []float64) (value float64, ok bool) {
+	num := len(pastValue)
+	if num == 0 {
+		return
+	}
+	numDecimal := decimal.NewFromInt(int64(num))
+
+	af := decimal.NewFromFloat(currValue)
+	bf := decimal.NewFromFloat(pastValue[0])
+
+	for k := 1; k < num; k++ {
+		tmpVal := decimal.NewFromFloat(pastValue[k])
+		bf = bf.Add(tmpVal)
+	}
+	value, _ = af.Sub(bf.Div(numDecimal)).RoundCeil(4).Float64()
+	ok = true
+
+	return
+}
+
+// Annualized
+// @Description: 年化计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-03 13:34:32
+// @param to orm.TxOrmer
+// @param edbInfoId int
+// @param source int
+// @param fromEdbInfo *EdbInfo
+// @param edbCode string
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) Annualized() (dateDataMap map[string]float64, err error) {
+	fromDataList := obj.DataList
+	lenFromDataList := len(fromDataList)
+	// 如果来源指标没有数据,那么就直接返回得了
+	if lenFromDataList <= 0 {
+		return
+	}
+
+	// 数据处理
+	// 插值法数据处理
+	handleDataMap := make(map[string]float64)
+	_, err = HandleDataByLinearRegression(fromDataList, handleDataMap)
+	if err != nil {
+		return
+	}
+
+	// 每年的最后一天的数据值
+	yearLastValMap := make(map[int]float64)
+	startDataTime, _ := time.ParseInLocation(utils.FormatDate, fromDataList[0].DataTime, time.Local)
+	endDataTime, _ := time.ParseInLocation(utils.FormatDate, fromDataList[lenFromDataList-1].DataTime, time.Local)
+	for i := startDataTime.Year(); i <= endDataTime.Year(); i++ {
+		tmpDateStr := fmt.Sprintf("%d-12-31", i)
+		if tmpVal, ok := handleDataMap[tmpDateStr]; ok {
+			yearLastValMap[i] = tmpVal
+		}
+	}
+
+	// 数据计算
+	// 遍历来源指标数据
+	for _, v := range fromDataList {
+		currDateStr := v.DataTime
+		currDate, _ := time.ParseInLocation(utils.FormatDate, currDateStr, time.Local)
+
+		perValMap := make(map[time.Time]float64)
+		//前3年当日的数据
+		for i := 1; i <= 3; i++ {
+			tmpDateTime := currDate.AddDate(-i, 0, 0)
+			if tmpVal, ok := handleDataMap[tmpDateTime.Format(utils.FormatDate)]; ok {
+				perValMap[tmpDateTime] = tmpVal
+			}
+		}
+		lenPerValMap := len(perValMap)
+		// 如果数据少于2年,那么就不参与计算,结束当前循环,进入下一个循环
+		if lenPerValMap < 2 {
+			continue
+		}
+
+		// N年 当前值占全年比重 的值列表
+		divValList := make([]decimal.Decimal, 0)
+		for tmpDateTime, tmpVal := range perValMap {
+			yearLastVal, ok2 := yearLastValMap[tmpDateTime.Year()]
+			// 如果当年最后一天没有数据
+			if !ok2 {
+				continue
+			}
+
+			// 当前值占全年比重
+			tmpYearLastVal := decimal.NewFromFloat(yearLastVal)
+			if tmpYearLastVal.IsZero() { //如果是0,那么就退出当前循环,进入下一个循环
+				continue
+			}
+			divVal := decimal.NewFromFloat(tmpVal).Div(tmpYearLastVal)
+			divValList = append(divValList, divVal)
+		}
+
+		lenDivValList := len(divValList)
+		// 如果 N年 当前值占全年比重 的值 小于 2个,那么就不参与计算,结束当前循环,进入下一个循环
+		if lenDivValList < 2 {
+			continue
+		}
+
+		divValSum := decimal.NewFromFloat(0)
+		for _, divVal := range divValList {
+			divValSum = divValSum.Add(divVal)
+		}
+
+		// 当前计算出来的结果
+		tmpDivVal := divValSum.Div(decimal.NewFromInt(int64(lenDivValList)))
+		if tmpDivVal.IsZero() { //如果是0,那么就退出当前循环,进入下一个循环
+			continue
+		}
+		currVal, _ := decimal.NewFromFloat(v.Value).Div(tmpDivVal).Round(4).Float64()
+
+		dateDataMap[currDateStr] = currVal
+	}
+
+	return
+}
+
+// Ljz
+// @Description: 累计值
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-03 13:49:17
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) Ljz() (dateDataMap map[string]float64, err error) {
+	dataList := obj.DataList
+	frequency := obj.Frequency         //需要变更的频度
+	fromFrequency := obj.FromFrequency //来源的频度
+
+	// 数据处理
+	var isWeekData bool // 是否周度数据,如果是周度数据的话,是需要变频的,最后结果还需要除以7
+	// 周度数据需要先变成日度的
+	if fromFrequency == `周度` {
+		isWeekData = true
+	}
+
+	fromEdbDataMap := make(map[string]float64)
+	if isWeekData {
+		dataList, err = HandleDataByLinearRegression(dataList, fromEdbDataMap)
+		if err != nil {
+			return
+		}
+	}
+
+	//日度转周度:日期选周五,计算上周六到本周五的日度值的加总,最新日期为最新值对应的周五。
+	//日度转月度:日期选每个月最后一天,计算当月所有日度值的加总,最新日期为最新值对应当月最后一天。
+	//日度转季度、年度:方法类似转月度。
+	//周度转月度/季度/年度:将周度值转成日度,空值用插值法插值,计算当月/当季/当年所有值的加总,然后除以7。
+	//月度转季度/年度: 当季/当年月度值相加。
+
+	dateList := make([]time.Time, 0)
+	valueMap := make(map[time.Time]float64)
+	switch frequency {
+	case "年度":
+		yearMap := make(map[int]float64)
+		yearList := make([]int, 0)
+		for _, item := range dataList {
+			itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			year := itemDate.Year()
+			yearVal, ok := yearMap[year]
+			if ok {
+				yearMap[year] = item.Value + yearVal
+			} else {
+				yearList = append(yearList, year)
+				yearMap[year] = item.Value
+			}
+		}
+		for _, v := range yearList {
+			currTime := time.Date(v, 12, 31, 0, 0, 0, 0, time.Local)
+			dateList = append(dateList, currTime)
+			valueMap[currTime] = yearMap[v]
+		}
+	case "半年度":
+		yearMonthMap := make(map[string]float64)
+		yearMonthList := make([]string, 0)
+		for _, item := range dataList {
+			itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			year := itemDate.Year()
+			var tmpK string
+			if itemDate.Month() <= 6 {
+				tmpK = fmt.Sprint(year, "06")
+			} else {
+				tmpK = fmt.Sprint(year, "12")
+			}
+
+			yearVal, ok := yearMonthMap[tmpK]
+			if ok {
+				yearMonthMap[tmpK] = item.Value + yearVal
+			} else {
+				yearMonthList = append(yearMonthList, tmpK)
+				yearMonthMap[tmpK] = item.Value
+			}
+		}
+		for _, v := range yearMonthList {
+			currTime, tmpErr := time.ParseInLocation(utils.FormatYearMonthUnSpace, v, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			currTime = currTime.AddDate(0, 1, -1)
+			dateList = append(dateList, currTime)
+			valueMap[currTime] = yearMonthMap[v]
+		}
+	case "季度":
+		yearMonthMap := make(map[string]float64)
+		yearMonthList := make([]string, 0)
+		for _, item := range dataList {
+			itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			year := itemDate.Year()
+			var tmpK string
+			if itemDate.Month() <= 3 {
+				tmpK = fmt.Sprint(year, "03")
+			} else if itemDate.Month() <= 6 {
+				tmpK = fmt.Sprint(year, "06")
+			} else if itemDate.Month() <= 9 {
+				tmpK = fmt.Sprint(year, "09")
+			} else {
+				tmpK = fmt.Sprint(year, "12")
+			}
+
+			yearVal, ok := yearMonthMap[tmpK]
+			if ok {
+				yearMonthMap[tmpK] = item.Value + yearVal
+			} else {
+				yearMonthList = append(yearMonthList, tmpK)
+				yearMonthMap[tmpK] = item.Value
+			}
+		}
+		for _, v := range yearMonthList {
+			currTime, tmpErr := time.ParseInLocation(utils.FormatYearMonthUnSpace, v, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			currTime = currTime.AddDate(0, 1, -1)
+			dateList = append(dateList, currTime)
+			valueMap[currTime] = yearMonthMap[v]
+		}
+	case "月度":
+		yearMonthMap := make(map[string]float64)
+		yearMonthList := make([]string, 0)
+		for _, item := range dataList {
+			itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			year := itemDate.Year()
+			var tmpK string
+			tmpK = fmt.Sprint(year*100 + int(itemDate.Month()))
+
+			yearVal, ok := yearMonthMap[tmpK]
+			if ok {
+				yearMonthMap[tmpK] = item.Value + yearVal
+			} else {
+				yearMonthList = append(yearMonthList, tmpK)
+				yearMonthMap[tmpK] = item.Value
+			}
+		}
+		for _, v := range yearMonthList {
+			currTime, tmpErr := time.ParseInLocation(utils.FormatYearMonthUnSpace, v, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			currTime = currTime.AddDate(0, 1, -1)
+			dateList = append(dateList, currTime)
+			valueMap[currTime] = yearMonthMap[v]
+		}
+	case "旬度":
+		tmpDateDataMap := make(map[time.Time]float64)
+		tmpDateList := make([]time.Time, 0)
+		for _, item := range dataList {
+			itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			dayInt := itemDate.Year()*100 + int(itemDate.Month())
+			var currTime time.Time
+			if itemDate.Month() <= 10 {
+				tmpK := fmt.Sprint(dayInt*100, "10")
+				currTime, err = time.ParseInLocation(utils.FormatDateUnSpace, tmpK, time.Local)
+				if err != nil {
+					return
+				}
+
+			} else if itemDate.Month() <= 20 {
+				tmpK := fmt.Sprint(dayInt*100, "20")
+				currTime, err = time.ParseInLocation(utils.FormatDateUnSpace, tmpK, time.Local)
+				if err != nil {
+					return
+				}
+			} else {
+				currTime, err = time.ParseInLocation(utils.FormatYearMonthUnSpace, fmt.Sprint(dayInt), time.Local)
+				if err != nil {
+					return
+				}
+				currTime = currTime.AddDate(0, 1, -1)
+			}
+
+			yearVal, ok := tmpDateDataMap[currTime]
+			if ok {
+				tmpDateDataMap[currTime] = item.Value + yearVal
+			} else {
+				tmpDateList = append(tmpDateList, currTime)
+				tmpDateDataMap[currTime] = item.Value
+			}
+		}
+		for _, currTime := range tmpDateList {
+			dateList = append(dateList, currTime)
+			valueMap[currTime] = tmpDateDataMap[currTime]
+		}
+	case "周度":
+		tmpDateDataMap := make(map[time.Time]float64)
+		tmpDateList := make([]time.Time, 0)
+		for _, item := range dataList {
+			itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			var currTime time.Time
+			// 周六周日,这是下一个周五的数据
+			if itemDate.Weekday() == 0 {
+				currTime = itemDate.AddDate(0, 0, 5)
+			} else if itemDate.Weekday() == 6 {
+				currTime = itemDate.AddDate(0, 0, 6)
+			} else {
+				currTime = itemDate.AddDate(0, 0, 5-int(itemDate.Weekday()))
+			}
+
+			yearVal, ok := tmpDateDataMap[currTime]
+			if ok {
+				tmpDateDataMap[currTime] = item.Value + yearVal
+			} else {
+				tmpDateList = append(tmpDateList, currTime)
+				tmpDateDataMap[currTime] = item.Value
+			}
+		}
+		for _, currTime := range tmpDateList {
+			dateList = append(dateList, currTime)
+			valueMap[currTime] = tmpDateDataMap[currTime]
+		}
+	default:
+		err = errors.New("错误的频度")
+		return
+
+	}
+
+	// 数据计算
+	for _, currTime := range dateList {
+		currDateStr := currTime.Format(utils.FormatDate)
+
+		tmpVal, ok2 := valueMap[currTime]
+		if !ok2 {
+			err = errors.New("数据异常,date:" + currDateStr)
+			return
+		}
+		var saveValue float64
+		if isWeekData { //周度指标转的话,最后结果要除以7
+			saveValue, _ = decimal.NewFromFloat(tmpVal).Div(decimal.NewFromInt(7)).Round(4).Float64()
+		} else {
+			saveValue, _ = decimal.NewFromFloat(tmpVal).Round(4).Float64()
+		}
+
+		dateDataMap[currDateStr] = saveValue
+	}
+
+	return
+}
+
+// LjzNczj
+// @Description:年初至今累计值计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-03 13:55:44
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) LjzNczj() (dateDataMap map[string]float64, err error) {
+	dataList := obj.DataList
+	frequency := obj.Frequency         //需要变更的频度
+	fromFrequency := obj.FromFrequency //来源的频度
+
+	// 数据处理
+	var isWeekData bool // 是否周度数据,如果是周度数据的话,是需要变频的,最后结果还需要除以7
+	// 周度数据需要先变成日度的
+	if fromFrequency == `周度` {
+		isWeekData = true
+	}
+
+	fromEdbDataMap := make(map[string]float64)
+	if isWeekData {
+		dataList, err = HandleDataByLinearRegression(dataList, fromEdbDataMap)
+		if err != nil {
+			return
+		}
+	}
+
+	//日度数据年初至今:日期同原日度数据。将每年1月1日(含)到日度数据所在日期含间的日度值,进行加总。
+	//周度数据年初至今:日期同原周度数据。将周度值转成日度频率,空值用插值法插值,然后算法同日度年度至今,再除以7
+	//月度/季度数据年初至今:日期同原月度/季度数据,将每年1月1日(含)到月度数据所在日期(含)之间的月度/季度值,进行加总
+	//以此类推
+
+	dateList := make([]time.Time, 0)
+	valueMap := make(map[time.Time]float64)
+	yearMap := make(map[int]float64)
+	switch frequency {
+	case "周度":
+		tmpDateDataMap := make(map[time.Time]float64)
+		tmpDateList := make([]time.Time, 0)
+		for _, item := range dataList {
+			itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			var currTime time.Time
+			// 周六周日,这是下一个周五的数据
+			if itemDate.Weekday() == 0 {
+				currTime = itemDate.AddDate(0, 0, 5)
+			} else if itemDate.Weekday() == 6 {
+				currTime = itemDate.AddDate(0, 0, 6)
+			} else {
+				currTime = itemDate.AddDate(0, 0, 5-int(itemDate.Weekday()))
+			}
+
+			year := itemDate.Year()
+			yearVal, ok := yearMap[year]
+			if ok {
+				yearMap[year] = item.Value + yearVal
+			} else {
+				yearMap[year] = item.Value
+			}
+
+			if itemDate.Equal(currTime) {
+				tmpDateDataMap[itemDate] = yearMap[year]
+				tmpDateList = append(tmpDateList, itemDate)
+			}
+		}
+		for _, currTime := range tmpDateList {
+			dateList = append(dateList, currTime)
+			valueMap[currTime] = tmpDateDataMap[currTime]
+		}
+	default:
+		for _, item := range dataList {
+			itemDate, tmpErr := time.ParseInLocation(utils.FormatDate, item.DataTime, time.Local)
+			if tmpErr != nil {
+				err = tmpErr
+				return
+			}
+			year := itemDate.Year()
+			yearVal, ok := yearMap[year]
+			if ok {
+				yearMap[year] = item.Value + yearVal
+			} else {
+				yearMap[year] = item.Value
+			}
+			valueMap[itemDate] = yearMap[year]
+			dateList = append(dateList, itemDate)
+		}
+
+	}
+
+	// 数据计算
+	for _, currTime := range dateList {
+		currDateStr := currTime.Format(utils.FormatDate)
+		tmpVal, ok2 := valueMap[currTime]
+		if !ok2 {
+			err = errors.New("数据异常,date:" + currDateStr)
+			return
+		}
+		var saveValue float64
+		if isWeekData { //周度指标转的话,最后结果要除以7
+			saveValue, _ = decimal.NewFromFloat(tmpVal).Div(decimal.NewFromInt(7)).Round(4).Float64()
+		} else {
+			saveValue, _ = decimal.NewFromFloat(tmpVal).Round(4).Float64()
+		}
+
+		dateDataMap[currDateStr] = saveValue
+	}
+
+	return
+}
+
+// ExponentialSmoothing
+// @Description: 指数修匀计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-03 14:07:47
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) ExponentialSmoothing() (dateDataMap map[string]float64, err error) {
+	dataList := obj.DataList
+	formula := obj.Formula.(string) // alpha值
+
+	alpha, _ := strconv.ParseFloat(formula, 64)
+	if alpha <= 0 || alpha >= 1 {
+		err = fmt.Errorf("alpha值有误: %v", alpha)
+		return
+	}
+
+	// 获取标准差图表的指标数据
+	fromDataList, err := calculateExponentialSmoothingData(dataList, alpha)
+	if err != nil {
+		return
+	}
+
+	// 数据计算
+	for _, tmpData := range fromDataList {
+		_, tmpErr := time.ParseInLocation(utils.FormatDate, tmpData.DataTime, time.Local)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		// 当前的实际值
+		saveValue, _ := decimal.NewFromFloat(tmpData.Value).Round(4).Float64()
+
+		dateDataMap[tmpData.DataTime] = saveValue
+	}
+
+	return
+}
+
+// calculateExponentialSmoothingData
+// @Description: 计算指数修匀
+// @author: Roc
+// @datetime2023-11-03 14:05:41
+// @param dataList []*EdbInfoSearchData 时间基准指标在时间区间内的值
+// @param strAlpha float64
+// @return newDataList []EdbInfoSearchData
+// @return err error
+func calculateExponentialSmoothingData(dataList []*EdbInfoSearchData, alpha float64) (newDataList []EdbInfoSearchData, err error) {
+	if alpha <= 0 || alpha >= 1 {
+		err = fmt.Errorf("alpha值有误: %v", alpha)
+		return
+	}
+
+	var preVal float64
+	alphaDecimal := decimal.NewFromFloat(alpha)
+	subAlpha := decimal.NewFromFloat(1).Sub(alphaDecimal)
+	for k, d := range dataList {
+		// 首期的值以原始值作为指数修匀的计算值
+		if k == 0 {
+			newDataList = append(newDataList, EdbInfoSearchData{
+				EdbDataId: k,
+				DataTime:  dataList[k].DataTime,
+				Value:     d.Value,
+			})
+			preVal = d.Value
+			continue
+		}
+
+		// 上一期的值参与计算
+		preDecimal := decimal.NewFromFloat(preVal)
+		valDecimal := decimal.NewFromFloat(d.Value)
+
+		partA := alphaDecimal.Mul(valDecimal)
+		partB := subAlpha.Mul(preDecimal)
+		res, _ := (partA.Add(partB)).Float64()
+		preVal = res
+		newDataList = append(newDataList, EdbInfoSearchData{
+			EdbDataId: k,
+			DataTime:  dataList[k].DataTime,
+			Value:     res,
+		})
+	}
+	return
+}
+
+// Rjz
+// @Description: 日均值计算
+// @author: Roc
+// @receiver obj
+// @datetime2023-11-03 14:47:47
+// @return dateDataMap map[string]float64
+// @return err error
+func (obj BaseCalculate) Rjz() (dateDataMap map[string]float64, err error) {
+	dataList := obj.DataList
+
+	fromFrequency := obj.FromFrequency
+	if fromFrequency == `` {
+		err = errors.New("错误的频度:" + fromFrequency)
+		return
+	}
+
+	// 数据处理
+	var dateArr []string
+	dataMap := make(map[string]*EdbInfoSearchData)
+	for _, v := range dataList {
+		dateArr = append(dateArr, v.DataTime)
+		dataMap[v.DataTime] = v
+	}
+
+	// 数据计算
+	for _, av := range dateArr {
+		currentItem, ok := dataMap[av]
+		if !ok {
+			continue
+		}
+
+		//当前日期
+		currentDate, tmpErr := time.ParseInLocation(utils.FormatDate, av, time.Local)
+		if tmpErr != nil {
+			err = tmpErr
+			return
+		}
+		//根据频度计算需要均分的天数
+		days := GetRjzFrequencyDays(currentDate, fromFrequency)
+		val, ok := rjzDivV2(currentItem.Value, days)
+		if !ok {
+			continue
+		}
+
+		dateDataMap[av] = val
+	}
+
+	return
+}
+
+// rjzDivV2
+// @Description: 日均值计算
+// @author: Roc
+// @datetime2023-11-03 14:47:36
+// @param a float64
+// @param b int
+// @return val float64
+// @return ok bool
+func rjzDivV2(a float64, b int) (val float64, ok bool) {
+	if b == 0 {
+		return
+	}
+
+	af := decimal.NewFromFloat(a)
+	bf := decimal.NewFromFloat(float64(b))
+	val, _ = af.Div(bf).Round(4).Float64()
+
+	return
+}

+ 0 - 3
models/edb_data_calculate_hcz.go

@@ -330,9 +330,6 @@ func refreshAllCalculateHcz(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo *
 
 // HczDiv 环差值计算,current:当期,pre:上期 公式:当期-上期
 func HczDiv(current, pre float64) string {
-	if pre == 0 {
-		return ""
-	}
 	currentVal := decimal.NewFromFloat(current)
 	preVal := decimal.NewFromFloat(pre)
 	val, _ := currentVal.Sub(preVal).Float64()

+ 2 - 2
models/edb_data_calculate_rjz.go

@@ -256,7 +256,7 @@ func refreshAllCalculateRjz(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo *
 				return err
 			}
 			//根据频度计算需要均分的天数
-			days, err := GetRjzFrequencyDays(currentDate, fromEdbInfo.Frequency)
+			days := GetRjzFrequencyDays(currentDate, fromEdbInfo.Frequency)
 			val := rjzDiv(currentItem.Value, days)
 
 			timestamp := currentDate.UnixNano() / 1e6
@@ -290,7 +290,7 @@ func refreshAllCalculateRjz(to orm.TxOrmer, edbInfoId, source int, fromEdbInfo *
 	}
 	return
 }
-func GetRjzFrequencyDays(currDate time.Time, frequency string) (days int, err error) {
+func GetRjzFrequencyDays(currDate time.Time, frequency string) (days int) {
 	switch frequency {
 	case "周度", "周":
 		days = 7