• 2022/7/27 算力-价格明细


    一.统计数据接口

     

     controller层

    1. /**
    2. * 根据ProductSpec和date查询
    3. * 查询条件: 地区,ProductSpec,date
    4. * @param renduiPriceDailyDTO
    5. * @return
    6. */
    7. @PostMapping(value = "/daily/getByProductSpecAndDate")
    8. public Result getByProductSpecAndDate(@RequestBody RenduiPriceDailyDTO renduiPriceDailyDTO){
    9. if(StringUtils.isBlank(renduiPriceDailyDTO.getSiteId())){
    10. return Result.error("地区不能为空!");
    11. }
    12. if(StringUtils.isBlank(renduiPriceDailyDTO.getProductSpec())){
    13. return Result.error("productSpec不能为空!");
    14. }
    15. if(renduiPriceDailyDTO.getDate() == null){
    16. return Result.error("日期不能为空,日期格式为:yyyy-MM-dd!");
    17. }
    18. return renduiPriceDailyService.getByProductSpecAndDate(renduiPriceDailyDTO);
    19. }

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

    1. StringUtils.isEmpty("yyy") = false
    2. StringUtils.isEmpty("") = true
    3. StringUtils.isEmpty(" ") = false
    4. StringUtils.isBlank("yyy") = false
    5. StringUtils.isBlank("") = true
    6. StringUtils.isBlank(" ") = true

    service层

    1. /**
    2. * 根据ProductSpec和date查询
    3. * 查询条件: 地区,ProductSpec,date
    4. * @param renduiPriceDailyDTO
    5. * @return
    6. */
    7. Result getByProductSpecAndDate(RenduiPriceDailyDTO renduiPriceDailyDTO);
    8. }

    serviceImpl层

    1. @Override
    2. public Result getByProductSpecAndDate(RenduiPriceDailyDTO renduiPriceDailyDTO) {
    3. //1.获取该日期的每日统计结果
    4. long date = renduiPriceDailyDTO.getDate().atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli();
    5. Document daily = renduiPriceDailyManager.queryByProductSpec(renduiPriceDailyDTO.getSiteId(), renduiPriceDailyDTO.getProductSpec(), date);
    6. if(daily == null){
    7. return Result.error("当前没有报价,暂无统计");
    8. }
    9. //今开
    10. if (daily.get("openingPrice") != null) {
    11. daily.put("openingPrice",daily.get("openingPrice"));
    12. daily.put("openingPriceTax",daily.get("openingPriceTax"));
    13. }else {
    14. daily.put("openingPrice",0);
    15. daily.put("openingPriceTax",0);
    16. }
    17. //2.查询该日期前一天的每日统计结果
    18. long yesterday = renduiPriceDailyDTO.getDate().minusDays(1).atStartOfDay().toInstant(ZoneOffset.of("+8")).toEpochMilli();
    19. Document yesterdayDaily = renduiPriceDailyManager.queryByProductSpec(renduiPriceDailyDTO.getSiteId(), renduiPriceDailyDTO.getProductSpec(), yesterday);
    20. if(yesterdayDaily == null){
    21. daily.put("closePrice",0);
    22. daily.put("closePriceTax",0);
    23. daily.put("riseAndFall",0);
    24. daily.put("riseAndFallTax",0);
    25. daily.put("riseRange",0.00);
    26. daily.put("riseRangeTax",0.00);
    27. return Result.OK(daily);
    28. }
    29. //3.计算
    30. //涨跌 当前价 - 昨天均价
    31. Float riseAndFall = Float.valueOf(daily.get("lastprice").toString()) - Float.valueOf(yesterdayDaily.get("price").toString());
    32. Float riseAndFallTax = Float.valueOf(daily.get("lastpriceTax").toString()) - Float.valueOf(yesterdayDaily.get("priceTax").toString());
    33. //涨幅 涨跌 / 昨天均价
    34. Float riseRange = Double.valueOf(AccurateCalculation.div(riseAndFall,Double.valueOf(yesterdayDaily.get("price").toString()),2)).floatValue() * 100;
    35. Float riseRangeTax = Double.valueOf(AccurateCalculation.div(riseAndFallTax,Double.valueOf(yesterdayDaily.get("priceTax").toString()),2)).floatValue() * 100;
    36. daily.put("riseAndFall",riseAndFall);
    37. daily.put("riseAndFallTax",riseAndFallTax);
    38. daily.put("riseRange",riseRange);
    39. daily.put("riseRangeTax",riseRangeTax);
    40. //昨收
    41. daily.put("closePrice",yesterdayDaily.get("closePrice"));
    42. daily.put("closePriceTax",yesterdayDaily.get("closePriceTax"));
    43. return Result.OK(daily);
    44. }

     atStartOfDay()

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

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

    声明

    public LocalDateTime atStartOfDay() 

    返回值

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

    示例

    1. package com.yiibai;
    2. import java.time.LocalDate;
    3. import java.time.LocalDateTime;
    4. public class LocalDateDemo {
    5. public static void main(String[] args) {
    6. LocalDate date = LocalDate.parse("2017-02-03");
    7. System.out.println(date);
    8. LocalDateTime date1 = date.atStartOfDay();
    9. System.out.println(date1);
    10. }
    11. }

    结果

    1. 2017-02-03
    2. 2017-02-03T00:00

    toInstant()

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

    localDateTime 

    1. // 输出当前时间:2019-04-24T19:41:21.858
    2. LocalDateTime now = LocalDateTime.now();
    3. System.out.println(now);
    4. // 格式化时间,输出:2019年04月24日 19:49:25
    5. LocalDateTime time = LocalDateTime.now();
    6. String timeStr = time.format(DateTimeFormatter.ofPattern("yyyy年年MM月dd日 HH:mm:ss"));
    7. System.out.println(timeStr);
    8. // 当前时间增加20分钟
    9. LocalDateTime afterPlusTime = LocalDateTime.now().plus(20, ChronoUnit.MINUTES);
    10. System.out.println(afterPlusTime);
    11. // 创建开始和结束时间,并计算中间差值
    12. LocalDateTime start = LocalDateTime.of(1992, 8, 13, 0, 0, 0);
    13. LocalDateTime end = LocalDateTime.of(2019, 4, 25, 0, 0);
    14. long diff = LocalDateTimeUtils.betweenTwoTime(start, end, ChronoUnit.YEARS);
    15. System.out.println(diff+"年"); // 26
    16. boolean b = start.isAfter(end);
    17. System.out.println(b); // false
    18. //获取秒数 (东8区,也就是北京时间)
    19. Long second = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
    20. //获取毫秒数(东8区,也就是北京时间)
    21. Long milliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();

    instant

    1. Instant now = Instant.now(); // 2019-04-24T12:30:34.349Z
    2. long currentSecond = now.getEpochSecond(); // 秒数:1556109034
    3. long currentMilli = now.toEpochMilli(); // 毫秒数:1556109034349
    4. Instant afterPlusSecondInstant = now.plusSeconds(1000); // 秒数增加1000
    5. boolean b = now.isBefore(afterPlusSecondInstant); // 比较

    DateTimeFormatter

    1. // 输出:2019年04月24日 20:53:23
    2. DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    3. LocalDateTime time = LocalDateTime.now();
    4. String formatResult = time.format(df);
    5. // 输出:20190424
    6. LocalDateTime time = LocalDateTime.now();
    7. String formatResult = time.format(DateTimeFormatter.BASIC_ISO_DATE);
    1. ISO_DATE --> 2019-04-24
    2. ISO_LOCAL_DATE --> 2019-04-24
    3. ISO_LOCAL_TIME --> 20:59:48.42
    4. ISO_TIME --> 21:00:38.256
    5. ISO_LOCAL_DATE_TIME --> 2019-04-24T21:01:11.083
    6. .......

    格式转化

    1. Instant instant = Instant.now();
    2. Date date = Date.from(instant); // Instant转换为Date
    3. Instant instant2 = date.toInstant(); // Date转换为Instant
    4. // Date 与 LocalDateTime 的转换是通过 Instant 中间的转换来进行的
    5. Date date = new Date();
    6. LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(),ZoneId.systemDefault()); // Date转换为LocalDateTime
    7. LocalDateTime localDateTime = LocalDateTime.now();
    8. Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
    9. Date date = Date.from(instant); // LocalDateTime转换为Date

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

     

     controller层

    1. /**
    2. * 查询分钟维度价格统计(曲线图的数据接口)
    3. * @param
    4. * @return
    5. */
    6. @AutoLog(value = "/prices/statistics")
    7. @ApiOperation(value = "/prices/statistics", notes = "/prices/statistics")
    8. @GetMapping(value = "/prices/statistics")
    9. public Result statisticsPrice(@RequestParam(value = "productSpec") String productSpec, @RequestParam(value = "siteId")String siteId, @RequestParam(value = "from")String from, @RequestParam(value = "to")String to) {
    10. boolean fromBeforeTo = DateCommonUtil.getDateFromStr(from).before(DateCommonUtil.getDateFromStr(to));
    11. if(!fromBeforeTo){
    12. return Result.error("开始时间不能大于结束时间");
    13. }
    14. return service.statisticsPrice(productSpec, siteId, from, to);
    15. }

    service层

        Result statisticsPrice(String productSpec, String siteId, String from, String to);

    serviceImpl层

    1. @Override
    2. public Result statisticsPrice(String productSpec, String siteId, String from, String to) {
    3. long dateDiff = DateUtil.betweenDay(DateCommonUtil.getDateFromStr(from), DateCommonUtil.getDateFromStr(to), false);
    4. boolean isSameDay = DateUtil.isSameDay(DateCommonUtil.getDateFromStr(from), DateCommonUtil.getDateFromStr(to));
    5. if (dateDiff <= 0 && isSameDay) {
    6. return Result.OK(statisticsMinutely2(productSpec, siteId, from, to));
    7. } else {
    8. return Result.OK(statisticsDaily(productSpec, siteId, from, to, dateDiff));
    9. }
    10. }
    1. private Map statisticsMinutely2(String productSpec, String siteId, String from, String to) {
    2. Map map = new HashMap<>();
    3. map.put("rangeAvgPrice",0);
    4. long FIVE_MINUTES = 5 * 60000;
    5. long fromTime = DateCommonUtil.getTimeFromStr(from);
    6. long toTime = DateCommonUtil.getTimeFromStr(to);
    7. List minutely = renduiPriceMinutelyManager.queryByProductSpec(productSpec, siteId, fromTime, toTime);
    8. List results = new ArrayList<>();
    9. long minuteDiff = DateUtil.between(DateCommonUtil.getDateFromStr(from), DateCommonUtil.getDateFromStr(to), DateUnit.MINUTE);
    10. int window = (int) minuteDiff / 5;
    11. // 如果为空
    12. if (minutely.size() == 0) {
    13. PriceStatisticsVO lastPrice = getLastPrice(productSpec, siteId, fromTime);
    14. long t = fromTime;
    15. while (t <= toTime) {
    16. PriceStatisticsVO p = new PriceStatisticsVO();
    17. BeanUtil.copyProperties(lastPrice, p);
    18. p.setTimestamp(t);
    19. results.add(lastPrice);
    20. t += 5 * 60000;
    21. }
    22. map.put("list",results);
    23. return map;
    24. }
    25. PriceStatisticsVO firstPrice = new PriceStatisticsVO();
    26. BeanUtil.copyProperties(minutely.get(0), firstPrice);
    27. // 补充左边的数据
    28. long fistTime = firstPrice.getTimestamp();
    29. PriceStatisticsVO formerPrice = null;
    30. if (fistTime > fromTime) {
    31. PriceStatisticsVO latestPrice = getLastPrice(productSpec, siteId, fromTime);
    32. long t = fromTime;
    33. int i = 0;
    34. while (t < fistTime) {
    35. PriceStatisticsVO p = new PriceStatisticsVO();
    36. BeanUtil.copyProperties(latestPrice, p);
    37. p.setTimestamp(t);
    38. results.add(p);
    39. formerPrice = p;
    40. i ++;
    41. t += FIVE_MINUTES;
    42. }
    43. }
    44. // 补充中间数据
    45. for (int i = 0; i < minutely.size(); i ++) {
    46. Document m = minutely.get(i);
    47. PriceStatisticsVO price = new PriceStatisticsVO();
    48. BeanUtil.copyProperties(m, price);
    49. // 补充中间数据
    50. if (formerPrice != null && price.getTimestamp() - formerPrice.getTimestamp() > FIVE_MINUTES) {
    51. long t = formerPrice.getTimestamp() + FIVE_MINUTES;
    52. while ( t < price.getTimestamp()) {
    53. PriceStatisticsVO p = new PriceStatisticsVO();
    54. BeanUtil.copyProperties(formerPrice, p);
    55. p.setTimestamp(t);
    56. results.add(p);
    57. t += FIVE_MINUTES;
    58. }
    59. }
    60. results.add(price);
    61. formerPrice = price;
    62. }
    63. if (formerPrice != null && formerPrice.getTimestamp() < toTime) {
    64. long t = formerPrice.getTimestamp() + FIVE_MINUTES;
    65. while ( t < toTime) {
    66. PriceStatisticsVO p = new PriceStatisticsVO();
    67. BeanUtil.copyProperties(formerPrice, p);
    68. p.setTimestamp(t);
    69. results.add(p);
    70. t += FIVE_MINUTES;
    71. }
    72. }
    73. map.put("list",results);
    74. return map;
    75. }

    DateUtil.betweenDay()

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

    1. // 使用方式
    2. // cn.hutool.core.date.DateUtil.betweenDay(currentDate, targetTime, true);
    3. // 源码
    4. /**
    5. * 判断两个日期相差的天数
    6. *
    7. *
    8. * 有时候我们计算相差天数的时候需要忽略时分秒。
    9. * 比如:2016-02-01 23:59:59和2016-02-02 00:00:00相差一秒
    10. * 如果isReset为false相差天数为0。
    11. * 如果isReset为true相差天数将被计算为1
    12. *
  • *
  • * @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);
  • }
    1. private Map statisticsDaily(String productSpec, String siteId, String from, String to, long dateDiff) {
    2. List result = new ArrayList<>();
    3. //按天统计
    4. long fromTime = 0;
    5. List avgList = new ArrayList<>();
    6. Map map = new HashMap<>();
    7. for (int i = 0; i < dateDiff + 1; i++) {
    8. if (i == 0) {
    9. fromTime = DateCommonUtil.getTimeFromStr(from);
    10. }
    11. long toTime = DateCommonUtil.dayAfterInterval(DateCommonUtil.dateFromTimestamp(fromTime), 1).getTime();
    12. List daily = renduiPriceDailyManager.queryByProductSpec(productSpec, siteId, fromTime, toTime);
    13. Float avgPrice = daily.stream().map(document -> document.get("price") == null ? 0 : Float.parseFloat(document.get("price").toString()))
    14. .collect(Collectors.averagingDouble(price -> price)).floatValue();
    15. //当avgPrice > 0
    16. if(avgPrice.compareTo(new Float(0.00f)) == 1 ){
    17. avgList.add(avgPrice);
    18. }
    19. PriceStatisticsVO statisticsVO = new PriceStatisticsVO();
    20. statisticsVO.setProductSpec(productSpec);
    21. statisticsVO.setPrice(Float.valueOf("0.00"));
    22. statisticsVO.setPriceTax(Float.valueOf("0.00"));
    23. statisticsVO.setSatisticsTime(DateCommonUtil.strFromTimestamp(fromTime));
    24. if (CollectionUtil.isEmpty(daily)) {
    25. setDailyEmptyVal(productSpec, siteId, fromTime, i, statisticsVO);
    26. } else {
    27. BeanUtil.copyProperties(daily.get(daily.size() - 1), statisticsVO);
    28. }
    29. fromTime = toTime;
    30. result.add(statisticsVO);
    31. }
    32. for (int i = 0; i < result.size(); i++) {
    33. //将空值替换为上个周期的数据 ,因为前面保证了第一条数据一定有值所以不会出现数组越界问题
    34. if (result.get(i).getProductSpec() != null && result.get(i).getProductSpec().equals(EMPTY_MARK)) {
    35. PriceStatisticsVO statisticsVO = getNotEmptyOne(i - 1, result);
    36. String statisticTime = result.get(i).getSatisticsTime();
    37. BeanUtil.copyProperties(statisticsVO, result.get(i));
    38. result.get(i).setSatisticsTime(statisticTime);
    39. }
    40. }
    41. Float rangeAvgPrice = avgList.stream().collect(Collectors.averagingDouble(avg -> avg)).floatValue();
    42. map.put("rangeAvgPrice",rangeAvgPrice);
    43. map.put("list",result);
    44. return map;
    45. }


    三.大盘价曲线图

    controller层

    1. /**
    2. * 大盘价曲线图
    3. * 根据范围查询
    4. * 查询条件 productSpec,siteId,from,to
    5. * @param bigDishPriceDTO
    6. * @return
    7. */
    8. @PostMapping(value = "/bigDishPrice/rangeQueryBigDishPrice")
    9. public Result rangeQueryBigDishPrice(@RequestBody BigDishPriceDTO bigDishPriceDTO){
    10. if(StringUtils.isBlank(bigDishPriceDTO.getProductSpec())){
    11. return Result.error("查询条件不能为空!");
    12. }
    13. if(StringUtils.isBlank(bigDishPriceDTO.getSiteId())){
    14. return Result.error("地区不能为空!");
    15. }
    16. if(bigDishPriceDTO.getTo().compareTo(LocalDateTime.now().plusMinutes(1)) == 1){
    17. return Result.error("结束时间需小于当前时间!");
    18. }
    19. if(bigDishPriceDTO.getFrom().compareTo(bigDishPriceDTO.getTo()) >= 0){
    20. return Result.error("开始时间需小于结束时间!");
    21. }
    22. return bigDishPriceService.rangeQueryBigDishPrice(bigDishPriceDTO);
    23. }

    service层

    1. /**
    2. * 大盘价曲线图
    3. * 根据范围查询
    4. * 查询条件 productSpec,siteId,from,to
    5. * @param bigDishPriceDTO
    6. * @return
    7. */
    8. Result rangeQueryBigDishPrice(BigDishPriceDTO bigDishPriceDTO);

    serviceImpl层

    1. @Override
    2. public Result rangeQueryBigDishPrice(BigDishPriceDTO bigDishPriceDTO) {
    3. Duration duration = Duration.between(bigDishPriceDTO.getFrom(),bigDishPriceDTO.getTo());
    4. //当前查询范围大于1天
    5. if(duration.toDays() > 1){
    6. return Result.OK(replenishDayData(bigDishPriceDTO.getProductSpec(),bigDishPriceDTO.getSiteId(),bigDishPriceDTO.getFrom(),bigDishPriceDTO.getTo(),duration.toDays()));
    7. }
    8. //1.查询范围内大盘价
    9. long fromTime = bigDishPriceDTO.getFrom().toInstant(ZoneOffset.of("+8")).toEpochMilli();
    10. long toTime = bigDishPriceDTO.getTo().toInstant(ZoneOffset.of("+8")).toEpochMilli();
    11. List priceList = renduiPriceMinutelyManager.queryByProductSpec(bigDishPriceDTO.getProductSpec(), bigDishPriceDTO.getSiteId(), fromTime, toTime);
    12. List result = new ArrayList<>();
    13. // 如果为空取之前的最后一条大盘价
    14. if (priceList.size() == 0 || priceList == null) {
    15. Document doc = renduiPriceMinutelyManager.queryLastDataBy(bigDishPriceDTO.getProductSpec(), bigDishPriceDTO.getSiteId(), fromTime);
    16. if(doc == null){
    17. return Result.OK();
    18. }
    19. doc.put("price",Float.parseFloat(doc.get("price").toString()));
    20. doc.put("priceTax",Float.parseFloat(doc.get("priceTax").toString()));
    21. PriceStatisticsVO lastPrice = JSONObject.parseObject(JSON.toJSONString(doc), PriceStatisticsVO.class);
    22. long from = fromTime;
    23. while (from <= toTime) {
    24. PriceStatisticsVO p = new PriceStatisticsVO();
    25. BeanUtil.copyProperties(lastPrice, p);
    26. p.setTimestamp(from);
    27. p.setSatisticsTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(from),ZoneOffset.of("+8")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    28. result.add(p);
    29. from = from + 5 * 60 * 1000;
    30. }
    31. return Result.OK(result);
    32. }
    33. //2.补充左边的数据
    34. Document firstDoc = priceList.get(0);
    35. firstDoc.put("price",Float.parseFloat(firstDoc.get("price").toString()));
    36. firstDoc.put("priceTax",Float.parseFloat(firstDoc.get("priceTax").toString()));
    37. PriceStatisticsVO firstPrice = JSONObject.parseObject(JSON.toJSONString(firstDoc), PriceStatisticsVO.class);
    38. PriceStatisticsVO flagPrice = null;
    39. if(firstPrice.getTimestamp() > fromTime){
    40. Document doc = renduiPriceMinutelyManager.queryLastDataBy(bigDishPriceDTO.getProductSpec(), bigDishPriceDTO.getSiteId(), fromTime);
    41. //如果之前没有数据则
    42. PriceStatisticsVO lastPrice;
    43. if(doc == null){
    44. lastPrice = firstPrice;
    45. }else {
    46. doc.put("price",Float.parseFloat(doc.get("price").toString()));
    47. doc.put("priceTax",Float.parseFloat(doc.get("priceTax").toString()));
    48. lastPrice = JSONObject.parseObject(JSON.toJSONString(doc), PriceStatisticsVO.class);
    49. }
    50. long from = fromTime;
    51. while (from < firstPrice.getTimestamp()) {
    52. PriceStatisticsVO p = new PriceStatisticsVO();
    53. BeanUtil.copyProperties(lastPrice, p);
    54. p.setTimestamp(from);
    55. p.setSatisticsTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(from),ZoneOffset.of("+8")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    56. result.add(p);
    57. from = from + 5 * 60 * 1000;
    58. flagPrice = p;
    59. }
    60. }
    61. //3.补充中间的数据
    62. for (Document document : priceList) {
    63. document.put("price",Float.parseFloat(document.get("price").toString()));
    64. document.put("priceTax",Float.parseFloat(document.get("priceTax").toString()));
    65. PriceStatisticsVO price = JSONObject.parseObject(JSON.toJSONString(document), PriceStatisticsVO.class);
    66. if(flagPrice != null && price.getTimestamp() - flagPrice.getTimestamp() >= 5 * 60 * 1000){
    67. //+ 5 分钟
    68. long from = flagPrice.getTimestamp() + 5 * 60 * 1000;
    69. while (from < price.getTimestamp()){
    70. PriceStatisticsVO p = new PriceStatisticsVO();
    71. BeanUtil.copyProperties(price, p);
    72. p.setTimestamp(from);
    73. p.setSatisticsTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(from),ZoneOffset.of("+8")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    74. result.add(p);
    75. from = from + 5 * 60 * 1000;
    76. }
    77. }
    78. price.setSatisticsTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(price.getTimestamp()),ZoneOffset.of("+8")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    79. result.add(price);
    80. flagPrice = price;
    81. }
    82. //4.补充右边的数据
    83. if(flagPrice != null && flagPrice.getTimestamp() < toTime){
    84. //+ 5 分钟
    85. long from = flagPrice.getTimestamp() + 5 * 60 * 1000;
    86. while (from < toTime){
    87. PriceStatisticsVO p = new PriceStatisticsVO();
    88. BeanUtil.copyProperties(flagPrice, p);
    89. p.setTimestamp(from);
    90. p.setSatisticsTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(from),ZoneOffset.of("+8")).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    91. result.add(p);
    92. from = from + 5 * 60 * 1000;
    93. }
    94. }
    95. return Result.OK(result);
    96. }

    四.计算基差 根据范围

    controller层

    1. /**
    2. * 根据范围计算基差
    3. * 计算规则:市场价 - 大盘价
    4. * @param bigDishPriceDTO
    5. * @return
    6. */
    7. @PostMapping(value = "/bigDishPrice/rangeQueryBasicDiff")
    8. public Result rangeQueryBasicDiff(@RequestBody BigDishPriceDTO bigDishPriceDTO){
    9. if(StringUtils.isBlank(bigDishPriceDTO.getProductSpec()) || StringUtils.isBlank(bigDishPriceDTO.getBigDishProductSpec())){
    10. return Result.error("查询条件不能为空!");
    11. }
    12. if(StringUtils.isBlank(bigDishPriceDTO.getSiteId()) || StringUtils.isBlank(bigDishPriceDTO.getBigDishSiteId())){
    13. return Result.error("地区不能为空!");
    14. }
    15. if(bigDishPriceDTO.getTo().compareTo(LocalDateTime.now().plusMinutes(1)) == 1){
    16. return Result.error("结束时间需小于当前时间!");
    17. }
    18. if(bigDishPriceDTO.getFrom().compareTo(bigDishPriceDTO.getTo()) >= 0){
    19. return Result.error("开始时间需小于结束时间!");
    20. }
    21. return bigDishPriceService.rangeQueryBasicDiff(bigDishPriceDTO);
    22. }

    service层

    1. /**
    2. * 根据范围查询基差
    3. * 计算规则:市场价 - 大盘价
    4. * @param bigDishPriceDTO
    5. * @return
    6. */
    7. Result rangeQueryBasicDiff(BigDishPriceDTO bigDishPriceDTO);

    serviceImpl层

    1. @Override
    2. public Result rangeQueryBasicDiff(BigDishPriceDTO bigDishPriceDTO) {
    3. //计算公式 市场价 - 大盘价
    4. //1.存储结果
    5. List result = new ArrayList<>();
    6. Duration duration = Duration.between(bigDishPriceDTO.getFrom(),bigDishPriceDTO.getTo());
    7. //当前查询范围大于1天
    8. if(duration.toDays() > 1){
    9. //2.根据时间补齐市场价的数据
    10. List priceList = replenishDayData(bigDishPriceDTO.getProductSpec(), bigDishPriceDTO.getSiteId(), bigDishPriceDTO.getFrom(), bigDishPriceDTO.getTo(),duration.toDays());
    11. //3.根据时间补齐大盘价的数据
    12. List bigDishPriceList = replenishDayData(bigDishPriceDTO.getBigDishProductSpec(), bigDishPriceDTO.getBigDishSiteId(), bigDishPriceDTO.getFrom(), bigDishPriceDTO.getTo(),duration.toDays());
    13. Map bigDishPriceMap = bigDishPriceList.stream().collect(Collectors.toMap(priceStatisticsVO -> priceStatisticsVO.getSatisticsTime(), o -> o.getPrice()));
    14. //4.计算存储结果
    15. priceList.forEach(p -> {
    16. PriceStatisticsVO priceStatisticsVO = new PriceStatisticsVO();
    17. //基差 = 市场价 - 大盘价
    18. Float basicDiff = p.getPrice() - bigDishPriceMap.get(p.getSatisticsTime());
    19. basicDiff = new BigDecimal(basicDiff).setScale(2,RoundingMode.HALF_UP).floatValue();
    20. priceStatisticsVO.setPrice(basicDiff);
    21. priceStatisticsVO.setSatisticsTime(p.getSatisticsTime());
    22. priceStatisticsVO.setTimestamp(p.getTimestamp());
    23. result.add(priceStatisticsVO);
    24. });
    25. return Result.OK(result);
    26. }
    27. //2.根据时间补齐市场价的数据
    28. List priceList = replenishData(bigDishPriceDTO.getProductSpec(), bigDishPriceDTO.getSiteId(), bigDishPriceDTO.getFrom(), bigDishPriceDTO.getTo());
    29. if(priceList == null || priceList.size() == 0){
    30. return Result.OK();
    31. }
    32. //3.根据时间补齐大盘价的数据
    33. List bigDishPriceList = replenishData(bigDishPriceDTO.getBigDishProductSpec(), bigDishPriceDTO.getBigDishSiteId(), bigDishPriceDTO.getFrom(), bigDishPriceDTO.getTo());
    34. if(bigDishPriceList == null || bigDishPriceList.size() == 0){
    35. return Result.OK();
    36. }
    37. Map bigDishPriceMap = bigDishPriceList.stream().collect(Collectors.toMap(priceStatisticsVO -> priceStatisticsVO.getSatisticsTime(), o -> o.getPrice()));
    38. //4.计算存储结果
    39. priceList.forEach(p -> {
    40. PriceStatisticsVO priceStatisticsVO = new PriceStatisticsVO();
    41. //基差 = 市场价 - 大盘价
    42. Float basicDiff = p.getPrice() - bigDishPriceMap.get(p.getSatisticsTime());
    43. basicDiff = new BigDecimal(basicDiff).setScale(2,RoundingMode.HALF_UP).floatValue();
    44. priceStatisticsVO.setPrice(basicDiff);
    45. priceStatisticsVO.setSatisticsTime(p.getSatisticsTime());
    46. priceStatisticsVO.setTimestamp(p.getTimestamp());
    47. result.add(priceStatisticsVO);
    48. });
    49. return Result.OK(result);
    50. }

  • 相关阅读:
    Ceres 曲线拟合
    msys2 + MSVC(VS2019)编译ffmpeg6.0源码
    iOS WKWebView H5微信、支付宝支付跳转
    C语言实现三字棋
    【MultiOTP】在Linux上使用MultiOTP进行SSH登录
    MySql用户管理与引擎介绍
    【20字符串代码题】下标法,辅助数组法
    判断子序列算法
    单商户商城系统功能拆解03—店铺主页编辑
    解析vue.config.js文件
  • 原文地址:https://blog.csdn.net/weixin_44021708/article/details/126008690