一.统计数据接口

 

 controller层

    /**
     * 根据ProductSpec和date查询
     * 查询条件: 地区,ProductSpec,date
     * @param renduiPriceDailyDTO
     * @return
     */
    @PostMapping(value = "/daily/getByProductSpecAndDate")
    public Result<?> getByProductSpecAndDate(@RequestBody RenduiPriceDailyDTO renduiPriceDailyDTO){
        if(StringUtils.isBlank(renduiPriceDailyDTO.getSiteId())){
            return Result.error("地区不能为空!");
        }
        if(StringUtils.isBlank(renduiPriceDailyDTO.getProductSpec())){
            return Result.error("productSpec不能为空!");
        }
        if(renduiPriceDailyDTO.getDate() == null){
            return Result.error("日期不能为空,日期格式为:yyyy-MM-dd!");
        }
        return renduiPriceDailyService.getByProductSpecAndDate(renduiPriceDailyDTO);
    }

在校验一个String类型的变量是否为空时,可以使用StringUtils.isBlank方法,它可以校验三种情况:是否为null、是否为""、是否为空字符串(引号中间有空格)" "、制表符、换行符、换页符和回车。

StringUtils.isEmpty("yyy") = false
StringUtils.isEmpty("") = true
StringUtils.isEmpty("   ") = false
 
StringUtils.isBlank("yyy") = false
StringUtils.isBlank("") = true
StringUtils.isBlank("   ") = true

service层

    /**
     * 根据ProductSpec和date查询
     * 查询条件: 地区,ProductSpec,date
     * @param renduiPriceDailyDTO
     * @return
     */
    Result<?> getByProductSpecAndDate(RenduiPriceDailyDTO renduiPriceDailyDTO);
}

serviceImpl层

 @Override
    public Result<?> getByProductSpecAndDate(RenduiPriceDailyDTO renduiPriceDailyDTO) {
        //1.获取该日期的每日统计结果
        long date = renduiPriceDailyDTO.getDate().atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli();
        Document daily = renduiPriceDailyManager.queryByProductSpec(renduiPriceDailyDTO.getSiteId(), renduiPriceDailyDTO.getProductSpec(), date);
        if(daily == null){
            return Result.error("当前没有报价,暂无统计");
        }
        //今开
        if (daily.get("openingPrice") != null) {
            daily.put("openingPrice",daily.get("openingPrice"));
            daily.put("openingPriceTax",daily.get("openingPriceTax"));
        }else {
            daily.put("openingPrice",0);
            daily.put("openingPriceTax",0);
        }
        //2.查询该日期前一天的每日统计结果
        long yesterday = renduiPriceDailyDTO.getDate().minusDays(1).atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli();
        Document yesterdayDaily = renduiPriceDailyManager.queryByProductSpec(renduiPriceDailyDTO.getSiteId(), renduiPriceDailyDTO.getProductSpec(), yesterday);
        if(yesterdayDaily == null){
            daily.put("closePrice",0);
            daily.put("closePriceTax",0);
            daily.put("riseAndFall",0);
            daily.put("riseAndFallTax",0);
            daily.put("riseRange",0.00);
            daily.put("riseRangeTax",0.00);
            return Result.OK(daily);
        }
        //3.计算
        //涨跌 当前价 - 昨天均价
        Float riseAndFall = Float.valueOf(daily.get("lastprice").toString()) - Float.valueOf(yesterdayDaily.get("price").toString());
        Float riseAndFallTax = Float.valueOf(daily.get("lastpriceTax").toString()) - Float.valueOf(yesterdayDaily.get("priceTax").toString());
        //涨幅 涨跌 / 昨天均价
        Float riseRange = Double.valueOf(AccurateCalculation.div(riseAndFall,Double.valueOf(yesterdayDaily.get("price").toString()),2)).floatValue() * 100;
        Float riseRangeTax = Double.valueOf(AccurateCalculation.div(riseAndFallTax,Double.valueOf(yesterdayDaily.get("priceTax").toString()),2)).floatValue() * 100;
        daily.put("riseAndFall",riseAndFall);
        daily.put("riseAndFallTax",riseAndFallTax);
        daily.put("riseRange",riseRange);
        daily.put("riseRangeTax",riseRangeTax);
        //昨收
        daily.put("closePrice",yesterdayDaily.get("closePrice"));
        daily.put("closePriceTax",yesterdayDaily.get("closePriceTax"));
        return Result.OK(daily);
    }

 atStartOfDay()

