Ver Fonte

feat:新增柱方图

Roc há 2 anos atrás
pai
commit
c366fcccbe
5 ficheiros alterados com 348 adições e 169 exclusões
  1. 36 155
      controllers/chart.go
  2. 24 13
      models/chart.go
  3. 27 0
      models/data_manage/chart_info.go
  4. 209 1
      services/data/chart_info.go
  5. 52 0
      utils/common.go

+ 36 - 155
controllers/chart.go

@@ -4,6 +4,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"hongze/hongze_chart_lib/models"
+	"hongze/hongze_chart_lib/models/data_manage"
 	"hongze/hongze_chart_lib/services/data"
 	"hongze/hongze_chart_lib/utils"
 	"strconv"
@@ -145,161 +146,38 @@ func (this *ChartController) ChartInfoDetail() {
 		return
 	}
 
-	//edbList := make([]*models.ChartEdbInfoMapping, 0)
-	//for _, v := range mappingList {
-	//	//minData, maxData, err := data_manage.GetEdbDataListMinAndMax(v.Source, v.EdbInfoId, startDate, endDate)
-	//	item := new(models.ChartEdbInfoMapping)
-	//	item.EdbInfoId = v.EdbInfoId
-	//	item.SourceName = v.SourceName
-	//	item.Source = v.Source
-	//	item.EdbCode = v.EdbCode
-	//	item.EdbName = v.EdbName
-	//	item.EdbNameEn = v.EdbNameEn
-	//	item.Frequency = v.Frequency
-	//	item.FrequencyEn = GetFrequencyEn(v.Frequency)
-	//	//无就是不展示
-	//	if v.Unit != `无` {
-	//		item.Unit = v.Unit
-	//	}
-	//	item.UnitEn = v.UnitEn
-	//	item.StartDate = v.StartDate
-	//	item.EndDate = v.EndDate
-	//	//item.ModifyTime = v.ModifyTime
-	//	//item.ChartEdbMappingId = v.ChartEdbMappingId
-	//	item.ChartInfoId = v.ChartInfoId
-	//	item.MaxData = v.MaxData
-	//	item.MinData = v.MinData
-	//	item.IsOrder = v.IsOrder
-	//	item.IsAxis = v.IsAxis
-	//	item.EdbInfoType = v.EdbInfoType
-	//	item.EdbType = v.EdbType
-	//	item.LeadValue = v.LeadValue
-	//	item.LeadUnit = v.LeadUnit
-	//	item.LeadUnitEn = GetLeadUnitEn(v.LeadUnit)
-	//	item.ChartStyle = v.ChartStyle
-	//	item.ChartColor = v.ChartColor
-	//	item.ChartWidth = v.ChartWidth
-	//
-	//	var startDateReal string
-	//	var diffSeconds int64
-	//	if chartType == 2 { //季节性图表
-	//		startDateReal = startDate
-	//	} else {
-	//		if v.EdbInfoType == 0 && v.LeadUnit != "" && v.LeadValue > 0 { //领先指标
-	//			var startTimeRealTemp time.Time
-	//			startDateParse, _ := time.Parse(utils.FormatDate, startDate)
-	//			switch v.LeadUnit {
-	//			case "天":
-	//				startTimeRealTemp = startDateParse.AddDate(0, 0, -v.LeadValue)
-	//			case "月":
-	//				startTimeRealTemp = startDateParse.AddDate(0, -v.LeadValue, 0)
-	//			case "季":
-	//				startTimeRealTemp = startDateParse.AddDate(0, -3*v.LeadValue, 0)
-	//			case "周":
-	//				startTimeRealTemp = startDateParse.AddDate(0, 0, -7*v.LeadValue)
-	//			case "年":
-	//				startTimeRealTemp = startDateParse.AddDate(-v.LeadValue, 0, 0)
-	//			}
-	//			if startTimeRealTemp.Before(startDateParse) {
-	//				startDateReal = startTimeRealTemp.Format(utils.FormatDate)
-	//				diffSeconds = (int64(startTimeRealTemp.UnixNano()) - int64(startDateParse.UnixNano())) / 1e6
-	//			} else {
-	//				startDateReal = startDate
-	//				diffSeconds = 0
-	//			}
-	//		} else {
-	//			startDateReal = startDate
-	//		}
-	//	}
-	//	calendarPreYear := 0
-	//	if calendar == "农历" {
-	//		newStartDateReal, err := time.Parse(utils.FormatDate, startDateReal)
-	//		if err != nil {
-	//			fmt.Println("time.Parse:" + err.Error())
-	//			utils.FileLog.Info("startDateReal parse err:" + err.Error())
-	//		}
-	//		calendarPreYear = newStartDateReal.Year() - 1
-	//		newStartDateReal = newStartDateReal.AddDate(-1, 0, 0)
-	//		startDateReal = newStartDateReal.Format(utils.FormatDate)
-	//	}
-	//	dataList := make([]*models.EdbDataList, 0)
-	//	fmt.Println("chart:", v.Source, v.EdbInfoId, startDateReal, endDate)
-	//	dataList, err = models.GetEdbDataList(v.Source, v.EdbInfoId, startDateReal, endDate)
-	//	if err != nil {
-	//		br.Msg = "获取失败"
-	//		br.Msg = "获取失败,Err:" + err.Error()
-	//		return
-	//	}
-	//	if diffSeconds != 0 && v.EdbInfoType == 0 {
-	//		dataListLen := len(dataList)
-	//		for i := 0; i < dataListLen; i++ {
-	//			dataList[i].DataTimestamp = dataList[i].DataTimestamp - diffSeconds
-	//		}
-	//	}
-	//
-	//	if chartType == 2 {
-	//		if calendar == "农历" {
-	//			result, err := models.AddCalculateQuarterV5(dataList)
-	//			if err != nil {
-	//				br.Msg = "获取失败"
-	//				br.Msg = "获取农历数据失败,Err:" + err.Error()
-	//				return
-	//			}
-	//			if result.List[0].Year != calendarPreYear {
-	//				itemList := make([]*models.EdbDataList, 0)
-	//				items := new(models.EdbDataItems)
-	//				//items.Year = calendarPreYear
-	//				items.Items = itemList
-	//
-	//				newResult := new(models.EdbDataResult)
-	//				newResult.List = append(newResult.List, items)
-	//				newResult.List = append(newResult.List, result.List...)
-	//				item.DataList = newResult
-	//			} else {
-	//				item.DataList = result
-	//			}
-	//		} else {
-	//			currentYear := time.Now().Year()
-	//			quarterDataList := make([]*models.QuarterData, 0)
-	//			quarterMap := make(map[int][]*models.EdbDataList)
-	//			var quarterArr []int
-	//			for _, v := range dataList {
-	//				//v.DataTime
-	//				itemDate, err := time.Parse(utils.FormatDate, v.DataTime)
-	//				if err != nil {
-	//					br.Msg = "获取失败"
-	//					br.Msg = "季度指标日期转换,Err:" + err.Error() + ";DataTime:" + v.DataTime
-	//					return
-	//				}
-	//				year := itemDate.Year()
-	//				newItemDate := itemDate.AddDate(currentYear-year, 0, 0)
-	//				timestamp := newItemDate.UnixNano() / 1e6
-	//				v.DataTimestamp = timestamp
-	//				if findVal, ok := quarterMap[year]; !ok {
-	//					quarterArr = append(quarterArr, year)
-	//					findVal = append(findVal, v)
-	//					quarterMap[year] = findVal
-	//				} else {
-	//					findVal = append(findVal, v)
-	//					quarterMap[year] = findVal
-	//				}
-	//			}
-	//			for _, v := range quarterArr {
-	//				itemList := quarterMap[v]
-	//				quarterItem := new(models.QuarterData)
-	//				quarterItem.Year = v
-	//				quarterItem.DataList = itemList
-	//				quarterDataList = append(quarterDataList, quarterItem)
-	//			}
-	//			item.DataList = quarterDataList
-	//		}
-	//	} else {
-	//		item.DataList = dataList
-	//	}
-	//	edbList = append(edbList, item)
-	//}
-	// 获取图表中的指标数据
-	edbList, err := data.GetChartEdbData(chartInfoId, chartType, calendar, startDate, endDate, mappingList)
+	barChartInfoDateList := make([]data_manage.BarChartInfoDateReq, 0)
+	barChartInfoSort := data_manage.BarChartInfoSortReq{}
+	// 柱方图的一些配置
+	if chartInfo != nil && chartInfo.ChartType == 7 {
+		if chartInfo.BarConfig == `` {
+			br.Msg = "柱方图未配置"
+			br.ErrMsg = "柱方图未配置"
+			return
+		}
+
+		var barConfig data_manage.BarChartInfoReq
+		err := json.Unmarshal([]byte(chartInfo.BarConfig), &barConfig)
+		if err != nil {
+			br.Msg = "柱方图配置异常"
+			br.ErrMsg = "柱方图配置异常"
+			return
+		}
+
+		barChartInfoDateList = barConfig.DateList
+		barChartInfoSort = barConfig.Sort
+
+		// 指标别名
+		for _, v := range mappingList {
+			for _, confEdb := range barConfig.EdbInfoIdList {
+				if v.EdbInfoId == confEdb.EdbInfoId {
+					v.EdbAliasName = confEdb.Name
+				}
+			}
+		}
+	}
+
+	edbList, xEdbIdValue, yDataList, err := data.GetChartEdbData(chartInfoId, chartType, calendar, startDate, endDate, mappingList, barChartInfoDateList, barChartInfoSort)
 	if err != nil {
 		br.Msg = "获取失败"
 		br.ErrMsg = "获取图表,指标信息失败,Err:" + err.Error()
@@ -308,6 +186,9 @@ func (this *ChartController) ChartInfoDetail() {
 
 	resp.ChartInfo = chartInfo
 	resp.EdbInfoList = edbList
+	resp.XEdbIdValue = xEdbIdValue
+	resp.YDataList = yDataList
+
 	if utils.Re == nil {
 		data, _ := json.Marshal(resp)
 		utils.Rc.Put(key, data, 10*time.Minute)

+ 24 - 13
models/chart.go

@@ -31,6 +31,7 @@ type ChartInfo struct {
 	SeasonStartDate string    `description:"季节性图开始日期"`
 	SeasonEndDate   string    `description:"季节性图开始日期"`
 	ChartImage      string    `description:"图表图片"`
+	BarConfig       string    `description:"柱方图的配置,json数据" json:"-"`
 }
 
 func GetChartInfoByUniqueCode(uniqueCode string) (item *ChartInfo, err error) {
@@ -41,19 +42,20 @@ func GetChartInfoByUniqueCode(uniqueCode string) (item *ChartInfo, err error) {
 }
 
 type ChartEdbInfoMapping struct {
-	EdbInfoId   int    `description:"指标id"`
-	SourceName  string `description:"来源名称"`
-	Source      int    `description:"来源id"`
-	EdbCode     string `description:"指标编码"`
-	EdbName     string `description:"指标名称"`
-	EdbNameEn   string `description:"英文指标名称"`
-	Frequency   string `description:"频率"`
-	FrequencyEn string `description:"英文频率"`
-	Unit        string `description:"单位"`
-	UnitEn      string `description:"英文单位"`
-	StartDate   string `description:"起始日期"`
-	EndDate     string `description:"终止日期"`
-	ModifyTime  string `description:"指标最后更新时间"`
+	EdbInfoId    int    `description:"指标id"`
+	SourceName   string `description:"来源名称"`
+	Source       int    `description:"来源id"`
+	EdbCode      string `description:"指标编码"`
+	EdbName      string `description:"指标名称"`
+	EdbAliasName string `description:"指标名称(别名)"`
+	EdbNameEn    string `description:"英文指标名称"`
+	Frequency    string `description:"频率"`
+	FrequencyEn  string `description:"英文频率"`
+	Unit         string `description:"单位"`
+	UnitEn       string `description:"英文单位"`
+	StartDate    string `description:"起始日期"`
+	EndDate      string `description:"终止日期"`
+	ModifyTime   string `description:"指标最后更新时间"`
 	//ChartEdbMappingId int     `description:"图表指标id"`
 	ChartInfoId int     `description:"图表id"`
 	MaxData     float64 `description:"上限"`
@@ -147,6 +149,15 @@ type QuarterData struct {
 type ChartInfoDetailResp struct {
 	ChartInfo   *ChartInfo
 	EdbInfoList []*ChartEdbInfoMapping
+	XEdbIdValue []int   `description:"柱方图的x轴数据,指标id"`
+	YDataList   []YData `description:"柱方图的y轴数据"`
+}
+
+// YData 柱方图的y轴数据
+type YData struct {
+	Date  string    `description:"数据日期"`
+	Color string    `description:"数据颜色"`
+	Value []float64 `description:"每个指标的值"`
 }
 
 //指标季度数据计算(公历转农历)

+ 27 - 0
models/data_manage/chart_info.go

@@ -108,3 +108,30 @@ func GetChartEdbMappingList(chartInfoId int) (list []*ChartEdbInfoMapping, err e
 	_, err = o.Raw(sql, chartInfoId).QueryRows(&list)
 	return
 }
+
+// BarChartInfoReq 柱方图预览请求数据
+type BarChartInfoReq struct {
+	EdbInfoIdList []BarChartInfoEdbItemReq `description:"指标信息"`
+	DateList      []BarChartInfoDateReq    `description:"日期配置"`
+	Sort          BarChartInfoSortReq      `description:"排序"`
+}
+
+// BarChartInfoEdbItemReq 柱方图预览请求数据(指标相关)
+type BarChartInfoEdbItemReq struct {
+	EdbInfoId int    `description:"指标ID"`
+	Name      string `description:"别名"`
+}
+
+// BarChartInfoDateReq 柱方图预览请求数据(日期相关)
+type BarChartInfoDateReq struct {
+	Type  int    `description:"配置类型"`
+	Date  string `description:"固定日期"`
+	Value int    `description:"N天的值"`
+	Color string `description:"颜色"`
+}
+
+// BarChartInfoSortReq 柱方图预览请求数据(排序相关)
+type BarChartInfoSortReq struct {
+	Sort      int `description:"排序类型,0:默认,1:升序,2:降序"`
+	DateIndex int `description:"日期数据的下标,从0开始"`
+}

+ 209 - 1
services/data/chart_info.go

@@ -190,8 +190,10 @@ func GetLeadUnitEn(unit string) (unitEn string) {
 }
 
 // GetChartEdbData 获取图表的指标数据
-func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*models.ChartEdbInfoMapping) (edbList []*models.ChartEdbInfoMapping, err error) {
+func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*models.ChartEdbInfoMapping, barChartInfoDateList []data_manage.BarChartInfoDateReq, barChartInfoSort data_manage.BarChartInfoSortReq) (edbList []*models.ChartEdbInfoMapping, xEdbIdValue []int, yDataList []models.YData, err error) {
 	edbList = make([]*models.ChartEdbInfoMapping, 0)
+	// 指标对应的所有数据
+	edbDataListMap := make(map[int][]*models.EdbDataList)
 
 	for _, v := range mappingList {
 		//fmt.Println("v:", v.EdbInfoId)
@@ -302,6 +304,8 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 		if err != nil {
 			return
 		}
+		edbDataListMap[v.EdbInfoId] = dataList
+
 		if diffSeconds != 0 && v.EdbInfoType == 0 {
 			dataListLen := len(dataList)
 			for i := 0; i < dataListLen; i++ {
@@ -415,11 +419,215 @@ func GetChartEdbData(chartInfoId, chartType int, calendar, startDate, endDate st
 				}
 				item.DataList = quarterDataList
 			}
+		} else if chartType == 7 { //柱方图
+			//item.DataList = dataList
 		} else {
 			item.DataList = dataList
 		}
 		edbList = append(edbList, item)
 	}
+
+	// 柱方图
+	if chartType == 7 {
+		xEdbIdValue, yDataList, err = BarChartData(mappingList, edbDataListMap, barChartInfoDateList, barChartInfoSort)
+	} else {
+		xEdbIdValue = make([]int, 0)
+		yDataList = make([]models.YData, 0)
+	}
+
+	return
+}
+
+// BarChartData 柱方图的数据处理
+func BarChartData(mappingList []*models.ChartEdbInfoMapping, edbDataListMap map[int][]*models.EdbDataList, barChartInfoDateList []data_manage.BarChartInfoDateReq, barChartInfoSort data_manage.BarChartInfoSortReq) (edbIdList []int, yDataList []models.YData, err error) {
+	// 指标数据数组(10086:{"2022-12-02":100.01,"2022-12-01":102.3})
+	edbDataMap := make(map[int]map[string]float64)
+	for edbInfoId, edbDataList := range edbDataListMap {
+		edbDateData := make(map[string]float64)
+		for _, edbData := range edbDataList {
+			edbDateData[edbData.DataTime] = edbData.Value
+		}
+		edbDataMap[edbInfoId] = edbDateData
+	}
+
+	// edbIdList 指标展示顺序;x轴的指标顺序
+	edbIdList = make([]int, 0)
+	//Sort int    `description:"排序类型,0:默认,1:升序,2:降序"`
+	dateData := make(map[int]float64)
+	if barChartInfoSort.Sort == 0 {
+		for _, v := range mappingList {
+			edbIdList = append(edbIdList, v.EdbInfoId)
+		}
+	} else {
+		lenBarChartInfoDateList := len(barChartInfoDateList)
+		if barChartInfoSort.DateIndex >= lenBarChartInfoDateList {
+			err = errors.New("排序日期异常")
+			return
+		}
+
+		notDataEdbIdList := make([]int, 0) //没有数据的指标id
+		// 日期配置
+		barChartInfoDate := barChartInfoDateList[barChartInfoSort.DateIndex]
+		for edbInfoId, dataList := range edbDataListMap {
+			findDate := barChartInfoDate.Date
+			switch barChartInfoDate.Type {
+			case 1: //最新值
+				findDate = dataList[len(dataList)-1].DataTime
+			case 2: //近期几天
+				findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				findDateTime = findDateTime.AddDate(0, 0, -barChartInfoDate.Value)
+
+				lenData := len(dataList) - 1
+
+				for i := lenData; i >= 0; i-- {
+					currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
+					if tmpErr != nil {
+						err = tmpErr
+						return
+					}
+					if utils.GetTimeSubDay(currDateTime, findDateTime) >= 5 {
+						findDate = dataList[i].DataTime
+						break
+					}
+				}
+			case 3: // 固定日期
+				//最早的日期
+				minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				//寻找固定日期的数据
+				findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime.AddDate(0, 0, -1) {
+					tmpDate := tmpDateTime.Format(utils.FormatDate)
+					if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
+						findDate = tmpDate
+						break
+					}
+				}
+			default:
+				err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
+				return
+			}
+			if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
+				dateData[edbInfoId] = tmpValue
+			} else {
+				// 没有数据的指标id
+				notDataEdbIdList = append(notDataEdbIdList, edbInfoId)
+			}
+		}
+
+		//Sort int    `description:"排序类型,0:默认,1:升序,2:降序"`
+		// 排序
+		dateDataSort := utils.NewMapSorter(dateData)
+		sort.Sort(dateDataSort)
+		if barChartInfoSort.Sort == 1 {
+			// 先将没有数据的指标id放在最前面
+			if len(notDataEdbIdList) > 0 {
+				edbIdList = append(edbIdList, notDataEdbIdList...)
+			}
+			for _, v := range dateDataSort {
+				edbIdList = append(edbIdList, v.Key)
+			}
+		} else {
+			for i := len(dateDataSort) - 1; i >= 0; i-- {
+				edbIdList = append(edbIdList, dateDataSort[i].Key)
+			}
+			// 再将没有数据的指标id放在最后面
+			if len(notDataEdbIdList) > 0 {
+				edbIdList = append(edbIdList, notDataEdbIdList...)
+			}
+		}
+	}
+
+	yDataList = make([]models.YData, 0) //y轴的数据列表
+
+	for _, barChartInfoDate := range barChartInfoDateList {
+		var maxDate time.Time
+
+		findDataList := make([]float64, 0) // 当前日期的数据值
+		for _, edbInfoId := range edbIdList {
+			findDate := barChartInfoDate.Date     //需要的日期值
+			dataList := edbDataListMap[edbInfoId] //指标的所有数据值
+			switch barChartInfoDate.Type {
+			case 1: //最新值
+				dataList := edbDataListMap[edbInfoId]
+				findDate = dataList[len(dataList)-1].DataTime
+			case 2: //近期几天
+				findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[len(dataList)-1].DataTime, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				findDateTime = findDateTime.AddDate(0, 0, -barChartInfoDate.Value)
+
+				lenData := len(dataList) - 1
+				for i := lenData; i >= 0; i-- {
+					currDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[i].DataTime, time.Local)
+					if tmpErr != nil {
+						err = tmpErr
+						return
+					}
+					if utils.GetTimeSubDay(currDateTime, findDateTime) >= 5 {
+						findDate = dataList[i].DataTime
+						break
+					}
+				}
+			case 3: // 固定日期
+				//最早的日期
+				minDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				//寻找固定日期的数据
+				findDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
+				if tmpErr != nil {
+					err = tmpErr
+					return
+				}
+				for tmpDateTime := findDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime.AddDate(0, 0, -1) {
+					tmpDate := tmpDateTime.Format(utils.FormatDate)
+					if _, ok := edbDataMap[edbInfoId][tmpDate]; ok { //如果能找到数据,那么就返回
+						findDate = tmpDate
+						break
+					}
+				}
+			default:
+				err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
+				return
+			}
+			findDateTime, _ := time.ParseInLocation(utils.FormatDate, findDate, time.Local)
+			if maxDate.IsZero() {
+				maxDate = findDateTime
+			} else {
+				if findDateTime.After(maxDate) {
+					maxDate = findDateTime
+				}
+			}
+			if tmpValue, ok := edbDataMap[edbInfoId][findDate]; ok {
+				findDataList = append(findDataList, tmpValue)
+			} else {
+				findDataList = append(findDataList, 0)
+			}
+		}
+
+		yDataList = append(yDataList, models.YData{
+			Date:  maxDate.Format(utils.FormatDate),
+			Value: findDataList,
+			Color: barChartInfoDate.Color,
+		})
+	}
+
 	return
 }
 

+ 52 - 0
utils/common.go

@@ -640,3 +640,55 @@ func RevSlice(slice []int) []int {
 	}
 	return slice
 }
+
+// GetTimeSubDay 计算两个时间的自然日期差
+func GetTimeSubDay(t1, t2 time.Time) int {
+	var day int
+	swap := false
+	if t1.Unix() > t2.Unix() {
+		t1, t2 = t2, t1
+		swap = true
+	}
+
+	t1_ := t1.Add(time.Duration(t2.Sub(t1).Milliseconds()%86400000) * time.Millisecond)
+	day = int(t2.Sub(t1).Hours() / 24)
+	// 计算在t1+两个时间的余数之后天数是否有变化
+	if t1_.Day() != t1.Day() {
+		day += 1
+	}
+
+	if swap {
+		day = -day
+	}
+
+	return day
+}
+
+// MapSorter 对于map 排序
+type MapSorter []Item
+
+type Item struct {
+	Key int
+	Val float64
+}
+
+func NewMapSorter(m map[int]float64) MapSorter {
+	ms := make(MapSorter, 0, len(m))
+	for k, v := range m {
+		ms = append(ms, Item{k, v})
+	}
+	return ms
+}
+
+func (ms MapSorter) Len() int {
+	return len(ms)
+}
+
+func (ms MapSorter) Less(i, j int) bool {
+	return ms[i].Val > ms[j].Val // 按值排序
+	//return ms[i].Key < ms[j].Key // 按键排序
+}
+
+func (ms MapSorter) Swap(i, j int) {
+	ms[i], ms[j] = ms[j], ms[i]
+}