long date = renduiPriceDailyDTO.getDate().atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli();

java.time.LocalDate.atStartOfDay()方法将此日期与午夜时间组合在一起,以便在此日期开始时创建LocalDateTime。 

声明

public LocalDateTime atStartOfDay() 

返回值

此日期开始时的午夜的本地日期时间,不为null

示例

package com.yiibai;

import java.time.LocalDate;
import java.time.LocalDateTime;

public class LocalDateDemo {
   public static void main(String[] args) {

      LocalDate date = LocalDate.parse("2017-02-03");
      System.out.println(date);  
      LocalDateTime date1 = date.atStartOfDay();
      System.out.println(date1);  
   }
}


结果

2017-02-03
2017-02-03T00:00

toInstant()

Java8出现的 Instant 类似于 Date ,LocalDateTime 类似于 Calendar,DateTimeFormatter 类似于 SimpleDateFormat,由于 SimpleDateFormat 是线程不安全的(一般使用 SimpleDateFormat 的时会把它定义成静态变量,从而避免频繁地创建它的对象实例,但 SimpleDateFormat 内部使用 Calendar 去完成日期的转换,多线程情况下可能会出现线程不安全情况),推荐使用 Instant代替 Date,LocalDateTime 代替 Calendar,DateTimeFormatter 代替 SimpleDateFormat

localDateTime 

// 输出当前时间:2019-04-24T19:41:21.858
LocalDateTime now = LocalDateTime.now();
System.out.println(now);

// 格式化时间,输出:2019年04月24日 19:49:25
LocalDateTime time = LocalDateTime.now();
String timeStr = time.format(DateTimeFormatter.ofPattern("yyyy年年MM月dd日 HH:mm:ss"));
System.out.println(timeStr);

// 当前时间增加20分钟
LocalDateTime afterPlusTime = LocalDateTime.now().plus(20, ChronoUnit.MINUTES);
System.out.println(afterPlusTime);

// 创建开始和结束时间,并计算中间差值
LocalDateTime start = LocalDateTime.of(1992, 8, 13, 0, 0, 0);
LocalDateTime end = LocalDateTime.of(2019, 4, 25, 0, 0);
long diff = LocalDateTimeUtils.betweenTwoTime(start, end, ChronoUnit.YEARS);
System.out.println(diff+"年"); // 26
        
boolean b = start.isAfter(end);
System.out.println(b); // false

//获取秒数 (东8区,也就是北京时间)
Long second = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
//获取毫秒数(东8区,也就是北京时间)
Long milliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();

instant

Instant now = Instant.now(); // 2019-04-24T12:30:34.349Z
long currentSecond = now.getEpochSecond(); // 秒数:1556109034
long currentMilli = now.toEpochMilli(); // 毫秒数:1556109034349

Instant afterPlusSecondInstant = now.plusSeconds(1000); // 秒数增加1000
boolean b = now.isBefore(afterPlusSecondInstant); // 比较

DateTimeFormatter

// 输出:2019年04月24日 20:53:23
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
LocalDateTime time = LocalDateTime.now();
String formatResult = time.format(df);

// 输出:20190424
LocalDateTime time = LocalDateTime.now();
String formatResult = time.format(DateTimeFormatter.BASIC_ISO_DATE);
ISO_DATE            --> 2019-04-24
ISO_LOCAL_DATE      --> 2019-04-24
ISO_LOCAL_TIME      --> 20:59:48.42
ISO_TIME            --> 21:00:38.256
ISO_LOCAL_DATE_TIME --> 2019-04-24T21:01:11.083
.......

格式转化

Instant instant  = Instant.now();
Date date = Date.from(instant); // Instant转换为Date
Instant instant2 = date.toInstant(); // Date转换为Instant

// Date 与 LocalDateTime 的转换是通过 Instant 中间的转换来进行的
Date date = new Date();
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(),ZoneId.systemDefault()); // Date转换为LocalDateTime

LocalDateTime localDateTime = LocalDateTime.now();
Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
Date date = Date.from(instant); // LocalDateTime转换为Date

二.根据维度查询 区间均价加折线图 当天不显示区间均价

 

 controller层

    /**
     * 查询分钟维度价格统计(曲线图的数据接口)
     * @param
     * @return
     */
    @AutoLog(value = "/prices/statistics")
    @ApiOperation(value = "/prices/statistics", notes = "/prices/statistics")
    @GetMapping(value = "/prices/statistics")
    public Result<?>  statisticsPrice(@RequestParam(value = "productSpec") String productSpec, @RequestParam(value = "siteId")String siteId, @RequestParam(value = "from")String from, @RequestParam(value = "to")String to) {
        boolean fromBeforeTo = DateCommonUtil.getDateFromStr(from).before(DateCommonUtil.getDateFromStr(to));
        if(!fromBeforeTo){
          return Result.error("开始时间不能大于结束时间");
        }
        return service.statisticsPrice(productSpec, siteId, from, to);
    }

service层

    Result<?> statisticsPrice(String productSpec, String siteId, String from, String to);

serviceImpl层

    @Override
    public Result<?> statisticsPrice(String productSpec, String siteId, String from, String to) {
        long dateDiff = DateUtil.betweenDay(DateCommonUtil.getDateFromStr(from), DateCommonUtil.getDateFromStr(to), false);
        boolean isSameDay = DateUtil.isSameDay(DateCommonUtil.getDateFromStr(from),  DateCommonUtil.getDateFromStr(to));
        if (dateDiff <= 0 && isSameDay) {
            return Result.OK(statisticsMinutely2(productSpec, siteId, from, to));
        } else {
            return Result.OK(statisticsDaily(productSpec, siteId, from, to, dateDiff));
        }
    }
private Map<String,Object> statisticsMinutely2(String productSpec, String siteId, String from, String to) {
        Map<String,Object> map = new HashMap<>();
        map.put("rangeAvgPrice",0);
        long FIVE_MINUTES = 5 * 60000;
        long fromTime = DateCommonUtil.getTimeFromStr(from);
        long toTime = DateCommonUtil.getTimeFromStr(to);
        List<Document> minutely = renduiPriceMinutelyManager.queryByProductSpec(productSpec, siteId, fromTime, toTime);
        List<PriceStatisticsVO> results = new ArrayList<>();
        long minuteDiff = DateUtil.between(DateCommonUtil.getDateFromStr(from), DateCommonUtil.getDateFromStr(to), DateUnit.MINUTE);
        int window = (int) minuteDiff / 5;
        // 如果为空
        if (minutely.size() == 0) {
            PriceStatisticsVO lastPrice = getLastPrice(productSpec, siteId, fromTime);
            long t = fromTime;
            while (t <= toTime) {
                PriceStatisticsVO p =  new PriceStatisticsVO();
                BeanUtil.copyProperties(lastPrice, p);
                p.setTimestamp(t);
                results.add(lastPrice);
                t += 5 * 60000;
            }
            map.put("list",results);
            return map;
        }

        PriceStatisticsVO firstPrice = new PriceStatisticsVO();
        BeanUtil.copyProperties(minutely.get(0), firstPrice);
        // 补充左边的数据
        long fistTime = firstPrice.getTimestamp();
        PriceStatisticsVO formerPrice = null;
        if (fistTime > fromTime) {
            PriceStatisticsVO latestPrice = getLastPrice(productSpec, siteId, fromTime);
            long t = fromTime;
            int i = 0;
            while (t < fistTime) {
                PriceStatisticsVO p =  new PriceStatisticsVO();
                BeanUtil.copyProperties(latestPrice, p);
                p.setTimestamp(t);

                results.add(p);
                formerPrice = p;
                i ++;
                t += FIVE_MINUTES;
            }
        }

        // 补充中间数据

        for (int i = 0; i < minutely.size(); i ++) {
            Document m = minutely.get(i);
            PriceStatisticsVO price = new PriceStatisticsVO();
            BeanUtil.copyProperties(m, price);
            // 补充中间数据
            if (formerPrice != null && price.getTimestamp() - formerPrice.getTimestamp() > FIVE_MINUTES) {
                long t = formerPrice.getTimestamp() + FIVE_MINUTES;
                while ( t < price.getTimestamp()) {
                    PriceStatisticsVO p = new PriceStatisticsVO();
                    BeanUtil.copyProperties(formerPrice, p);
                    p.setTimestamp(t);
                    results.add(p);
                    t += FIVE_MINUTES;
                }
            }
            results.add(price);
            formerPrice = price;
        }

        if (formerPrice != null && formerPrice.getTimestamp() < toTime) {
            long t = formerPrice.getTimestamp() + FIVE_MINUTES;
            while ( t < toTime) {
                PriceStatisticsVO p = new PriceStatisticsVO();
                BeanUtil.copyProperties(formerPrice, p);
                p.setTimestamp(t);
                results.add(p);
                t += FIVE_MINUTES;
            }
        }
        map.put("list",results);
        return map;
    }

DateUtil.betweenDay()

需求
求出 当前天, 与指定日期之间相差的天数, 指定日期一定在 当前天之前即 当前天为 01-23 , 指定日期应该为 01-22
解决方案
使用hutools工具包中提供的计算两个日期之间相差天数的方法
betweenDay()
三个参数: betweenDay(Date,Date,Boolean)

 // 使用方式
 // cn.hutool.core.date.DateUtil.betweenDay(currentDate, targetTime, true);
 // 源码
	/**
	 * 判断两个日期相差的天数<br>
	 *
	 * <pre>
	 * 有时候我们计算相差天数的时候需要忽略时分秒。
	 * 比如:2016-02-01 23:59:59和2016-02-02 00:00:00相差一秒
	 * 如果isReset为<code>false</code>相差天数为0。
	 * 如果isReset为<code>true</code>相差天数将被计算为1
	 * </pre>
	 *
	 * @param beginDate 起始日期
	 * @param endDate   结束日期
	 * @param isReset   是否重置时间为起始时间
	 * @return 日期差
	 * @since 3.0.1
	 */
	public static long betweenDay(Date beginDate, Date endDate, boolean isReset) {
		if (isReset) {
			beginDate = beginOfDay(beginDate);
			endDate = beginOfDay(endDate);
		}
		return between(beginDate, endDate, DateUnit.DAY);
	}
private Map<String,Object> statisticsDaily(String productSpec, String siteId, String from, String to, long dateDiff) {
        List<PriceStatisticsVO> result = new ArrayList<>();
        //按天统计
        long fromTime = 0;
        List<Float> avgList = new ArrayList<>();
        Map<String,Object> map = new HashMap<>();
        for (int i = 0; i < dateDiff + 1; i++) {
            if (i == 0) {
                fromTime = DateCommonUtil.getTimeFromStr(from);
            }
            long  toTime = DateCommonUtil.dayAfterInterval(DateCommonUtil.dateFromTimestamp(fromTime), 1).getTime();
            List<Document> daily = renduiPriceDailyManager.queryByProductSpec(productSpec, siteId, fromTime, toTime);
            Float avgPrice = daily.stream().map(document -> document.get("price") == null ? 0 : Float.parseFloat(document.get("price").toString()))
                    .collect(Collectors.averagingDouble(price -> price)).floatValue();
            //当avgPrice > 0
            if(avgPrice.compareTo(new Float(0.00f)) == 1 ){
                avgList.add(avgPrice);
            }
            PriceStatisticsVO statisticsVO = new PriceStatisticsVO();
            statisticsVO.setProductSpec(productSpec);
            statisticsVO.setPrice(Float.valueOf("0.00"));
            statisticsVO.setPriceTax(Float.valueOf("0.00"));
            statisticsVO.setSatisticsTime(DateCommonUtil.strFromTimestamp(fromTime));
            if (CollectionUtil.isEmpty(daily)) {
                setDailyEmptyVal(productSpec, siteId, fromTime, i, statisticsVO);
            } else {
                BeanUtil.copyProperties(daily.get(daily.size() - 1), statisticsVO);
            }
            fromTime = toTime;
            result.add(statisticsVO);
        }

        for (int i = 0; i < result.size(); i++) {
            //将空值替换为上个周期的数据 ,因为前面保证了第一条数据一定有值所以不会出现数组越界问题
            if (result.get(i).getProductSpec() != null && result.get(i).getProductSpec().equals(EMPTY_MARK)) {
                PriceStatisticsVO statisticsVO = getNotEmptyOne(i - 1, result);
                String statisticTime = result.get(i).getSatisticsTime();
                BeanUtil.copyProperties(statisticsVO, result.get(i));
                result.get(i).setSatisticsTime(statisticTime);
            }
        }
        Float rangeAvgPrice = avgList.stream().collect(Collectors.averagingDouble(avg -> avg)).floatValue();
        map.put("rangeAvgPrice",rangeAvgPrice);
        map.put("list",result);
        return map;
    }


三.大盘价曲线图

controller层

    /**
     * 大盘价曲线图
     * 根据范围查询
     * 查询条件  productSpec,siteId,from,to
     * @param bigDishPriceDTO
     * @return
     */
    @PostMapping(value = "/bigDishPrice/rangeQueryBigDishPrice")
    public Result<?> rangeQueryBigDishPrice(@RequestBody BigDishPriceDTO bigDishPriceDTO){
        if(StringUtils.isBlank(bigDishPriceDTO.getProductSpec())){
            return Result.error("查询条件不能为空!");
        }
        if(StringUtils.isBlank(bigDishPriceDTO.getSiteId())){
            return Result.error("地区不能为空!");
        }
        if(bigDishPriceDTO.getTo().compareTo(LocalDateTime.now().plusMinutes(1)) == 1){
            return Result.error("结束时间需小于当前时间!");
        }
        if(bigDishPriceDTO.getFrom().compareTo(bigDishPriceDTO.getTo()) >= 0){
            return Result.error("开始时间需小于结束时间!");
        }
        return bigDishPriceService.rangeQueryBigDishPrice(bigDishPriceDTO);
    }

service层

    /**
     * 大盘价曲线图
     * 根据范围查询
     * 查询条件  productSpec,siteId,from,to
     * @param bigDishPriceDTO
     * @return
     */
    Result<?> rangeQueryBigDishPrice(BigDishPriceDTO bigDishPriceDTO);

serviceImpl层

  @Override
    public Result<?> rangeQueryBigDishPrice(BigDishPriceDTO bigDishPriceDTO) {
        Duration duration = Duration.between(bigDishPriceDTO.getFrom(),bigDishPriceDTO.getTo());
        //当前查询范围大于1天
        if(duration.toDays() > 1){
            return Result.OK(replenishDayData(bigDishPriceDTO.getProductSpec(),bigDishPriceDTO.getSiteId(),bigDishPriceDTO.getFrom(),bigDishPriceDTO.getTo(),duration.toDays()));
        }
        //1.查询范围内大盘价
        long fromTime = bigDishPriceDTO.getFrom().toInstant(ZoneOffset.of("+8")).toEpochMilli();
        long toTime = bigDishPriceDTO.getTo().toInstant(ZoneOffset.of("+8")).toEpochMilli();
        List<Document> priceList = renduiPriceMinutelyManager.queryByProductSpec(bigDishPriceDTO.getProductSpec(), bigDishPriceDTO.getSiteId(), fromTime, toTime);
        List<PriceStatisticsVO> result = new ArrayList<>();
        // 如果为空取之前的最后一条大盘价
        if (priceList.size() == 0 || priceList == null) {
            Document doc = renduiPriceMinutelyManager.queryLastDataBy(bigDishPriceDTO.getProductSpec(), bigDishPriceDTO.getSiteId(), fromTime);
            if(doc == null){
                return Result.OK();
            }
            doc.put("price",Float.parseFloat(doc.get("price").toString()));
            doc.put("priceTax",Float.parseFloat(doc.get("priceTax").toString()));
            PriceStatisticsVO lastPrice = JSONObject.parseObject(JSON.toJSONString(doc), PriceStatisticsVO.class);
            long from = fromTime;
            while (from <= toTime) {
                PriceStatisticsVO p =  new PriceStatisticsVO();
                BeanUtil.copyProperties(lastPrice, p);
                p.setTimestamp(from);
                p.setSatisticsTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(from),ZoneOffset.of("+8")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                result.add(p);
                from = from + 5 * 60 * 1000;
            }
            return Result.OK(result);
        }
        //2.补充左边的数据
        Document firstDoc = priceList.get(0);
        firstDoc.put("price",Float.parseFloat(firstDoc.get("price").toString()));
        firstDoc.put("priceTax",Float.parseFloat(firstDoc.get("priceTax").toString()));
        PriceStatisticsVO firstPrice = JSONObject.parseObject(JSON.toJSONString(firstDoc), PriceStatisticsVO.class);
        PriceStatisticsVO flagPrice = null;
        if(firstPrice.getTimestamp() > fromTime){
            Document doc = renduiPriceMinutelyManager.queryLastDataBy(bigDishPriceDTO.getProductSpec(), bigDishPriceDTO.getSiteId(), fromTime);
            //如果之前没有数据则
            PriceStatisticsVO lastPrice;
            if(doc == null){
                lastPrice = firstPrice;
            }else {
                doc.put("price",Float.parseFloat(doc.get("price").toString()));
                doc.put("priceTax",Float.parseFloat(doc.get("priceTax").toString()));
                lastPrice = JSONObject.parseObject(JSON.toJSONString(doc), PriceStatisticsVO.class);
            }
            long from = fromTime;
            while (from < firstPrice.getTimestamp()) {
                PriceStatisticsVO p =  new PriceStatisticsVO();
                BeanUtil.copyProperties(lastPrice, p);
                p.setTimestamp(from);
                p.setSatisticsTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(from),ZoneOffset.of("+8")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                result.add(p);
                from = from + 5 * 60 * 1000;
                flagPrice = p;
            }
        }
        //3.补充中间的数据
        for (Document document : priceList) {
            document.put("price",Float.parseFloat(document.get("price").toString()));
            document.put("priceTax",Float.parseFloat(document.get("priceTax").toString()));
            PriceStatisticsVO price = JSONObject.parseObject(JSON.toJSONString(document), PriceStatisticsVO.class);
            if(flagPrice != null && price.getTimestamp() - flagPrice.getTimestamp() >= 5 * 60 * 1000){
                //+ 5 分钟
                long from = flagPrice.getTimestamp() + 5 * 60 * 1000;
                while (from < price.getTimestamp()){
                    PriceStatisticsVO p =  new PriceStatisticsVO();
                    BeanUtil.copyProperties(price, p);
                    p.setTimestamp(from);
                    p.setSatisticsTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(from),ZoneOffset.of("+8")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                    result.add(p);
                    from = from + 5 * 60 * 1000;
                }
            }
            price.setSatisticsTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(price.getTimestamp()),ZoneOffset.of("+8")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            result.add(price);
            flagPrice = price;
        }
        //4.补充右边的数据
        if(flagPrice != null && flagPrice.getTimestamp() < toTime){
            //+ 5 分钟
            long from = flagPrice.getTimestamp() + 5 * 60 * 1000;
            while (from < toTime){
                PriceStatisticsVO p =  new PriceStatisticsVO();
                BeanUtil.copyProperties(flagPrice, p);
                p.setTimestamp(from);
                p.setSatisticsTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(from),ZoneOffset.of("+8")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                result.add(p);
                from = from + 5 * 60 * 1000;
            }
        }
        return Result.OK(result);
    }

四.计算基差 根据范围

controller层

    /**
     * 根据范围计算基差
     * 计算规则:市场价 - 大盘价
     * @param bigDishPriceDTO
     * @return
     */
    @PostMapping(value = "/bigDishPrice/rangeQueryBasicDiff")
    public Result<?> rangeQueryBasicDiff(@RequestBody BigDishPriceDTO bigDishPriceDTO){
        if(StringUtils.isBlank(bigDishPriceDTO.getProductSpec()) || StringUtils.isBlank(bigDishPriceDTO.getBigDishProductSpec())){
            return Result.error("查询条件不能为空!");
        }
        if(StringUtils.isBlank(bigDishPriceDTO.getSiteId()) || StringUtils.isBlank(bigDishPriceDTO.getBigDishSiteId())){
            return Result.error("地区不能为空!");
        }
        if(bigDishPriceDTO.getTo().compareTo(LocalDateTime.now().plusMinutes(1)) == 1){
            return Result.error("结束时间需小于当前时间!");
        }
        if(bigDishPriceDTO.getFrom().compareTo(bigDishPriceDTO.getTo()) >= 0){
            return Result.error("开始时间需小于结束时间!");
        }
        return bigDishPriceService.rangeQueryBasicDiff(bigDishPriceDTO);
    }

service层

    /**
     * 根据范围查询基差
     * 计算规则:市场价 - 大盘价
     * @param bigDishPriceDTO
     * @return
     */
    Result<?> rangeQueryBasicDiff(BigDishPriceDTO bigDishPriceDTO);

serviceImpl层

  @Override
    public Result<?> rangeQueryBasicDiff(BigDishPriceDTO bigDishPriceDTO) {
        //计算公式 市场价 - 大盘价
        //1.存储结果
        List<PriceStatisticsVO> result = new ArrayList<>();
        Duration duration = Duration.between(bigDishPriceDTO.getFrom(),bigDishPriceDTO.getTo());
        //当前查询范围大于1天
        if(duration.toDays() > 1){
            //2.根据时间补齐市场价的数据
            List<PriceStatisticsVO> priceList = replenishDayData(bigDishPriceDTO.getProductSpec(), bigDishPriceDTO.getSiteId(), bigDishPriceDTO.getFrom(), bigDishPriceDTO.getTo(),duration.toDays());
            //3.根据时间补齐大盘价的数据
            List<PriceStatisticsVO> bigDishPriceList = replenishDayData(bigDishPriceDTO.getBigDishProductSpec(), bigDishPriceDTO.getBigDishSiteId(), bigDishPriceDTO.getFrom(), bigDishPriceDTO.getTo(),duration.toDays());
            Map<String, Float> bigDishPriceMap = bigDishPriceList.stream().collect(Collectors.toMap(priceStatisticsVO -> priceStatisticsVO.getSatisticsTime(), o -> o.getPrice()));
            //4.计算存储结果
            priceList.forEach(p -> {
                PriceStatisticsVO priceStatisticsVO = new PriceStatisticsVO();
                //基差 = 市场价 - 大盘价
                Float basicDiff = p.getPrice() - bigDishPriceMap.get(p.getSatisticsTime());
                basicDiff = new BigDecimal(basicDiff).setScale(2,RoundingMode.HALF_UP).floatValue();
                priceStatisticsVO.setPrice(basicDiff);
                priceStatisticsVO.setSatisticsTime(p.getSatisticsTime());
                priceStatisticsVO.setTimestamp(p.getTimestamp());
                result.add(priceStatisticsVO);
            });
            return Result.OK(result);
        }
        //2.根据时间补齐市场价的数据
        List<PriceStatisticsVO> priceList = replenishData(bigDishPriceDTO.getProductSpec(), bigDishPriceDTO.getSiteId(), bigDishPriceDTO.getFrom(), bigDishPriceDTO.getTo());
        if(priceList == null || priceList.size() == 0){
            return Result.OK();
        }
        //3.根据时间补齐大盘价的数据
        List<PriceStatisticsVO> bigDishPriceList = replenishData(bigDishPriceDTO.getBigDishProductSpec(), bigDishPriceDTO.getBigDishSiteId(), bigDishPriceDTO.getFrom(), bigDishPriceDTO.getTo());
        if(bigDishPriceList == null || bigDishPriceList.size() == 0){
            return Result.OK();
        }
        Map<String, Float> bigDishPriceMap = bigDishPriceList.stream().collect(Collectors.toMap(priceStatisticsVO -> priceStatisticsVO.getSatisticsTime(), o -> o.getPrice()));
        //4.计算存储结果
        priceList.forEach(p -> {
            PriceStatisticsVO priceStatisticsVO = new PriceStatisticsVO();
            //基差 = 市场价 - 大盘价
            Float basicDiff = p.getPrice() - bigDishPriceMap.get(p.getSatisticsTime());
            basicDiff = new BigDecimal(basicDiff).setScale(2,RoundingMode.HALF_UP).floatValue();
            priceStatisticsVO.setPrice(basicDiff);
            priceStatisticsVO.setSatisticsTime(p.getSatisticsTime());
            priceStatisticsVO.setTimestamp(p.getTimestamp());
            result.add(priceStatisticsVO);
        });
        return Result.OK(result);
    }

更多推荐